Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin: (75 commits)
  Blackfin: update ftrace for latest toolchain
  Blackfin: fix elf_fpregset_t definition
  Blackfin: unify cache init functions
  Blackfin: swap clocksource ratings for gptimer/cycles
  Blackfin: update ftrace_push_return_trace() breakage
  Blackfin: update cm board resources
  Blackfin: cm-bf537u: split board from cm-bf537e
  Blackfin: bf538-ezkit: add SPI IRQ resources
  Blackfin: increase default async timings for parallel flashes
  Blackfin: add ICPLB coverage for async banks
  Blackfin: use KERN_ALERT in all kgdb_test output
  Blackfin: fix BF54x SPI CS resources
  Blackfin: fix typo in isram_write()
  Blackfin: bf537-stamp: add adp5588 gpio resources
  Blackfin: add some isram-driver self tests
  Blackfin: workaround anomaly 05000283
  Blackfin: fix spelling in a few comments
  Blackfin: use raw_smp_processor_id() in exception code
  Blackfin: remove useless duplicated assignment in gpio code
  Blackfin: Fix link errors with binutils 2.19 and GCC 4.3
  ...
diff --git a/Documentation/hwmon/pcf8591 b/Documentation/hwmon/pcf8591
index 5628fcf..e76a789 100644
--- a/Documentation/hwmon/pcf8591
+++ b/Documentation/hwmon/pcf8591
@@ -2,11 +2,11 @@
 =====================
 
 Supported chips:
-  * Philips PCF8591
+  * Philips/NXP PCF8591
     Prefix: 'pcf8591'
     Addresses scanned: I2C 0x48 - 0x4f
-    Datasheet: Publicly available at the Philips Semiconductor website
-               http://www.semiconductors.philips.com/pip/PCF8591P.html
+    Datasheet: Publicly available at the NXP website
+               http://www.nxp.com/pip/PCF8591_6.html
 
 Authors:
         Aurelien Jarno <aurelien@aurel32.net>
@@ -16,9 +16,10 @@
 
 Description
 -----------
+
 The PCF8591 is an 8-bit A/D and D/A converter (4 analog inputs and one
-analog output) for the I2C bus produced by Philips Semiconductors. It
-is designed to provide a byte I2C interface to up to 4 separate devices.
+analog output) for the I2C bus produced by Philips Semiconductors (now NXP).
+It is designed to provide a byte I2C interface to up to 4 separate devices.
 
 The PCF8591 has 4 analog inputs programmable as single-ended or
 differential inputs :
@@ -58,8 +59,8 @@
 -------------------------------------
 
 ! Be careful !
-The PCF8591 is plainly impossible to detect ! Stupid chip.
-So every chip with address in the interval [48..4f] is
+The PCF8591 is plainly impossible to detect! Stupid chip.
+So every chip with address in the interval [0x48..0x4f] is
 detected as PCF8591. If you have other chips in this address
 range, the workaround is to load this module after the one
 for your others chips.
@@ -67,19 +68,20 @@
 On detection (i.e. insmod, modprobe et al.), directories are being
 created for each detected PCF8591:
 
-/sys/bus/devices/<0>-<1>/
+/sys/bus/i2c/devices/<0>-<1>/
 where <0> is the bus the chip was detected on (e. g. i2c-0)
 and <1> the chip address ([48..4f])
 
 Inside these directories, there are such files:
-in0, in1, in2, in3, out0_enable, out0_output, name
+in0_input, in1_input, in2_input, in3_input, out0_enable, out0_output, name
 
 Name contains chip name.
 
-The in0, in1, in2 and in3 files are RO. Reading gives the value of the
-corresponding channel. Depending on the current analog inputs configuration,
-files in2 and/or in3 do not exist. Values range are from 0 to 255 for single
-ended inputs and -128 to +127 for differential inputs (8-bit ADC).
+The in0_input, in1_input, in2_input and in3_input files are RO. Reading gives
+the value of the corresponding channel. Depending on the current analog inputs
+configuration, files in2_input and in3_input may not exist. Values range
+from 0 to 255 for single ended inputs and -128 to +127 for differential inputs
+(8-bit ADC).
 
 The out0_enable file is RW. Reading gives "1" for analog output enabled and
 "0" for analog output disabled. Writing accepts "0" and "1" accordingly.
diff --git a/Documentation/hwmon/tmp421 b/Documentation/hwmon/tmp421
new file mode 100644
index 0000000..0cf07f82
--- /dev/null
+++ b/Documentation/hwmon/tmp421
@@ -0,0 +1,36 @@
+Kernel driver tmp421
+====================
+
+Supported chips:
+  * Texas Instruments TMP421
+    Prefix: 'tmp421'
+    Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+    Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
+  * Texas Instruments TMP422
+    Prefix: 'tmp422'
+    Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+    Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
+  * Texas Instruments TMP423
+    Prefix: 'tmp423'
+    Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+    Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
+
+Authors:
+	Andre Prendel <andre.prendel@gmx.de>
+
+Description
+-----------
+
+This driver implements support for Texas Instruments TMP421, TMP422
+and TMP423 temperature sensor chips. These chips implement one local
+and up to one (TMP421), up to two (TMP422) or up to three (TMP423)
+remote sensors. Temperature is measured in degrees Celsius. The chips
+are wired over I2C/SMBus and specified over a temperature range of -40
+to +125 degrees Celsius. Resolution for both the local and remote
+channels is 0.0625 degree C.
+
+The chips support only temperature measurement. The driver exports
+the temperature values via the following sysfs files:
+
+temp[1-4]_input
+temp[2-4]_fault
diff --git a/MAINTAINERS b/MAINTAINERS
index 9117b65..c5f312b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -931,6 +931,12 @@
 S:	Maintained
 F:	drivers/net/wireless/ath/ar9170/
 
+ATK0110 HWMON DRIVER
+M:	Luca Tettamanti <kronos.it@gmail.com>
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+F:	drivers/hwmon/asus_atk0110.c
+
 ATI_REMOTE2 DRIVER
 M:	Ville Syrjala <syrjala@sci.fi>
 S:	Maintained
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index e6c5c3d..23f846d 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -34,7 +34,6 @@
 #include <asm/mca_asm.h>
 #include <linux/init.h>
 #include <linux/linkage.h>
-#include "head.h"
 
 #ifdef CONFIG_HOTPLUG_CPU
 #define SAL_PSR_BITS_TO_SET				\
diff --git a/arch/ia64/kernel/head.h b/arch/ia64/kernel/head.h
deleted file mode 100644
index 2e2ac68..0000000
--- a/arch/ia64/kernel/head.h
+++ /dev/null
@@ -1 +0,0 @@
-extern void console_print(const char *s);
diff --git a/arch/m68k/include/asm/checksum.h b/arch/m68k/include/asm/checksum.h
index 1cf5447..ec51448 100644
--- a/arch/m68k/include/asm/checksum.h
+++ b/arch/m68k/include/asm/checksum.h
@@ -1,5 +1,170 @@
-#ifdef __uClinux__
-#include "checksum_no.h"
+#ifndef _M68K_CHECKSUM_H
+#define _M68K_CHECKSUM_H
+
+#include <linux/in6.h>
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+__wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+extern __wsum csum_partial_copy_from_user(const void __user *src,
+						void *dst,
+						int len, __wsum sum,
+						int *csum_err);
+
+extern __wsum csum_partial_copy_nocheck(const void *src,
+					      void *dst, int len,
+					      __wsum sum);
+
+
+#ifdef CONFIG_COLDFIRE
+
+/*
+ *	The ColdFire cores don't support all the 68k instructions used
+ *	in the optimized checksum code below. So it reverts back to using
+ *	more standard C coded checksums. The fast checksum code is
+ *	significantly larger than the optimized version, so it is not
+ *	inlined here.
+ */
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
+
+static inline __sum16 csum_fold(__wsum sum)
+{
+	unsigned int tmp = (__force u32)sum;
+
+	tmp = (tmp & 0xffff) + (tmp >> 16);
+	tmp = (tmp & 0xffff) + (tmp >> 16);
+
+	return (__force __sum16)~tmp;
+}
+
 #else
-#include "checksum_mm.h"
-#endif
+
+/*
+ *	This is a version of ip_fast_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	unsigned int sum = 0;
+	unsigned long tmp;
+
+	__asm__ ("subqw #1,%2\n"
+		 "1:\t"
+		 "movel %1@+,%3\n\t"
+		 "addxl %3,%0\n\t"
+		 "dbra  %2,1b\n\t"
+		 "movel %0,%3\n\t"
+		 "swap  %3\n\t"
+		 "addxw %3,%0\n\t"
+		 "clrw  %3\n\t"
+		 "addxw %3,%0\n\t"
+		 : "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp)
+		 : "0" (sum), "1" (iph), "2" (ihl)
+		 : "memory");
+	return (__force __sum16)~sum;
+}
+
+static inline __sum16 csum_fold(__wsum sum)
+{
+	unsigned int tmp = (__force u32)sum;
+
+	__asm__("swap %1\n\t"
+		"addw %1, %0\n\t"
+		"clrw %1\n\t"
+		"addxw %1, %0"
+		: "=&d" (sum), "=&d" (tmp)
+		: "0" (sum), "1" (tmp));
+
+	return (__force __sum16)~sum;
+}
+
+#endif /* CONFIG_COLDFIRE */
+
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+		  unsigned short proto, __wsum sum)
+{
+	__asm__ ("addl  %2,%0\n\t"
+		 "addxl %3,%0\n\t"
+		 "addxl %4,%0\n\t"
+		 "clrl %1\n\t"
+		 "addxl %1,%0"
+		 : "=&d" (sum), "=d" (saddr)
+		 : "g" (daddr), "1" (saddr), "d" (len + proto),
+		   "0" (sum));
+	return sum;
+}
+
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
+		  unsigned short proto, __wsum sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+	return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ __sum16
+csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
+		__u32 len, unsigned short proto, __wsum sum)
+{
+	register unsigned long tmp;
+	__asm__("addl %2@,%0\n\t"
+		"movel %2@(4),%1\n\t"
+		"addxl %1,%0\n\t"
+		"movel %2@(8),%1\n\t"
+		"addxl %1,%0\n\t"
+		"movel %2@(12),%1\n\t"
+		"addxl %1,%0\n\t"
+		"movel %3@,%1\n\t"
+		"addxl %1,%0\n\t"
+		"movel %3@(4),%1\n\t"
+		"addxl %1,%0\n\t"
+		"movel %3@(8),%1\n\t"
+		"addxl %1,%0\n\t"
+		"movel %3@(12),%1\n\t"
+		"addxl %1,%0\n\t"
+		"addxl %4,%0\n\t"
+		"clrl %1\n\t"
+		"addxl %1,%0"
+		: "=&d" (sum), "=&d" (tmp)
+		: "a" (saddr), "a" (daddr), "d" (len + proto),
+		  "0" (sum));
+
+	return csum_fold(sum);
+}
+
+#endif /* _M68K_CHECKSUM_H */
diff --git a/arch/m68k/include/asm/checksum_mm.h b/arch/m68k/include/asm/checksum_mm.h
deleted file mode 100644
index 494f9ae..0000000
--- a/arch/m68k/include/asm/checksum_mm.h
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef _M68K_CHECKSUM_H
-#define _M68K_CHECKSUM_H
-
-#include <linux/in6.h>
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-extern __wsum csum_partial_copy_from_user(const void __user *src,
-						void *dst,
-						int len, __wsum sum,
-						int *csum_err);
-
-extern __wsum csum_partial_copy_nocheck(const void *src,
-					      void *dst, int len,
-					      __wsum sum);
-
-/*
- *	This is a version of ip_compute_csum() optimized for IP headers,
- *	which always checksum on 4 octet boundaries.
- *
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	unsigned int sum = 0;
-	unsigned long tmp;
-
-	__asm__ ("subqw #1,%2\n"
-		 "1:\t"
-		 "movel %1@+,%3\n\t"
-		 "addxl %3,%0\n\t"
-		 "dbra  %2,1b\n\t"
-		 "movel %0,%3\n\t"
-		 "swap  %3\n\t"
-		 "addxw %3,%0\n\t"
-		 "clrw  %3\n\t"
-		 "addxw %3,%0\n\t"
-		 : "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp)
-		 : "0" (sum), "1" (iph), "2" (ihl)
-		 : "memory");
-	return (__force __sum16)~sum;
-}
-
-/*
- *	Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
-	unsigned int tmp = (__force u32)sum;
-	__asm__("swap %1\n\t"
-		"addw %1, %0\n\t"
-		"clrw %1\n\t"
-		"addxw %1, %0"
-		: "=&d" (sum), "=&d" (tmp)
-		: "0" (sum), "1" (tmp));
-	return (__force __sum16)~sum;
-}
-
-
-static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
-		  unsigned short proto, __wsum sum)
-{
-	__asm__ ("addl  %2,%0\n\t"
-		 "addxl %3,%0\n\t"
-		 "addxl %4,%0\n\t"
-		 "clrl %1\n\t"
-		 "addxl %1,%0"
-		 : "=&d" (sum), "=d" (saddr)
-		 : "g" (daddr), "1" (saddr), "d" (len + proto),
-		   "0" (sum));
-	return sum;
-}
-
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16
-csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
-		  unsigned short proto, __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
-static inline __sum16 ip_compute_csum(const void *buff, int len)
-{
-	return csum_fold (csum_partial(buff, len, 0));
-}
-
-#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ __sum16
-csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
-		__u32 len, unsigned short proto, __wsum sum)
-{
-	register unsigned long tmp;
-	__asm__("addl %2@,%0\n\t"
-		"movel %2@(4),%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %2@(8),%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %2@(12),%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %3@,%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %3@(4),%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %3@(8),%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %3@(12),%1\n\t"
-		"addxl %1,%0\n\t"
-		"addxl %4,%0\n\t"
-		"clrl %1\n\t"
-		"addxl %1,%0"
-		: "=&d" (sum), "=&d" (tmp)
-		: "a" (saddr), "a" (daddr), "d" (len + proto),
-		  "0" (sum));
-
-	return csum_fold(sum);
-}
-
-#endif /* _M68K_CHECKSUM_H */
diff --git a/arch/m68k/include/asm/checksum_no.h b/arch/m68k/include/asm/checksum_no.h
deleted file mode 100644
index 8188348..0000000
--- a/arch/m68k/include/asm/checksum_no.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef _M68K_CHECKSUM_H
-#define _M68K_CHECKSUM_H
-
-#include <linux/in6.h>
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
-	int len, __wsum sum);
-
-
-/*
- * the same as csum_partial_copy, but copies from user space.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-extern __wsum csum_partial_copy_from_user(const void __user *src,
-	void *dst, int len, __wsum sum, int *csum_err);
-
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-/*
- *	Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
-	unsigned int tmp = (__force u32)sum;
-#ifdef CONFIG_COLDFIRE
-	tmp = (tmp & 0xffff) + (tmp >> 16);
-	tmp = (tmp & 0xffff) + (tmp >> 16);
-	return (__force __sum16)~tmp;
-#else
-	__asm__("swap %1\n\t"
-		"addw %1, %0\n\t"
-		"clrw %1\n\t"
-		"addxw %1, %0"
-		: "=&d" (sum), "=&d" (tmp)
-		: "0" (sum), "1" (sum));
-	return (__force __sum16)~sum;
-#endif
-}
-
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-
-static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
-		  unsigned short proto, __wsum sum)
-{
-	__asm__ ("addl  %1,%0\n\t"
-		 "addxl %4,%0\n\t"
-		 "addxl %5,%0\n\t"
-		 "clrl %1\n\t"
-		 "addxl %1,%0"
-		 : "=&d" (sum), "=&d" (saddr)
-		 : "0" (daddr), "1" (saddr), "d" (len + proto),
-		   "d"(sum));
-	return sum;
-}
-
-static inline __sum16
-csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
-		  unsigned short proto, __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ __sum16
-csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
-		__u32 len, unsigned short proto, __wsum sum)
-{
-	register unsigned long tmp;
-	__asm__("addl %2@,%0\n\t"
-		"movel %2@(4),%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %2@(8),%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %2@(12),%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %3@,%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %3@(4),%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %3@(8),%1\n\t"
-		"addxl %1,%0\n\t"
-		"movel %3@(12),%1\n\t"
-		"addxl %1,%0\n\t"
-		"addxl %4,%0\n\t"
-		"clrl %1\n\t"
-		"addxl %1,%0"
-		: "=&d" (sum), "=&d" (tmp)
-		: "a" (saddr), "a" (daddr), "d" (len + proto),
-		  "0" (sum));
-
-	return csum_fold(sum);
-}
-
-#endif /* _M68K_CHECKSUM_H */
diff --git a/arch/m68k/include/asm/dma.h b/arch/m68k/include/asm/dma.h
index b82e660..6fbdfe8 100644
--- a/arch/m68k/include/asm/dma.h
+++ b/arch/m68k/include/asm/dma.h
@@ -1,5 +1,491 @@
-#ifdef __uClinux__
-#include "dma_no.h"
+#ifndef _M68K_DMA_H
+#define _M68K_DMA_H 1
+
+#ifdef CONFIG_COLDFIRE
+/*
+ * ColdFire DMA Model:
+ *   ColdFire DMA supports two forms of DMA: Single and Dual address. Single
+ * address mode emits a source address, and expects that the device will either
+ * pick up the data (DMA READ) or source data (DMA WRITE). This implies that
+ * the device will place data on the correct byte(s) of the data bus, as the
+ * memory transactions are always 32 bits. This implies that only 32 bit
+ * devices will find single mode transfers useful. Dual address DMA mode
+ * performs two cycles: source read and destination write. ColdFire will
+ * align the data so that the device will always get the correct bytes, thus
+ * is useful for 8 and 16 bit devices. This is the mode that is supported
+ * below.
+ *
+ * AUG/22/2000 : added support for 32-bit Dual-Address-Mode (K) 2000
+ *               Oliver Kamphenkel (O.Kamphenkel@tu-bs.de)
+ *
+ * AUG/25/2000 : addad support for 8, 16 and 32-bit Single-Address-Mode (K)2000
+ *               Oliver Kamphenkel (O.Kamphenkel@tu-bs.de)
+ *
+ * APR/18/2002 : added proper support for MCF5272 DMA controller.
+ *               Arthur Shipkowski (art@videon-central.com)
+ */
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfdma.h>
+
+/*
+ * Set number of channels of DMA on ColdFire for different implementations.
+ */
+#if defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407) || \
+	defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#define MAX_M68K_DMA_CHANNELS 4
+#elif defined(CONFIG_M5272)
+#define MAX_M68K_DMA_CHANNELS 1
+#elif defined(CONFIG_M532x)
+#define MAX_M68K_DMA_CHANNELS 0
 #else
-#include "dma_mm.h"
+#define MAX_M68K_DMA_CHANNELS 2
 #endif
+
+extern unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS];
+extern unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
+
+#if !defined(CONFIG_M5272)
+#define DMA_MODE_WRITE_BIT  0x01  /* Memory/IO to IO/Memory select */
+#define DMA_MODE_WORD_BIT   0x02  /* 8 or 16 bit transfers */
+#define DMA_MODE_LONG_BIT   0x04  /* or 32 bit transfers */
+#define DMA_MODE_SINGLE_BIT 0x08  /* single-address-mode */
+
+/* I/O to memory, 8 bits, mode */
+#define DMA_MODE_READ	            0
+/* memory to I/O, 8 bits, mode */
+#define DMA_MODE_WRITE	            1
+/* I/O to memory, 16 bits, mode */
+#define DMA_MODE_READ_WORD          2
+/* memory to I/O, 16 bits, mode */
+#define DMA_MODE_WRITE_WORD         3
+/* I/O to memory, 32 bits, mode */
+#define DMA_MODE_READ_LONG          4
+/* memory to I/O, 32 bits, mode */
+#define DMA_MODE_WRITE_LONG         5
+/* I/O to memory, 8 bits, single-address-mode */
+#define DMA_MODE_READ_SINGLE        8
+/* memory to I/O, 8 bits, single-address-mode */
+#define DMA_MODE_WRITE_SINGLE       9
+/* I/O to memory, 16 bits, single-address-mode */
+#define DMA_MODE_READ_WORD_SINGLE  10
+/* memory to I/O, 16 bits, single-address-mode */
+#define DMA_MODE_WRITE_WORD_SINGLE 11
+/* I/O to memory, 32 bits, single-address-mode */
+#define DMA_MODE_READ_LONG_SINGLE  12
+/* memory to I/O, 32 bits, single-address-mode */
+#define DMA_MODE_WRITE_LONG_SINGLE 13
+
+#else /* CONFIG_M5272 is defined */
+
+/* Source static-address mode */
+#define DMA_MODE_SRC_SA_BIT 0x01
+/* Two bits to select between all four modes */
+#define DMA_MODE_SSIZE_MASK 0x06
+/* Offset to shift bits in */
+#define DMA_MODE_SSIZE_OFF  0x01
+/* Destination static-address mode */
+#define DMA_MODE_DES_SA_BIT 0x10
+/* Two bits to select between all four modes */
+#define DMA_MODE_DSIZE_MASK 0x60
+/* Offset to shift bits in */
+#define DMA_MODE_DSIZE_OFF  0x05
+/* Size modifiers */
+#define DMA_MODE_SIZE_LONG  0x00
+#define DMA_MODE_SIZE_BYTE  0x01
+#define DMA_MODE_SIZE_WORD  0x02
+#define DMA_MODE_SIZE_LINE  0x03
+
+/*
+ * Aliases to help speed quick ports; these may be suboptimal, however. They
+ * do not include the SINGLE mode modifiers since the MCF5272 does not have a
+ * mode where the device is in control of its addressing.
+ */
+
+/* I/O to memory, 8 bits, mode */
+#define DMA_MODE_READ	              ((DMA_MODE_SIZE_BYTE << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_BYTE << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
+/* memory to I/O, 8 bits, mode */
+#define DMA_MODE_WRITE	            ((DMA_MODE_SIZE_BYTE << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_BYTE << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
+/* I/O to memory, 16 bits, mode */
+#define DMA_MODE_READ_WORD	        ((DMA_MODE_SIZE_WORD << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_WORD << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
+/* memory to I/O, 16 bits, mode */
+#define DMA_MODE_WRITE_WORD         ((DMA_MODE_SIZE_WORD << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_WORD << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
+/* I/O to memory, 32 bits, mode */
+#define DMA_MODE_READ_LONG	        ((DMA_MODE_SIZE_LONG << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_LONG << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
+/* memory to I/O, 32 bits, mode */
+#define DMA_MODE_WRITE_LONG         ((DMA_MODE_SIZE_LONG << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_LONG << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
+
+#endif /* !defined(CONFIG_M5272) */
+
+#if !defined(CONFIG_M5272)
+/* enable/disable a specific DMA channel */
+static __inline__ void enable_dma(unsigned int dmanr)
+{
+  volatile unsigned short *dmawp;
+
+#ifdef DMA_DEBUG
+  printk("enable_dma(dmanr=%d)\n", dmanr);
+#endif
+
+  dmawp = (unsigned short *) dma_base_addr[dmanr];
+  dmawp[MCFDMA_DCR] |= MCFDMA_DCR_EEXT;
+}
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+  volatile unsigned short *dmawp;
+  volatile unsigned char  *dmapb;
+
+#ifdef DMA_DEBUG
+  printk("disable_dma(dmanr=%d)\n", dmanr);
+#endif
+
+  dmawp = (unsigned short *) dma_base_addr[dmanr];
+  dmapb = (unsigned char *) dma_base_addr[dmanr];
+
+  /* Turn off external requests, and stop any DMA in progress */
+  dmawp[MCFDMA_DCR] &= ~MCFDMA_DCR_EEXT;
+  dmapb[MCFDMA_DSR] = MCFDMA_DSR_DONE;
+}
+
+/*
+ * Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while interrupts are disabled! ---
+ *
+ * This is a NOP for ColdFire. Provide a stub for compatibility.
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+}
+
+/* set mode (above) for a specific DMA channel */
+static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+{
+
+  volatile unsigned char  *dmabp;
+  volatile unsigned short *dmawp;
+
+#ifdef DMA_DEBUG
+  printk("set_dma_mode(dmanr=%d,mode=%d)\n", dmanr, mode);
+#endif
+
+  dmabp = (unsigned char *) dma_base_addr[dmanr];
+  dmawp = (unsigned short *) dma_base_addr[dmanr];
+
+  /* Clear config errors */
+  dmabp[MCFDMA_DSR] = MCFDMA_DSR_DONE;
+
+  /* Set command register */
+  dmawp[MCFDMA_DCR] =
+    MCFDMA_DCR_INT |         /* Enable completion irq */
+    MCFDMA_DCR_CS |          /* Force one xfer per request */
+    MCFDMA_DCR_AA |          /* Enable auto alignment */
+    /* single-address-mode */
+    ((mode & DMA_MODE_SINGLE_BIT) ? MCFDMA_DCR_SAA : 0) |
+    /* sets s_rw (-> r/w) high if Memory to I/0 */
+    ((mode & DMA_MODE_WRITE_BIT) ? MCFDMA_DCR_S_RW : 0) |
+    /* Memory to I/O or I/O to Memory */
+    ((mode & DMA_MODE_WRITE_BIT) ? MCFDMA_DCR_SINC : MCFDMA_DCR_DINC) |
+    /* 32 bit, 16 bit or 8 bit transfers */
+    ((mode & DMA_MODE_WORD_BIT)  ? MCFDMA_DCR_SSIZE_WORD :
+     ((mode & DMA_MODE_LONG_BIT) ? MCFDMA_DCR_SSIZE_LONG :
+                                   MCFDMA_DCR_SSIZE_BYTE)) |
+    ((mode & DMA_MODE_WORD_BIT)  ? MCFDMA_DCR_DSIZE_WORD :
+     ((mode & DMA_MODE_LONG_BIT) ? MCFDMA_DCR_DSIZE_LONG :
+                                   MCFDMA_DCR_DSIZE_BYTE));
+
+#ifdef DEBUG_DMA
+  printk("%s(%d): dmanr=%d DSR[%x]=%x DCR[%x]=%x\n", __FILE__, __LINE__,
+         dmanr, (int) &dmabp[MCFDMA_DSR], dmabp[MCFDMA_DSR],
+	 (int) &dmawp[MCFDMA_DCR], dmawp[MCFDMA_DCR]);
+#endif
+}
+
+/* Set transfer address for specific DMA channel */
+static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+  volatile unsigned short *dmawp;
+  volatile unsigned int   *dmalp;
+
+#ifdef DMA_DEBUG
+  printk("set_dma_addr(dmanr=%d,a=%x)\n", dmanr, a);
+#endif
+
+  dmawp = (unsigned short *) dma_base_addr[dmanr];
+  dmalp = (unsigned int *) dma_base_addr[dmanr];
+
+  /* Determine which address registers are used for memory/device accesses */
+  if (dmawp[MCFDMA_DCR] & MCFDMA_DCR_SINC) {
+    /* Source incrementing, must be memory */
+    dmalp[MCFDMA_SAR] = a;
+    /* Set dest address, must be device */
+    dmalp[MCFDMA_DAR] = dma_device_address[dmanr];
+  } else {
+    /* Destination incrementing, must be memory */
+    dmalp[MCFDMA_DAR] = a;
+    /* Set source address, must be device */
+    dmalp[MCFDMA_SAR] = dma_device_address[dmanr];
+  }
+
+#ifdef DEBUG_DMA
+  printk("%s(%d): dmanr=%d DCR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n",
+	__FILE__, __LINE__, dmanr, (int) &dmawp[MCFDMA_DCR], dmawp[MCFDMA_DCR],
+	(int) &dmalp[MCFDMA_SAR], dmalp[MCFDMA_SAR],
+	(int) &dmalp[MCFDMA_DAR], dmalp[MCFDMA_DAR]);
+#endif
+}
+
+/*
+ * Specific for Coldfire - sets device address.
+ * Should be called after the mode set call, and before set DMA address.
+ */
+static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a)
+{
+#ifdef DMA_DEBUG
+  printk("set_dma_device_addr(dmanr=%d,a=%x)\n", dmanr, a);
+#endif
+
+  dma_device_address[dmanr] = a;
+}
+
+/*
+ * NOTE 2: "count" represents _bytes_.
+ */
+static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+  volatile unsigned short *dmawp;
+
+#ifdef DMA_DEBUG
+  printk("set_dma_count(dmanr=%d,count=%d)\n", dmanr, count);
+#endif
+
+  dmawp = (unsigned short *) dma_base_addr[dmanr];
+  dmawp[MCFDMA_BCR] = (unsigned short)count;
+}
+
+/*
+ * Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ */
+static __inline__ int get_dma_residue(unsigned int dmanr)
+{
+  volatile unsigned short *dmawp;
+  unsigned short count;
+
+#ifdef DMA_DEBUG
+  printk("get_dma_residue(dmanr=%d)\n", dmanr);
+#endif
+
+  dmawp = (unsigned short *) dma_base_addr[dmanr];
+  count = dmawp[MCFDMA_BCR];
+  return((int) count);
+}
+#else /* CONFIG_M5272 is defined */
+
+/*
+ * The MCF5272 DMA controller is very different than the controller defined above
+ * in terms of register mapping.  For instance, with the exception of the 16-bit
+ * interrupt register (IRQ#85, for reference), all of the registers are 32-bit.
+ *
+ * The big difference, however, is the lack of device-requested DMA.  All modes
+ * are dual address transfer, and there is no 'device' setup or direction bit.
+ * You can DMA between a device and memory, between memory and memory, or even between
+ * two devices directly, with any combination of incrementing and non-incrementing
+ * addresses you choose.  This puts a crimp in distinguishing between the 'device
+ * address' set up by set_dma_device_addr.
+ *
+ * Therefore, there are two options.  One is to use set_dma_addr and set_dma_device_addr,
+ * which will act exactly as above in -- it will look to see if the source is set to
+ * autoincrement, and if so it will make the source use the set_dma_addr value and the
+ * destination the set_dma_device_addr value.  Otherwise the source will be set to the
+ * set_dma_device_addr value and the destination will get the set_dma_addr value.
+ *
+ * The other is to use the provided set_dma_src_addr and set_dma_dest_addr functions
+ * and make it explicit.  Depending on what you're doing, one of these two should work
+ * for you, but don't mix them in the same transfer setup.
+ */
+
+/* enable/disable a specific DMA channel */
+static __inline__ void enable_dma(unsigned int dmanr)
+{
+  volatile unsigned int  *dmalp;
+
+#ifdef DMA_DEBUG
+  printk("enable_dma(dmanr=%d)\n", dmanr);
+#endif
+
+  dmalp = (unsigned int *) dma_base_addr[dmanr];
+  dmalp[MCFDMA_DMR] |= MCFDMA_DMR_EN;
+}
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+  volatile unsigned int   *dmalp;
+
+#ifdef DMA_DEBUG
+  printk("disable_dma(dmanr=%d)\n", dmanr);
+#endif
+
+  dmalp = (unsigned int *) dma_base_addr[dmanr];
+
+  /* Turn off external requests, and stop any DMA in progress */
+  dmalp[MCFDMA_DMR] &= ~MCFDMA_DMR_EN;
+  dmalp[MCFDMA_DMR] |= MCFDMA_DMR_RESET;
+}
+
+/*
+ * Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while interrupts are disabled! ---
+ *
+ * This is a NOP for ColdFire. Provide a stub for compatibility.
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+}
+
+/* set mode (above) for a specific DMA channel */
+static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+{
+
+  volatile unsigned int   *dmalp;
+  volatile unsigned short *dmawp;
+
+#ifdef DMA_DEBUG
+  printk("set_dma_mode(dmanr=%d,mode=%d)\n", dmanr, mode);
+#endif
+  dmalp = (unsigned int *) dma_base_addr[dmanr];
+  dmawp = (unsigned short *) dma_base_addr[dmanr];
+
+  /* Clear config errors */
+  dmalp[MCFDMA_DMR] |= MCFDMA_DMR_RESET;
+
+  /* Set command register */
+  dmalp[MCFDMA_DMR] =
+    MCFDMA_DMR_RQM_DUAL |         /* Mandatory Request Mode setting */
+    MCFDMA_DMR_DSTT_SD  |         /* Set up addressing types; set to supervisor-data. */
+    MCFDMA_DMR_SRCT_SD  |         /* Set up addressing types; set to supervisor-data. */
+    /* source static-address-mode */
+    ((mode & DMA_MODE_SRC_SA_BIT) ? MCFDMA_DMR_SRCM_SA : MCFDMA_DMR_SRCM_IA) |
+    /* dest static-address-mode */
+    ((mode & DMA_MODE_DES_SA_BIT) ? MCFDMA_DMR_DSTM_SA : MCFDMA_DMR_DSTM_IA) |
+    /* burst, 32 bit, 16 bit or 8 bit transfers are separately configurable on the MCF5272 */
+    (((mode & DMA_MODE_SSIZE_MASK) >> DMA_MODE_SSIZE_OFF) << MCFDMA_DMR_DSTS_OFF) |
+    (((mode & DMA_MODE_SSIZE_MASK) >> DMA_MODE_SSIZE_OFF) << MCFDMA_DMR_SRCS_OFF);
+
+  dmawp[MCFDMA_DIR] |= MCFDMA_DIR_ASCEN;   /* Enable completion interrupts */
+
+#ifdef DEBUG_DMA
+  printk("%s(%d): dmanr=%d DMR[%x]=%x DIR[%x]=%x\n", __FILE__, __LINE__,
+         dmanr, (int) &dmalp[MCFDMA_DMR], dmabp[MCFDMA_DMR],
+	 (int) &dmawp[MCFDMA_DIR], dmawp[MCFDMA_DIR]);
+#endif
+}
+
+/* Set transfer address for specific DMA channel */
+static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+  volatile unsigned int   *dmalp;
+
+#ifdef DMA_DEBUG
+  printk("set_dma_addr(dmanr=%d,a=%x)\n", dmanr, a);
+#endif
+
+  dmalp = (unsigned int *) dma_base_addr[dmanr];
+
+  /* Determine which address registers are used for memory/device accesses */
+  if (dmalp[MCFDMA_DMR] & MCFDMA_DMR_SRCM) {
+    /* Source incrementing, must be memory */
+    dmalp[MCFDMA_DSAR] = a;
+    /* Set dest address, must be device */
+    dmalp[MCFDMA_DDAR] = dma_device_address[dmanr];
+  } else {
+    /* Destination incrementing, must be memory */
+    dmalp[MCFDMA_DDAR] = a;
+    /* Set source address, must be device */
+    dmalp[MCFDMA_DSAR] = dma_device_address[dmanr];
+  }
+
+#ifdef DEBUG_DMA
+  printk("%s(%d): dmanr=%d DMR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n",
+	__FILE__, __LINE__, dmanr, (int) &dmawp[MCFDMA_DMR], dmawp[MCFDMA_DMR],
+	(int) &dmalp[MCFDMA_DSAR], dmalp[MCFDMA_DSAR],
+	(int) &dmalp[MCFDMA_DDAR], dmalp[MCFDMA_DDAR]);
+#endif
+}
+
+/*
+ * Specific for Coldfire - sets device address.
+ * Should be called after the mode set call, and before set DMA address.
+ */
+static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a)
+{
+#ifdef DMA_DEBUG
+  printk("set_dma_device_addr(dmanr=%d,a=%x)\n", dmanr, a);
+#endif
+
+  dma_device_address[dmanr] = a;
+}
+
+/*
+ * NOTE 2: "count" represents _bytes_.
+ *
+ * NOTE 3: While a 32-bit register, "count" is only a maximum 24-bit value.
+ */
+static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+  volatile unsigned int *dmalp;
+
+#ifdef DMA_DEBUG
+  printk("set_dma_count(dmanr=%d,count=%d)\n", dmanr, count);
+#endif
+
+  dmalp = (unsigned int *) dma_base_addr[dmanr];
+  dmalp[MCFDMA_DBCR] = count;
+}
+
+/*
+ * Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ */
+static __inline__ int get_dma_residue(unsigned int dmanr)
+{
+  volatile unsigned int *dmalp;
+  unsigned int count;
+
+#ifdef DMA_DEBUG
+  printk("get_dma_residue(dmanr=%d)\n", dmanr);
+#endif
+
+  dmalp = (unsigned int *) dma_base_addr[dmanr];
+  count = dmalp[MCFDMA_DBCR];
+  return(count);
+}
+
+#endif /* !defined(CONFIG_M5272) */
+#endif /* CONFIG_COLDFIRE */
+
+/* it's useless on the m68k, but unfortunately needed by the new
+   bootmem allocator (but this should do it for this) */
+#define MAX_DMA_ADDRESS PAGE_OFFSET
+
+#define MAX_DMA_CHANNELS 8
+
+extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
+extern void free_dma(unsigned int dmanr);	/* release it again */
+
+#define isa_dma_bridge_buggy    (0)
+
+#endif /* _M68K_DMA_H */
diff --git a/arch/m68k/include/asm/dma_mm.h b/arch/m68k/include/asm/dma_mm.h
deleted file mode 100644
index 4240fbc9..0000000
--- a/arch/m68k/include/asm/dma_mm.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _M68K_DMA_H
-#define _M68K_DMA_H 1
-
-
-/* it's useless on the m68k, but unfortunately needed by the new
-   bootmem allocator (but this should do it for this) */
-#define MAX_DMA_ADDRESS PAGE_OFFSET
-
-#define MAX_DMA_CHANNELS 8
-
-extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
-extern void free_dma(unsigned int dmanr);	/* release it again */
-
-#define isa_dma_bridge_buggy    (0)
-
-#endif /* _M68K_DMA_H */
diff --git a/arch/m68k/include/asm/dma_no.h b/arch/m68k/include/asm/dma_no.h
deleted file mode 100644
index 939a020..0000000
--- a/arch/m68k/include/asm/dma_no.h
+++ /dev/null
@@ -1,494 +0,0 @@
-#ifndef _M68K_DMA_H
-#define _M68K_DMA_H 1
- 
-//#define	DMA_DEBUG	1
-
-
-#ifdef CONFIG_COLDFIRE
-/*
- * ColdFire DMA Model:
- *   ColdFire DMA supports two forms of DMA: Single and Dual address. Single
- * address mode emits a source address, and expects that the device will either
- * pick up the data (DMA READ) or source data (DMA WRITE). This implies that
- * the device will place data on the correct byte(s) of the data bus, as the
- * memory transactions are always 32 bits. This implies that only 32 bit
- * devices will find single mode transfers useful. Dual address DMA mode
- * performs two cycles: source read and destination write. ColdFire will
- * align the data so that the device will always get the correct bytes, thus
- * is useful for 8 and 16 bit devices. This is the mode that is supported
- * below.
- *
- * AUG/22/2000 : added support for 32-bit Dual-Address-Mode (K) 2000 
- *               Oliver Kamphenkel (O.Kamphenkel@tu-bs.de)
- *
- * AUG/25/2000 : addad support for 8, 16 and 32-bit Single-Address-Mode (K)2000
- *               Oliver Kamphenkel (O.Kamphenkel@tu-bs.de)
- *
- * APR/18/2002 : added proper support for MCF5272 DMA controller.
- *               Arthur Shipkowski (art@videon-central.com)
- */
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfdma.h>
-
-/*
- * Set number of channels of DMA on ColdFire for different implementations.
- */
-#if defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407) || \
-	defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
-#define MAX_M68K_DMA_CHANNELS 4
-#elif defined(CONFIG_M5272)
-#define MAX_M68K_DMA_CHANNELS 1
-#elif defined(CONFIG_M532x)
-#define MAX_M68K_DMA_CHANNELS 0
-#else
-#define MAX_M68K_DMA_CHANNELS 2
-#endif
-
-extern unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS];
-extern unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
-
-#if !defined(CONFIG_M5272)
-#define DMA_MODE_WRITE_BIT  0x01  /* Memory/IO to IO/Memory select */
-#define DMA_MODE_WORD_BIT   0x02  /* 8 or 16 bit transfers */
-#define DMA_MODE_LONG_BIT   0x04  /* or 32 bit transfers */
-#define DMA_MODE_SINGLE_BIT 0x08  /* single-address-mode */
-
-/* I/O to memory, 8 bits, mode */
-#define DMA_MODE_READ	            0
-/* memory to I/O, 8 bits, mode */
-#define DMA_MODE_WRITE	            1
-/* I/O to memory, 16 bits, mode */
-#define DMA_MODE_READ_WORD          2
-/* memory to I/O, 16 bits, mode */
-#define DMA_MODE_WRITE_WORD         3
-/* I/O to memory, 32 bits, mode */
-#define DMA_MODE_READ_LONG          4
-/* memory to I/O, 32 bits, mode */
-#define DMA_MODE_WRITE_LONG         5
-/* I/O to memory, 8 bits, single-address-mode */     
-#define DMA_MODE_READ_SINGLE        8
-/* memory to I/O, 8 bits, single-address-mode */
-#define DMA_MODE_WRITE_SINGLE       9
-/* I/O to memory, 16 bits, single-address-mode */
-#define DMA_MODE_READ_WORD_SINGLE  10
-/* memory to I/O, 16 bits, single-address-mode */
-#define DMA_MODE_WRITE_WORD_SINGLE 11
-/* I/O to memory, 32 bits, single-address-mode */
-#define DMA_MODE_READ_LONG_SINGLE  12
-/* memory to I/O, 32 bits, single-address-mode */
-#define DMA_MODE_WRITE_LONG_SINGLE 13
-
-#else /* CONFIG_M5272 is defined */
-
-/* Source static-address mode */
-#define DMA_MODE_SRC_SA_BIT 0x01  
-/* Two bits to select between all four modes */
-#define DMA_MODE_SSIZE_MASK 0x06 
-/* Offset to shift bits in */
-#define DMA_MODE_SSIZE_OFF  0x01  
-/* Destination static-address mode */
-#define DMA_MODE_DES_SA_BIT 0x10  
-/* Two bits to select between all four modes */
-#define DMA_MODE_DSIZE_MASK 0x60  
-/* Offset to shift bits in */
-#define DMA_MODE_DSIZE_OFF  0x05
-/* Size modifiers */
-#define DMA_MODE_SIZE_LONG  0x00
-#define DMA_MODE_SIZE_BYTE  0x01
-#define DMA_MODE_SIZE_WORD  0x02
-#define DMA_MODE_SIZE_LINE  0x03
-
-/* 
- * Aliases to help speed quick ports; these may be suboptimal, however. They
- * do not include the SINGLE mode modifiers since the MCF5272 does not have a
- * mode where the device is in control of its addressing.
- */
-
-/* I/O to memory, 8 bits, mode */
-#define DMA_MODE_READ	              ((DMA_MODE_SIZE_BYTE << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_BYTE << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
-/* memory to I/O, 8 bits, mode */
-#define DMA_MODE_WRITE	            ((DMA_MODE_SIZE_BYTE << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_BYTE << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
-/* I/O to memory, 16 bits, mode */
-#define DMA_MODE_READ_WORD	        ((DMA_MODE_SIZE_WORD << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_WORD << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
-/* memory to I/O, 16 bits, mode */
-#define DMA_MODE_WRITE_WORD         ((DMA_MODE_SIZE_WORD << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_WORD << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
-/* I/O to memory, 32 bits, mode */
-#define DMA_MODE_READ_LONG	        ((DMA_MODE_SIZE_LONG << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_LONG << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
-/* memory to I/O, 32 bits, mode */
-#define DMA_MODE_WRITE_LONG         ((DMA_MODE_SIZE_LONG << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_LONG << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
-
-#endif /* !defined(CONFIG_M5272) */
-
-#if !defined(CONFIG_M5272)
-/* enable/disable a specific DMA channel */
-static __inline__ void enable_dma(unsigned int dmanr)
-{
-  volatile unsigned short *dmawp;
-
-#ifdef DMA_DEBUG
-  printk("enable_dma(dmanr=%d)\n", dmanr);
-#endif
-
-  dmawp = (unsigned short *) dma_base_addr[dmanr];
-  dmawp[MCFDMA_DCR] |= MCFDMA_DCR_EEXT;
-}
-
-static __inline__ void disable_dma(unsigned int dmanr)
-{
-  volatile unsigned short *dmawp;
-  volatile unsigned char  *dmapb;
-
-#ifdef DMA_DEBUG
-  printk("disable_dma(dmanr=%d)\n", dmanr);
-#endif
-
-  dmawp = (unsigned short *) dma_base_addr[dmanr];
-  dmapb = (unsigned char *) dma_base_addr[dmanr];
-
-  /* Turn off external requests, and stop any DMA in progress */
-  dmawp[MCFDMA_DCR] &= ~MCFDMA_DCR_EEXT;
-  dmapb[MCFDMA_DSR] = MCFDMA_DSR_DONE;
-}
-
-/*
- * Clear the 'DMA Pointer Flip Flop'.
- * Write 0 for LSB/MSB, 1 for MSB/LSB access.
- * Use this once to initialize the FF to a known state.
- * After that, keep track of it. :-)
- * --- In order to do that, the DMA routines below should ---
- * --- only be used while interrupts are disabled! ---
- *
- * This is a NOP for ColdFire. Provide a stub for compatibility.
- */
-static __inline__ void clear_dma_ff(unsigned int dmanr)
-{
-}
-
-/* set mode (above) for a specific DMA channel */
-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
-{
-
-  volatile unsigned char  *dmabp;
-  volatile unsigned short *dmawp;
-
-#ifdef DMA_DEBUG
-  printk("set_dma_mode(dmanr=%d,mode=%d)\n", dmanr, mode);
-#endif
-
-  dmabp = (unsigned char *) dma_base_addr[dmanr];
-  dmawp = (unsigned short *) dma_base_addr[dmanr];
-
-  // Clear config errors
-  dmabp[MCFDMA_DSR] = MCFDMA_DSR_DONE; 
-
-  // Set command register
-  dmawp[MCFDMA_DCR] =
-    MCFDMA_DCR_INT |         // Enable completion irq
-    MCFDMA_DCR_CS |          // Force one xfer per request
-    MCFDMA_DCR_AA |          // Enable auto alignment
-    // single-address-mode
-    ((mode & DMA_MODE_SINGLE_BIT) ? MCFDMA_DCR_SAA : 0) |
-    // sets s_rw (-> r/w) high if Memory to I/0
-    ((mode & DMA_MODE_WRITE_BIT) ? MCFDMA_DCR_S_RW : 0) |
-    // Memory to I/O or I/O to Memory
-    ((mode & DMA_MODE_WRITE_BIT) ? MCFDMA_DCR_SINC : MCFDMA_DCR_DINC) |
-    // 32 bit, 16 bit or 8 bit transfers
-    ((mode & DMA_MODE_WORD_BIT)  ? MCFDMA_DCR_SSIZE_WORD : 
-     ((mode & DMA_MODE_LONG_BIT) ? MCFDMA_DCR_SSIZE_LONG :
-                                   MCFDMA_DCR_SSIZE_BYTE)) |
-    ((mode & DMA_MODE_WORD_BIT)  ? MCFDMA_DCR_DSIZE_WORD :
-     ((mode & DMA_MODE_LONG_BIT) ? MCFDMA_DCR_DSIZE_LONG :
-                                   MCFDMA_DCR_DSIZE_BYTE));
-
-#ifdef DEBUG_DMA
-  printk("%s(%d): dmanr=%d DSR[%x]=%x DCR[%x]=%x\n", __FILE__, __LINE__,
-         dmanr, (int) &dmabp[MCFDMA_DSR], dmabp[MCFDMA_DSR],
-	 (int) &dmawp[MCFDMA_DCR], dmawp[MCFDMA_DCR]);
-#endif
-}
-
-/* Set transfer address for specific DMA channel */
-static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
-{
-  volatile unsigned short *dmawp;
-  volatile unsigned int   *dmalp;
-
-#ifdef DMA_DEBUG
-  printk("set_dma_addr(dmanr=%d,a=%x)\n", dmanr, a);
-#endif
-
-  dmawp = (unsigned short *) dma_base_addr[dmanr];
-  dmalp = (unsigned int *) dma_base_addr[dmanr];
-
-  // Determine which address registers are used for memory/device accesses
-  if (dmawp[MCFDMA_DCR] & MCFDMA_DCR_SINC) {
-    // Source incrementing, must be memory
-    dmalp[MCFDMA_SAR] = a;
-    // Set dest address, must be device
-    dmalp[MCFDMA_DAR] = dma_device_address[dmanr];
-  } else {
-    // Destination incrementing, must be memory
-    dmalp[MCFDMA_DAR] = a;
-    // Set source address, must be device
-    dmalp[MCFDMA_SAR] = dma_device_address[dmanr];
-  }
-
-#ifdef DEBUG_DMA
-  printk("%s(%d): dmanr=%d DCR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n",
-	__FILE__, __LINE__, dmanr, (int) &dmawp[MCFDMA_DCR], dmawp[MCFDMA_DCR],
-	(int) &dmalp[MCFDMA_SAR], dmalp[MCFDMA_SAR],
-	(int) &dmalp[MCFDMA_DAR], dmalp[MCFDMA_DAR]);
-#endif
-}
-
-/*
- * Specific for Coldfire - sets device address.
- * Should be called after the mode set call, and before set DMA address.
- */
-static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a)
-{
-#ifdef DMA_DEBUG
-  printk("set_dma_device_addr(dmanr=%d,a=%x)\n", dmanr, a);
-#endif
-
-  dma_device_address[dmanr] = a;
-}
-
-/*
- * NOTE 2: "count" represents _bytes_.
- */
-static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
-{
-  volatile unsigned short *dmawp;
-
-#ifdef DMA_DEBUG
-  printk("set_dma_count(dmanr=%d,count=%d)\n", dmanr, count);
-#endif
-
-  dmawp = (unsigned short *) dma_base_addr[dmanr];
-  dmawp[MCFDMA_BCR] = (unsigned short)count;
-}
-
-/*
- * Get DMA residue count. After a DMA transfer, this
- * should return zero. Reading this while a DMA transfer is
- * still in progress will return unpredictable results.
- * Otherwise, it returns the number of _bytes_ left to transfer.
- */
-static __inline__ int get_dma_residue(unsigned int dmanr)
-{
-  volatile unsigned short *dmawp;
-  unsigned short count;
-
-#ifdef DMA_DEBUG
-  printk("get_dma_residue(dmanr=%d)\n", dmanr);
-#endif
-
-  dmawp = (unsigned short *) dma_base_addr[dmanr];
-  count = dmawp[MCFDMA_BCR];
-  return((int) count);
-}
-#else /* CONFIG_M5272 is defined */
-
-/*
- * The MCF5272 DMA controller is very different than the controller defined above
- * in terms of register mapping.  For instance, with the exception of the 16-bit 
- * interrupt register (IRQ#85, for reference), all of the registers are 32-bit.
- *
- * The big difference, however, is the lack of device-requested DMA.  All modes
- * are dual address transfer, and there is no 'device' setup or direction bit.
- * You can DMA between a device and memory, between memory and memory, or even between
- * two devices directly, with any combination of incrementing and non-incrementing
- * addresses you choose.  This puts a crimp in distinguishing between the 'device 
- * address' set up by set_dma_device_addr.
- *
- * Therefore, there are two options.  One is to use set_dma_addr and set_dma_device_addr,
- * which will act exactly as above in -- it will look to see if the source is set to
- * autoincrement, and if so it will make the source use the set_dma_addr value and the
- * destination the set_dma_device_addr value.  Otherwise the source will be set to the
- * set_dma_device_addr value and the destination will get the set_dma_addr value.
- *
- * The other is to use the provided set_dma_src_addr and set_dma_dest_addr functions
- * and make it explicit.  Depending on what you're doing, one of these two should work
- * for you, but don't mix them in the same transfer setup.
- */
-
-/* enable/disable a specific DMA channel */
-static __inline__ void enable_dma(unsigned int dmanr)
-{
-  volatile unsigned int  *dmalp;
-
-#ifdef DMA_DEBUG
-  printk("enable_dma(dmanr=%d)\n", dmanr);
-#endif
-
-  dmalp = (unsigned int *) dma_base_addr[dmanr];
-  dmalp[MCFDMA_DMR] |= MCFDMA_DMR_EN;
-}
-
-static __inline__ void disable_dma(unsigned int dmanr)
-{
-  volatile unsigned int   *dmalp;
-
-#ifdef DMA_DEBUG
-  printk("disable_dma(dmanr=%d)\n", dmanr);
-#endif
-
-  dmalp = (unsigned int *) dma_base_addr[dmanr];
-
-  /* Turn off external requests, and stop any DMA in progress */
-  dmalp[MCFDMA_DMR] &= ~MCFDMA_DMR_EN;
-  dmalp[MCFDMA_DMR] |= MCFDMA_DMR_RESET;
-}
-
-/*
- * Clear the 'DMA Pointer Flip Flop'.
- * Write 0 for LSB/MSB, 1 for MSB/LSB access.
- * Use this once to initialize the FF to a known state.
- * After that, keep track of it. :-)
- * --- In order to do that, the DMA routines below should ---
- * --- only be used while interrupts are disabled! ---
- *
- * This is a NOP for ColdFire. Provide a stub for compatibility.
- */
-static __inline__ void clear_dma_ff(unsigned int dmanr)
-{
-}
-
-/* set mode (above) for a specific DMA channel */
-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
-{
-
-  volatile unsigned int   *dmalp;
-  volatile unsigned short *dmawp;
-
-#ifdef DMA_DEBUG
-  printk("set_dma_mode(dmanr=%d,mode=%d)\n", dmanr, mode);
-#endif
-  dmalp = (unsigned int *) dma_base_addr[dmanr];
-  dmawp = (unsigned short *) dma_base_addr[dmanr];
-
-  // Clear config errors
-  dmalp[MCFDMA_DMR] |= MCFDMA_DMR_RESET; 
-
-  // Set command register
-  dmalp[MCFDMA_DMR] =
-    MCFDMA_DMR_RQM_DUAL |         // Mandatory Request Mode setting
-    MCFDMA_DMR_DSTT_SD  |         // Set up addressing types; set to supervisor-data.
-    MCFDMA_DMR_SRCT_SD  |         // Set up addressing types; set to supervisor-data. 
-    // source static-address-mode
-    ((mode & DMA_MODE_SRC_SA_BIT) ? MCFDMA_DMR_SRCM_SA : MCFDMA_DMR_SRCM_IA) |
-    // dest static-address-mode
-    ((mode & DMA_MODE_DES_SA_BIT) ? MCFDMA_DMR_DSTM_SA : MCFDMA_DMR_DSTM_IA) |
-    // burst, 32 bit, 16 bit or 8 bit transfers are separately configurable on the MCF5272
-    (((mode & DMA_MODE_SSIZE_MASK) >> DMA_MODE_SSIZE_OFF) << MCFDMA_DMR_DSTS_OFF) |
-    (((mode & DMA_MODE_SSIZE_MASK) >> DMA_MODE_SSIZE_OFF) << MCFDMA_DMR_SRCS_OFF);
-    
-  dmawp[MCFDMA_DIR] |= MCFDMA_DIR_ASCEN;   /* Enable completion interrupts */
-  
-#ifdef DEBUG_DMA
-  printk("%s(%d): dmanr=%d DMR[%x]=%x DIR[%x]=%x\n", __FILE__, __LINE__,
-         dmanr, (int) &dmalp[MCFDMA_DMR], dmabp[MCFDMA_DMR],
-	 (int) &dmawp[MCFDMA_DIR], dmawp[MCFDMA_DIR]);
-#endif
-}
-
-/* Set transfer address for specific DMA channel */
-static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
-{
-  volatile unsigned int   *dmalp;
-
-#ifdef DMA_DEBUG
-  printk("set_dma_addr(dmanr=%d,a=%x)\n", dmanr, a);
-#endif
-
-  dmalp = (unsigned int *) dma_base_addr[dmanr];
-
-  // Determine which address registers are used for memory/device accesses
-  if (dmalp[MCFDMA_DMR] & MCFDMA_DMR_SRCM) {
-    // Source incrementing, must be memory
-    dmalp[MCFDMA_DSAR] = a;
-    // Set dest address, must be device
-    dmalp[MCFDMA_DDAR] = dma_device_address[dmanr];
-  } else {
-    // Destination incrementing, must be memory
-    dmalp[MCFDMA_DDAR] = a;
-    // Set source address, must be device
-    dmalp[MCFDMA_DSAR] = dma_device_address[dmanr];
-  }
-
-#ifdef DEBUG_DMA
-  printk("%s(%d): dmanr=%d DMR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n",
-	__FILE__, __LINE__, dmanr, (int) &dmawp[MCFDMA_DMR], dmawp[MCFDMA_DMR],
-	(int) &dmalp[MCFDMA_DSAR], dmalp[MCFDMA_DSAR],
-	(int) &dmalp[MCFDMA_DDAR], dmalp[MCFDMA_DDAR]);
-#endif
-}
-
-/*
- * Specific for Coldfire - sets device address.
- * Should be called after the mode set call, and before set DMA address.
- */
-static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a)
-{
-#ifdef DMA_DEBUG
-  printk("set_dma_device_addr(dmanr=%d,a=%x)\n", dmanr, a);
-#endif
-
-  dma_device_address[dmanr] = a;
-}
-
-/*
- * NOTE 2: "count" represents _bytes_.
- *
- * NOTE 3: While a 32-bit register, "count" is only a maximum 24-bit value.
- */
-static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
-{
-  volatile unsigned int *dmalp;
-  
-#ifdef DMA_DEBUG
-  printk("set_dma_count(dmanr=%d,count=%d)\n", dmanr, count);
-#endif
-
-  dmalp = (unsigned int *) dma_base_addr[dmanr];
-  dmalp[MCFDMA_DBCR] = count;
-}
-
-/*
- * Get DMA residue count. After a DMA transfer, this
- * should return zero. Reading this while a DMA transfer is
- * still in progress will return unpredictable results.
- * Otherwise, it returns the number of _bytes_ left to transfer.
- */
-static __inline__ int get_dma_residue(unsigned int dmanr)
-{
-  volatile unsigned int *dmalp;
-  unsigned int count;
-
-#ifdef DMA_DEBUG
-  printk("get_dma_residue(dmanr=%d)\n", dmanr);
-#endif
-
-  dmalp = (unsigned int *) dma_base_addr[dmanr];
-  count = dmalp[MCFDMA_DBCR];
-  return(count);
-}
-
-#endif /* !defined(CONFIG_M5272) */
-#endif /* CONFIG_COLDFIRE */
- 
-#define MAX_DMA_CHANNELS 8
-
-/* Don't define MAX_DMA_ADDRESS; it's useless on the m68k/coldfire and any
-   occurrence should be flagged as an error.  */
-/* under 2.4 it is actually needed by the new bootmem allocator */
-#define MAX_DMA_ADDRESS PAGE_OFFSET
-
-/* These are in kernel/dma.c: */
-extern int request_dma(unsigned int dmanr, const char *device_id);	/* reserve a DMA channel */
-extern void free_dma(unsigned int dmanr);	/* release it again */
- 
-#endif /* _M68K_DMA_H */
diff --git a/arch/m68k/include/asm/elia.h b/arch/m68k/include/asm/elia.h
deleted file mode 100644
index e037d4e..0000000
--- a/arch/m68k/include/asm/elia.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/****************************************************************************/
-
-/*
- *	elia.h -- Lineo (formerly Moreton Bay) eLIA platform support.
- *
- *	(C) Copyright 1999-2000, Moreton Bay (www.moreton.com.au)
- *	(C) Copyright 1999-2000, Lineo (www.lineo.com)
- */
-
-/****************************************************************************/
-#ifndef	elia_h
-#define	elia_h
-/****************************************************************************/
-
-#include <asm/coldfire.h>
-
-#ifdef CONFIG_eLIA
-
-/*
- *	The serial port DTR and DCD lines are also on the Parallel I/O
- *	as well, so define those too.
- */
-
-#define	eLIA_DCD1		0x0001
-#define	eLIA_DCD0		0x0002
-#define	eLIA_DTR1		0x0004
-#define	eLIA_DTR0		0x0008
-
-#define	eLIA_PCIRESET		0x0020
-
-/*
- *	Kernel macros to set and unset the LEDs.
- */
-#ifndef __ASSEMBLY__
-extern unsigned short	ppdata;
-#endif /* __ASSEMBLY__ */
-
-#endif	/* CONFIG_eLIA */
-
-/****************************************************************************/
-#endif	/* elia_h */
diff --git a/arch/m68k/include/asm/gpio.h b/arch/m68k/include/asm/gpio.h
new file mode 100644
index 0000000..283214d
--- /dev/null
+++ b/arch/m68k/include/asm/gpio.h
@@ -0,0 +1,238 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#ifndef coldfire_gpio_h
+#define coldfire_gpio_h
+
+#include <linux/io.h>
+#include <asm-generic/gpio.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+/*
+ * The Freescale Coldfire family is quite varied in how they implement GPIO.
+ * Some parts have 8 bit ports, some have 16bit and some have 32bit; some have
+ * only one port, others have multiple ports; some have a single data latch
+ * for both input and output, others have a separate pin data register to read
+ * input; some require a read-modify-write access to change an output, others
+ * have set and clear registers for some of the outputs; Some have all the
+ * GPIOs in a single control area, others have some GPIOs implemented in
+ * different modules.
+ *
+ * This implementation attempts accomodate the differences while presenting
+ * a generic interface that will optimize to as few instructions as possible.
+ */
+#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
+    defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
+    defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
+
+/* These parts have GPIO organized by 8 bit ports */
+
+#define MCFGPIO_PORTTYPE		u8
+#define MCFGPIO_PORTSIZE		8
+#define mcfgpio_read(port)		__raw_readb(port)
+#define mcfgpio_write(data, port)	__raw_writeb(data, port)
+
+#elif defined(CONFIG_M5307) || defined(CONFIG_M5407) || defined(CONFIG_M5272)
+
+/* These parts have GPIO organized by 16 bit ports */
+
+#define MCFGPIO_PORTTYPE		u16
+#define MCFGPIO_PORTSIZE		16
+#define mcfgpio_read(port)		__raw_readw(port)
+#define mcfgpio_write(data, port)	__raw_writew(data, port)
+
+#elif defined(CONFIG_M5249)
+
+/* These parts have GPIO organized by 32 bit ports */
+
+#define MCFGPIO_PORTTYPE		u32
+#define MCFGPIO_PORTSIZE		32
+#define mcfgpio_read(port)		__raw_readl(port)
+#define mcfgpio_write(data, port)	__raw_writel(data, port)
+
+#endif
+
+#define mcfgpio_bit(gpio)		(1 << ((gpio) %  MCFGPIO_PORTSIZE))
+#define mcfgpio_port(gpio)		((gpio) / MCFGPIO_PORTSIZE)
+
+#if defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
+    defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
+/*
+ * These parts have an 'Edge' Port module (external interrupt/GPIO) which uses
+ * read-modify-write to change an output and a GPIO module which has separate
+ * set/clr registers to directly change outputs with a single write access.
+ */
+#if defined(CONFIG_M528x)
+/*
+ * The 528x also has GPIOs in other modules (GPT, QADC) which use
+ * read-modify-write as well as those controlled by the EPORT and GPIO modules.
+ */
+#define MCFGPIO_SCR_START		40
+#else
+#define MCFGPIO_SCR_START		8
+#endif
+
+#define MCFGPIO_SETR_PORT(gpio)		(MCFGPIO_SETR + \
+					mcfgpio_port(gpio - MCFGPIO_SCR_START))
+
+#define MCFGPIO_CLRR_PORT(gpio)		(MCFGPIO_CLRR + \
+					mcfgpio_port(gpio - MCFGPIO_SCR_START))
+#else
+
+#define MCFGPIO_SCR_START		MCFGPIO_PIN_MAX
+/* with MCFGPIO_SCR == MCFGPIO_PIN_MAX, these will be optimized away */
+#define MCFGPIO_SETR_PORT(gpio)		0
+#define MCFGPIO_CLRR_PORT(gpio)		0
+
+#endif
+/*
+ * Coldfire specific helper functions
+ */
+
+/* return the port pin data register for a gpio */
+static inline u32 __mcf_gpio_ppdr(unsigned gpio)
+{
+#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
+    defined(CONFIG_M5307) || defined(CONFIG_M5407)
+	return MCFSIM_PADAT;
+#elif defined(CONFIG_M5272)
+	if (gpio < 16)
+		return MCFSIM_PADAT;
+	else if (gpio < 32)
+		return MCFSIM_PBDAT;
+	else
+		return MCFSIM_PCDAT;
+#elif defined(CONFIG_M5249)
+	if (gpio < 32)
+		return MCFSIM2_GPIOREAD;
+	else
+		return MCFSIM2_GPIO1READ;
+#elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
+      defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
+	if (gpio < 8)
+		return MCFEPORT_EPPDR;
+#if defined(CONFIG_M528x)
+	else if (gpio < 16)
+		return MCFGPTA_GPTPORT;
+	else if (gpio < 24)
+		return MCFGPTB_GPTPORT;
+	else if (gpio < 32)
+		return MCFQADC_PORTQA;
+	else if (gpio < 40)
+		return MCFQADC_PORTQB;
+#endif
+	else
+		return MCFGPIO_PPDR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
+#endif
+}
+
+/* return the port output data register for a gpio */
+static inline u32 __mcf_gpio_podr(unsigned gpio)
+{
+#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
+    defined(CONFIG_M5307) || defined(CONFIG_M5407)
+	return MCFSIM_PADAT;
+#elif defined(CONFIG_M5272)
+	if (gpio < 16)
+		return MCFSIM_PADAT;
+	else if (gpio < 32)
+		return MCFSIM_PBDAT;
+	else
+		return MCFSIM_PCDAT;
+#elif defined(CONFIG_M5249)
+	if (gpio < 32)
+		return MCFSIM2_GPIOWRITE;
+	else
+		return MCFSIM2_GPIO1WRITE;
+#elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
+      defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
+	if (gpio < 8)
+		return MCFEPORT_EPDR;
+#if defined(CONFIG_M528x)
+	else if (gpio < 16)
+		return MCFGPTA_GPTPORT;
+	else if (gpio < 24)
+		return MCFGPTB_GPTPORT;
+	else if (gpio < 32)
+		return MCFQADC_PORTQA;
+	else if (gpio < 40)
+		return MCFQADC_PORTQB;
+#endif
+	else
+		return MCFGPIO_PODR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
+#endif
+}
+
+/*
+ * The Generic GPIO functions
+ *
+ * If the gpio is a compile time constant and is one of the Coldfire gpios,
+ * use the inline version, otherwise dispatch thru gpiolib.
+ */
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	if (__builtin_constant_p(gpio) && gpio < MCFGPIO_PIN_MAX)
+		return mcfgpio_read(__mcf_gpio_ppdr(gpio)) & mcfgpio_bit(gpio);
+	else
+		return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	if (__builtin_constant_p(gpio) && gpio < MCFGPIO_PIN_MAX) {
+		if (gpio < MCFGPIO_SCR_START) {
+			unsigned long flags;
+			MCFGPIO_PORTTYPE data;
+
+			local_irq_save(flags);
+			data = mcfgpio_read(__mcf_gpio_podr(gpio));
+			if (value)
+				data |= mcfgpio_bit(gpio);
+			else
+				data &= ~mcfgpio_bit(gpio);
+			mcfgpio_write(data, __mcf_gpio_podr(gpio));
+			local_irq_restore(flags);
+		} else {
+			if (value)
+				mcfgpio_write(mcfgpio_bit(gpio),
+						MCFGPIO_SETR_PORT(gpio));
+			else
+				mcfgpio_write(~mcfgpio_bit(gpio),
+						MCFGPIO_CLRR_PORT(gpio));
+		}
+	} else
+		__gpio_set_value(gpio, value);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return (gpio < MCFGPIO_IRQ_MAX) ? gpio + MCFGPIO_IRQ_VECBASE : -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return (irq >= MCFGPIO_IRQ_VECBASE &&
+		irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) ?
+		irq - MCFGPIO_IRQ_VECBASE : -ENXIO;
+}
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+	return gpio < MCFGPIO_PIN_MAX ? 0 : __gpio_cansleep(gpio);
+}
+
+#endif
diff --git a/arch/m68k/include/asm/hardirq_no.h b/arch/m68k/include/asm/hardirq_no.h
index bfad281..b44b14b 100644
--- a/arch/m68k/include/asm/hardirq_no.h
+++ b/arch/m68k/include/asm/hardirq_no.h
@@ -1,16 +1,8 @@
 #ifndef __M68K_HARDIRQ_H
 #define __M68K_HARDIRQ_H
 
-#include <linux/cache.h>
-#include <linux/threads.h>
 #include <asm/irq.h>
 
-typedef struct {
-	unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
-
 #define HARDIRQ_BITS	8
 
 /*
@@ -22,6 +14,6 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-void ack_bad_irq(unsigned int irq);
+#include <asm-generic/hardirq.h>
 
 #endif /* __M68K_HARDIRQ_H */
diff --git a/arch/m68k/include/asm/io_no.h b/arch/m68k/include/asm/io_no.h
index 6adef1e..7f57436 100644
--- a/arch/m68k/include/asm/io_no.h
+++ b/arch/m68k/include/asm/io_no.h
@@ -134,7 +134,7 @@
 #define insw(a,b,l) io_insw(a,b,l)
 #define insl(a,b,l) io_insl(a,b,l)
 
-#define IO_SPACE_LIMIT 0xffff
+#define IO_SPACE_LIMIT 0xffffffff
 
 
 /* Values for nocacheflag and cmode */
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
index d031416..907eff1 100644
--- a/arch/m68k/include/asm/irq.h
+++ b/arch/m68k/include/asm/irq.h
@@ -1,5 +1,134 @@
-#ifdef __uClinux__
-#include "irq_no.h"
+#ifndef _M68K_IRQ_H_
+#define _M68K_IRQ_H_
+
+/*
+ * This should be the same as the max(NUM_X_SOURCES) for all the
+ * different m68k hosts compiled into the kernel.
+ * Currently the Atari has 72 and the Amiga 24, but if both are
+ * supported in the kernel it is better to make room for 72.
+ */
+#if defined(CONFIG_COLDFIRE)
+#define NR_IRQS 256
+#elif defined(CONFIG_VME) || defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+#define NR_IRQS 200
+#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
+#define NR_IRQS 72
+#elif defined(CONFIG_Q40)
+#define NR_IRQS	43
+#elif defined(CONFIG_AMIGA) || !defined(CONFIG_MMU)
+#define NR_IRQS	32
+#elif defined(CONFIG_APOLLO)
+#define NR_IRQS	24
+#elif defined(CONFIG_HP300)
+#define NR_IRQS	8
 #else
-#include "irq_mm.h"
+#define NR_IRQS	0
 #endif
+
+#ifdef CONFIG_MMU
+
+#include <linux/linkage.h>
+#include <linux/hardirq.h>
+#include <linux/irqreturn.h>
+#include <linux/spinlock_types.h>
+
+/*
+ * The hardirq mask has to be large enough to have
+ * space for potentially all IRQ sources in the system
+ * nesting on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
+
+/*
+ * Interrupt source definitions
+ * General interrupt sources are the level 1-7.
+ * Adding an interrupt service routine for one of these sources
+ * results in the addition of that routine to a chain of routines.
+ * Each one is called in succession.  Each individual interrupt
+ * service routine should determine if the device associated with
+ * that routine requires service.
+ */
+
+#define IRQ_SPURIOUS	0
+
+#define IRQ_AUTO_1	1	/* level 1 interrupt */
+#define IRQ_AUTO_2	2	/* level 2 interrupt */
+#define IRQ_AUTO_3	3	/* level 3 interrupt */
+#define IRQ_AUTO_4	4	/* level 4 interrupt */
+#define IRQ_AUTO_5	5	/* level 5 interrupt */
+#define IRQ_AUTO_6	6	/* level 6 interrupt */
+#define IRQ_AUTO_7	7	/* level 7 interrupt (non-maskable) */
+
+#define IRQ_USER	8
+
+extern unsigned int irq_canonicalize(unsigned int irq);
+
+struct pt_regs;
+
+/*
+ * various flags for request_irq() - the Amiga now uses the standard
+ * mechanism like all other architectures - IRQF_DISABLED and
+ * IRQF_SHARED are your friends.
+ */
+#ifndef MACH_AMIGA_ONLY
+#define IRQ_FLG_LOCK	(0x0001)	/* handler is not replaceable	*/
+#define IRQ_FLG_REPLACE	(0x0002)	/* replace existing handler	*/
+#define IRQ_FLG_FAST	(0x0004)
+#define IRQ_FLG_SLOW	(0x0008)
+#define IRQ_FLG_STD	(0x8000)	/* internally used		*/
+#endif
+
+/*
+ * This structure is used to chain together the ISRs for a particular
+ * interrupt source (if it supports chaining).
+ */
+typedef struct irq_node {
+	irqreturn_t	(*handler)(int, void *);
+	void		*dev_id;
+	struct irq_node *next;
+	unsigned long	flags;
+	const char	*devname;
+} irq_node_t;
+
+/*
+ * This structure has only 4 elements for speed reasons
+ */
+struct irq_handler {
+	int		(*handler)(int, void *);
+	unsigned long	flags;
+	void		*dev_id;
+	const char	*devname;
+};
+
+struct irq_controller {
+	const char *name;
+	spinlock_t lock;
+	int (*startup)(unsigned int irq);
+	void (*shutdown)(unsigned int irq);
+	void (*enable)(unsigned int irq);
+	void (*disable)(unsigned int irq);
+};
+
+extern int m68k_irq_startup(unsigned int);
+extern void m68k_irq_shutdown(unsigned int);
+
+/*
+ * This function returns a new irq_node_t
+ */
+extern irq_node_t *new_irq_node(void);
+
+extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
+extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
+				      void (*handler)(unsigned int, struct pt_regs *));
+extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
+
+asmlinkage void m68k_handle_int(unsigned int);
+asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
+
+#else
+#define irq_canonicalize(irq)  (irq)
+#endif /* CONFIG_MMU */
+
+#endif /* _M68K_IRQ_H_ */
diff --git a/arch/m68k/include/asm/irq_mm.h b/arch/m68k/include/asm/irq_mm.h
deleted file mode 100644
index 0cab42c..0000000
--- a/arch/m68k/include/asm/irq_mm.h
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifndef _M68K_IRQ_H_
-#define _M68K_IRQ_H_
-
-#include <linux/linkage.h>
-#include <linux/hardirq.h>
-#include <linux/irqreturn.h>
-#include <linux/spinlock_types.h>
-
-/*
- * This should be the same as the max(NUM_X_SOURCES) for all the
- * different m68k hosts compiled into the kernel.
- * Currently the Atari has 72 and the Amiga 24, but if both are
- * supported in the kernel it is better to make room for 72.
- */
-#if defined(CONFIG_VME) || defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
-#define NR_IRQS 200
-#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
-#define NR_IRQS 72
-#elif defined(CONFIG_Q40)
-#define NR_IRQS	43
-#elif defined(CONFIG_AMIGA)
-#define NR_IRQS	32
-#elif defined(CONFIG_APOLLO)
-#define NR_IRQS	24
-#elif defined(CONFIG_HP300)
-#define NR_IRQS	8
-#else
-#define NR_IRQS	0
-#endif
-
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-/*
- * Interrupt source definitions
- * General interrupt sources are the level 1-7.
- * Adding an interrupt service routine for one of these sources
- * results in the addition of that routine to a chain of routines.
- * Each one is called in succession.  Each individual interrupt
- * service routine should determine if the device associated with
- * that routine requires service.
- */
-
-#define IRQ_SPURIOUS	0
-
-#define IRQ_AUTO_1	1	/* level 1 interrupt */
-#define IRQ_AUTO_2	2	/* level 2 interrupt */
-#define IRQ_AUTO_3	3	/* level 3 interrupt */
-#define IRQ_AUTO_4	4	/* level 4 interrupt */
-#define IRQ_AUTO_5	5	/* level 5 interrupt */
-#define IRQ_AUTO_6	6	/* level 6 interrupt */
-#define IRQ_AUTO_7	7	/* level 7 interrupt (non-maskable) */
-
-#define IRQ_USER	8
-
-extern unsigned int irq_canonicalize(unsigned int irq);
-
-struct pt_regs;
-
-/*
- * various flags for request_irq() - the Amiga now uses the standard
- * mechanism like all other architectures - IRQF_DISABLED and
- * IRQF_SHARED are your friends.
- */
-#ifndef MACH_AMIGA_ONLY
-#define IRQ_FLG_LOCK	(0x0001)	/* handler is not replaceable	*/
-#define IRQ_FLG_REPLACE	(0x0002)	/* replace existing handler	*/
-#define IRQ_FLG_FAST	(0x0004)
-#define IRQ_FLG_SLOW	(0x0008)
-#define IRQ_FLG_STD	(0x8000)	/* internally used		*/
-#endif
-
-/*
- * This structure is used to chain together the ISRs for a particular
- * interrupt source (if it supports chaining).
- */
-typedef struct irq_node {
-	irqreturn_t	(*handler)(int, void *);
-	void		*dev_id;
-	struct irq_node *next;
-	unsigned long	flags;
-	const char	*devname;
-} irq_node_t;
-
-/*
- * This structure has only 4 elements for speed reasons
- */
-struct irq_handler {
-	int		(*handler)(int, void *);
-	unsigned long	flags;
-	void		*dev_id;
-	const char	*devname;
-};
-
-struct irq_controller {
-	const char *name;
-	spinlock_t lock;
-	int (*startup)(unsigned int irq);
-	void (*shutdown)(unsigned int irq);
-	void (*enable)(unsigned int irq);
-	void (*disable)(unsigned int irq);
-};
-
-extern int m68k_irq_startup(unsigned int);
-extern void m68k_irq_shutdown(unsigned int);
-
-/*
- * This function returns a new irq_node_t
- */
-extern irq_node_t *new_irq_node(void);
-
-extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
-				      void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
-
-asmlinkage void m68k_handle_int(unsigned int);
-asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
-
-#endif /* _M68K_IRQ_H_ */
diff --git a/arch/m68k/include/asm/irq_no.h b/arch/m68k/include/asm/irq_no.h
deleted file mode 100644
index 9373c31..0000000
--- a/arch/m68k/include/asm/irq_no.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _M68KNOMMU_IRQ_H_
-#define _M68KNOMMU_IRQ_H_
-
-#ifdef CONFIG_COLDFIRE
-/*
- * On the ColdFire we keep track of all vectors. That way drivers
- * can register whatever vector number they wish, and we can deal
- * with it.
- */
-#define	SYS_IRQS	256
-#define	NR_IRQS		SYS_IRQS
-
-#else
-
-/*
- * # of m68k interrupts
- */
-#define SYS_IRQS	8
-#define NR_IRQS		(24 + SYS_IRQS)
-
-#endif /* CONFIG_COLDFIRE */
-
-
-#define irq_canonicalize(irq)	(irq)
-
-#endif /* _M68KNOMMU_IRQ_H_ */
diff --git a/arch/m68k/include/asm/m5206sim.h b/arch/m68k/include/asm/m5206sim.h
index 7e3594d..9c384e2 100644
--- a/arch/m68k/include/asm/m5206sim.h
+++ b/arch/m68k/include/asm/m5206sim.h
@@ -85,8 +85,21 @@
 #define	MCFSIM_PAR		0xcb		/* Pin Assignment reg (r/w) */
 #endif
 
-#define	MCFSIM_PADDR		0x1c5		/* Parallel Direction (r/w) */
-#define	MCFSIM_PADAT		0x1c9		/* Parallel Port Value (r/w) */
+#define	MCFSIM_PADDR		(MCF_MBAR + 0x1c5)	/* Parallel Direction (r/w) */
+#define	MCFSIM_PADAT		(MCF_MBAR + 0x1c9)	/* Parallel Port Value (r/w) */
+
+/*
+ *	Define system peripheral IRQ usage.
+ */
+#define	MCF_IRQ_TIMER		30		/* Timer0, Level 6 */
+#define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
+
+/*
+ * Generic GPIO
+ */
+#define MCFGPIO_PIN_MAX		8
+#define MCFGPIO_IRQ_VECBASE	-1
+#define MCFGPIO_IRQ_MAX		-1
 
 /*
  *	Some symbol defines for the Parallel Port Pin Assignment Register
@@ -111,21 +124,5 @@
 #define	MCFSIM_DMA2ICR		MCFSIM_ICR15	/* DMA 2 ICR */
 #endif
 
-#if defined(CONFIG_M5206e)
-#define	MCFSIM_IMR_MASKALL	0xfffe		/* All SIM intr sources */
-#endif
-
-/*
- *	Macro to get and set IMR register. It is 16 bits on the 5206.
- */
-#define	mcf_getimr()		\
-	*((volatile unsigned short *) (MCF_MBAR + MCFSIM_IMR))
-
-#define	mcf_setimr(imr)		\
-	*((volatile unsigned short *) (MCF_MBAR + MCFSIM_IMR)) = (imr)
-
-#define	mcf_getipr()		\
-	*((volatile unsigned short *) (MCF_MBAR + MCFSIM_IPR))
-
 /****************************************************************************/
 #endif	/* m5206sim_h */
diff --git a/arch/m68k/include/asm/m520xsim.h b/arch/m68k/include/asm/m520xsim.h
index 83bbcfd..ed2b69b 100644
--- a/arch/m68k/include/asm/m520xsim.h
+++ b/arch/m68k/include/asm/m520xsim.h
@@ -11,9 +11,8 @@
 #define m520xsim_h
 /****************************************************************************/
 
-
 /*
- *  Define the 5282 SIM register set addresses.
+ *  Define the 520x SIM register set addresses.
  */
 #define MCFICM_INTC0        0x48000     /* Base for Interrupt Ctrl 0 */
 #define MCFINTC_IPRH        0x00        /* Interrupt pending 32-63 */
@@ -22,8 +21,22 @@
 #define MCFINTC_IMRL        0x0c        /* Interrupt mask 1-31 */
 #define MCFINTC_INTFRCH     0x10        /* Interrupt force 32-63 */
 #define MCFINTC_INTFRCL     0x14        /* Interrupt force 1-31 */
+#define MCFINTC_SIMR        0x1c        /* Set interrupt mask 0-63 */
+#define MCFINTC_CIMR        0x1d        /* Clear interrupt mask 0-63 */
 #define MCFINTC_ICR0        0x40        /* Base ICR register */
 
+/*
+ *  The common interrupt controller code just wants to know the absolute
+ *  address to the SIMR and CIMR registers (not offsets into IPSBAR).
+ *  The 520x family only has a single INTC unit.
+ */
+#define MCFINTC0_SIMR       (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_SIMR)
+#define MCFINTC0_CIMR       (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_CIMR)
+#define	MCFINTC0_ICR0       (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0)
+#define MCFINTC1_SIMR       (0)
+#define MCFINTC1_CIMR       (0)
+#define	MCFINTC1_ICR0       (0)
+
 #define MCFINT_VECBASE      64
 #define MCFINT_UART0        26          /* Interrupt number for UART0 */
 #define MCFINT_UART1        27          /* Interrupt number for UART1 */
@@ -41,6 +54,62 @@
 #define MCFSIM_SDCS0        0x000a8110	/* SDRAM Chip Select 0 Configuration */
 #define MCFSIM_SDCS1        0x000a8114	/* SDRAM Chip Select 1 Configuration */
 
+#define MCFEPORT_EPDDR			0xFC088002
+#define MCFEPORT_EPDR			0xFC088004
+#define MCFEPORT_EPPDR			0xFC088005
+
+#define MCFGPIO_PODR_BUSCTL		0xFC0A4000
+#define MCFGPIO_PODR_BE			0xFC0A4001
+#define MCFGPIO_PODR_CS			0xFC0A4002
+#define MCFGPIO_PODR_FECI2C		0xFC0A4003
+#define MCFGPIO_PODR_QSPI		0xFC0A4004
+#define MCFGPIO_PODR_TIMER		0xFC0A4005
+#define MCFGPIO_PODR_UART		0xFC0A4006
+#define MCFGPIO_PODR_FECH		0xFC0A4007
+#define MCFGPIO_PODR_FECL		0xFC0A4008
+
+#define MCFGPIO_PDDR_BUSCTL		0xFC0A400C
+#define MCFGPIO_PDDR_BE			0xFC0A400D
+#define MCFGPIO_PDDR_CS			0xFC0A400E
+#define MCFGPIO_PDDR_FECI2C		0xFC0A400F
+#define MCFGPIO_PDDR_QSPI		0xFC0A4010
+#define MCFGPIO_PDDR_TIMER		0xFC0A4011
+#define MCFGPIO_PDDR_UART		0xFC0A4012
+#define MCFGPIO_PDDR_FECH		0xFC0A4013
+#define MCFGPIO_PDDR_FECL		0xFC0A4014
+
+#define MCFGPIO_PPDSDR_BUSCTL		0xFC0A401A
+#define MCFGPIO_PPDSDR_BE		0xFC0A401B
+#define MCFGPIO_PPDSDR_CS		0xFC0A401C
+#define MCFGPIO_PPDSDR_FECI2C		0xFC0A401D
+#define MCFGPIO_PPDSDR_QSPI		0xFC0A401E
+#define MCFGPIO_PPDSDR_TIMER		0xFC0A401F
+#define MCFGPIO_PPDSDR_UART		0xFC0A4021
+#define MCFGPIO_PPDSDR_FECH		0xFC0A4021
+#define MCFGPIO_PPDSDR_FECL		0xFC0A4022
+
+#define MCFGPIO_PCLRR_BUSCTL		0xFC0A4024
+#define MCFGPIO_PCLRR_BE		0xFC0A4025
+#define MCFGPIO_PCLRR_CS		0xFC0A4026
+#define MCFGPIO_PCLRR_FECI2C		0xFC0A4027
+#define MCFGPIO_PCLRR_QSPI		0xFC0A4028
+#define MCFGPIO_PCLRR_TIMER		0xFC0A4029
+#define MCFGPIO_PCLRR_UART		0xFC0A402A
+#define MCFGPIO_PCLRR_FECH		0xFC0A402B
+#define MCFGPIO_PCLRR_FECL		0xFC0A402C
+/*
+ * Generic GPIO support
+ */
+#define MCFGPIO_PODR			MCFGPIO_PODR_BUSCTL
+#define MCFGPIO_PDDR			MCFGPIO_PDDR_BUSCTL
+#define MCFGPIO_PPDR			MCFGPIO_PPDSDR_BUSCTL
+#define MCFGPIO_SETR			MCFGPIO_PPDSDR_BUSCTL
+#define MCFGPIO_CLRR			MCFGPIO_PCLRR_BUSCTL
+
+#define MCFGPIO_PIN_MAX			80
+#define MCFGPIO_IRQ_MAX			8
+#define MCFGPIO_IRQ_VECBASE		MCFINT_VECBASE
+/****************************************************************************/
 
 #define MCF_GPIO_PAR_UART                   (0xA4036)
 #define MCF_GPIO_PAR_FECI2C                 (0xA4033)
@@ -55,10 +124,6 @@
 #define MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2   (0x02)
 #define MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2   (0x04)
 
-#define ICR_INTRCONF		0x05
-#define MCFPIT_IMR		MCFINTC_IMRL
-#define MCFPIT_IMR_IBIT		(1 << MCFINT_PIT1)
-
 /*
  *  Reset Controll Unit.
  */
diff --git a/arch/m68k/include/asm/m523xsim.h b/arch/m68k/include/asm/m523xsim.h
index 55183b5d..a34894c 100644
--- a/arch/m68k/include/asm/m523xsim.h
+++ b/arch/m68k/include/asm/m523xsim.h
@@ -50,5 +50,82 @@
 #define	MCF_RCR_SWRESET		0x80		/* Software reset bit */
 #define	MCF_RCR_FRCSTOUT	0x40		/* Force external reset */
 
+#define MCFGPIO_PODR_ADDR	(MCF_IPSBAR + 0x100000)
+#define MCFGPIO_PODR_DATAH	(MCF_IPSBAR + 0x100001)
+#define MCFGPIO_PODR_DATAL	(MCF_IPSBAR + 0x100002)
+#define MCFGPIO_PODR_BUSCTL	(MCF_IPSBAR + 0x100003)
+#define MCFGPIO_PODR_BS		(MCF_IPSBAR + 0x100004)
+#define MCFGPIO_PODR_CS		(MCF_IPSBAR + 0x100005)
+#define MCFGPIO_PODR_SDRAM	(MCF_IPSBAR + 0x100006)
+#define MCFGPIO_PODR_FECI2C	(MCF_IPSBAR + 0x100007)
+#define MCFGPIO_PODR_UARTH	(MCF_IPSBAR + 0x100008)
+#define MCFGPIO_PODR_UARTL	(MCF_IPSBAR + 0x100009)
+#define MCFGPIO_PODR_QSPI	(MCF_IPSBAR + 0x10000A)
+#define MCFGPIO_PODR_TIMER	(MCF_IPSBAR + 0x10000B)
+#define MCFGPIO_PODR_ETPU	(MCF_IPSBAR + 0x10000C)
+
+#define MCFGPIO_PDDR_ADDR	(MCF_IPSBAR + 0x100010)
+#define MCFGPIO_PDDR_DATAH	(MCF_IPSBAR + 0x100011)
+#define MCFGPIO_PDDR_DATAL	(MCF_IPSBAR + 0x100012)
+#define MCFGPIO_PDDR_BUSCTL	(MCF_IPSBAR + 0x100013)
+#define MCFGPIO_PDDR_BS		(MCF_IPSBAR + 0x100014)
+#define MCFGPIO_PDDR_CS		(MCF_IPSBAR + 0x100015)
+#define MCFGPIO_PDDR_SDRAM	(MCF_IPSBAR + 0x100016)
+#define MCFGPIO_PDDR_FECI2C	(MCF_IPSBAR + 0x100017)
+#define MCFGPIO_PDDR_UARTH	(MCF_IPSBAR + 0x100018)
+#define MCFGPIO_PDDR_UARTL	(MCF_IPSBAR + 0x100019)
+#define MCFGPIO_PDDR_QSPI	(MCF_IPSBAR + 0x10001A)
+#define MCFGPIO_PDDR_TIMER	(MCF_IPSBAR + 0x10001B)
+#define MCFGPIO_PDDR_ETPU	(MCF_IPSBAR + 0x10001C)
+
+#define MCFGPIO_PPDSDR_ADDR	(MCF_IPSBAR + 0x100020)
+#define MCFGPIO_PPDSDR_DATAH	(MCF_IPSBAR + 0x100021)
+#define MCFGPIO_PPDSDR_DATAL	(MCF_IPSBAR + 0x100022)
+#define MCFGPIO_PPDSDR_BUSCTL	(MCF_IPSBAR + 0x100023)
+#define MCFGPIO_PPDSDR_BS	(MCF_IPSBAR + 0x100024)
+#define MCFGPIO_PPDSDR_CS	(MCF_IPSBAR + 0x100025)
+#define MCFGPIO_PPDSDR_SDRAM	(MCF_IPSBAR + 0x100026)
+#define MCFGPIO_PPDSDR_FECI2C	(MCF_IPSBAR + 0x100027)
+#define MCFGPIO_PPDSDR_UARTH	(MCF_IPSBAR + 0x100028)
+#define MCFGPIO_PPDSDR_UARTL	(MCF_IPSBAR + 0x100029)
+#define MCFGPIO_PPDSDR_QSPI	(MCF_IPSBAR + 0x10002A)
+#define MCFGPIO_PPDSDR_TIMER	(MCF_IPSBAR + 0x10002B)
+#define MCFGPIO_PPDSDR_ETPU	(MCF_IPSBAR + 0x10002C)
+
+#define MCFGPIO_PCLRR_ADDR	(MCF_IPSBAR + 0x100030)
+#define MCFGPIO_PCLRR_DATAH	(MCF_IPSBAR + 0x100031)
+#define MCFGPIO_PCLRR_DATAL	(MCF_IPSBAR + 0x100032)
+#define MCFGPIO_PCLRR_BUSCTL	(MCF_IPSBAR + 0x100033)
+#define MCFGPIO_PCLRR_BS	(MCF_IPSBAR + 0x100034)
+#define MCFGPIO_PCLRR_CS	(MCF_IPSBAR + 0x100035)
+#define MCFGPIO_PCLRR_SDRAM	(MCF_IPSBAR + 0x100036)
+#define MCFGPIO_PCLRR_FECI2C	(MCF_IPSBAR + 0x100037)
+#define MCFGPIO_PCLRR_UARTH	(MCF_IPSBAR + 0x100038)
+#define MCFGPIO_PCLRR_UARTL	(MCF_IPSBAR + 0x100039)
+#define MCFGPIO_PCLRR_QSPI	(MCF_IPSBAR + 0x10003A)
+#define MCFGPIO_PCLRR_TIMER	(MCF_IPSBAR + 0x10003B)
+#define MCFGPIO_PCLRR_ETPU	(MCF_IPSBAR + 0x10003C)
+
+/*
+ * EPort
+ */
+
+#define MCFEPORT_EPDDR		(MCF_IPSBAR + 0x130002)
+#define MCFEPORT_EPDR		(MCF_IPSBAR + 0x130004)
+#define MCFEPORT_EPPDR		(MCF_IPSBAR + 0x130005)
+
+/*
+ * Generic GPIO support
+ */
+#define MCFGPIO_PODR			MCFGPIO_PODR_ADDR
+#define MCFGPIO_PDDR			MCFGPIO_PDDR_ADDR
+#define MCFGPIO_PPDR			MCFGPIO_PPDSDR_ADDR
+#define MCFGPIO_SETR			MCFGPIO_PPDSDR_ADDR
+#define MCFGPIO_CLRR			MCFGPIO_PCLRR_ADDR
+
+#define MCFGPIO_PIN_MAX			107
+#define MCFGPIO_IRQ_MAX			8
+#define MCFGPIO_IRQ_VECBASE		MCFINT_VECBASE
+
 /****************************************************************************/
 #endif	/* m523xsim_h */
diff --git a/arch/m68k/include/asm/m5249sim.h b/arch/m68k/include/asm/m5249sim.h
index 366eb86..14bce87 100644
--- a/arch/m68k/include/asm/m5249sim.h
+++ b/arch/m68k/include/asm/m5249sim.h
@@ -71,16 +71,22 @@
 #define	MCFSIM_DMA3ICR		MCFSIM_ICR9	/* DMA 3 ICR */
 
 /*
+ *	Define system peripheral IRQ usage.
+ */
+#define	MCF_IRQ_TIMER		30		/* Timer0, Level 6 */
+#define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
+
+/*
  *	General purpose IO registers (in MBAR2).
  */
-#define	MCFSIM2_GPIOREAD	0x0		/* GPIO read values */
-#define	MCFSIM2_GPIOWRITE	0x4		/* GPIO write values */
-#define	MCFSIM2_GPIOENABLE	0x8		/* GPIO enabled */
-#define	MCFSIM2_GPIOFUNC	0xc		/* GPIO function */
-#define	MCFSIM2_GPIO1READ	0xb0		/* GPIO1 read values */
-#define	MCFSIM2_GPIO1WRITE	0xb4		/* GPIO1 write values */
-#define	MCFSIM2_GPIO1ENABLE	0xb8		/* GPIO1 enabled */
-#define	MCFSIM2_GPIO1FUNC	0xbc		/* GPIO1 function */
+#define	MCFSIM2_GPIOREAD	(MCF_MBAR2 + 0x000)	/* GPIO read values */
+#define	MCFSIM2_GPIOWRITE	(MCF_MBAR2 + 0x004)	/* GPIO write values */
+#define	MCFSIM2_GPIOENABLE	(MCF_MBAR2 + 0x008)	/* GPIO enabled */
+#define	MCFSIM2_GPIOFUNC	(MCF_MBAR2 + 0x00C)	/* GPIO function */
+#define	MCFSIM2_GPIO1READ	(MCF_MBAR2 + 0x0B0)	/* GPIO1 read values */
+#define	MCFSIM2_GPIO1WRITE	(MCF_MBAR2 + 0x0B4)	/* GPIO1 write values */
+#define	MCFSIM2_GPIO1ENABLE	(MCF_MBAR2 + 0x0B8)	/* GPIO1 enabled */
+#define	MCFSIM2_GPIO1FUNC	(MCF_MBAR2 + 0x0BC)	/* GPIO1 function */
 
 #define	MCFSIM2_GPIOINTSTAT	0xc0		/* GPIO interrupt status */
 #define	MCFSIM2_GPIOINTCLEAR	0xc0		/* GPIO interrupt clear */
@@ -100,20 +106,28 @@
 #define	MCFSIM2_IDECONFIG1	0x18c		/* IDEconfig1 */
 #define	MCFSIM2_IDECONFIG2	0x190		/* IDEconfig2 */
 
+/*
+ * Define the base interrupt for the second interrupt controller.
+ * We set it to 128, out of the way of the base interrupts, and plenty
+ * of room for its 64 interrupts.
+ */
+#define	MCFINTC2_VECBASE	128
+
+#define	MCFINTC2_GPIOIRQ0	(MCFINTC2_VECBASE + 32)
+#define	MCFINTC2_GPIOIRQ1	(MCFINTC2_VECBASE + 33)
+#define	MCFINTC2_GPIOIRQ2	(MCFINTC2_VECBASE + 34)
+#define	MCFINTC2_GPIOIRQ3	(MCFINTC2_VECBASE + 35)
+#define	MCFINTC2_GPIOIRQ4	(MCFINTC2_VECBASE + 36)
+#define	MCFINTC2_GPIOIRQ5	(MCFINTC2_VECBASE + 37)
+#define	MCFINTC2_GPIOIRQ6	(MCFINTC2_VECBASE + 38)
+#define	MCFINTC2_GPIOIRQ7	(MCFINTC2_VECBASE + 39)
 
 /*
- *	Macro to set IMR register. It is 32 bits on the 5249.
+ * Generic GPIO support
  */
-#define	MCFSIM_IMR_MASKALL	0x7fffe		/* All SIM intr sources */
-
-#define	mcf_getimr()		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR))
-
-#define	mcf_setimr(imr)		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR)) = (imr);
-
-#define	mcf_getipr()		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPR))
+#define MCFGPIO_PIN_MAX		64
+#define MCFGPIO_IRQ_MAX		-1
+#define MCFGPIO_IRQ_VECBASE	-1
 
 /****************************************************************************/
 
@@ -137,9 +151,9 @@
 	subql	#1,%a1				/* get MBAR2 address in a1 */
 
 	/*
-	 *      Move secondary interrupts to base at 128.
+	 *      Move secondary interrupts to their base (128).
 	 */
-	moveb	#0x80,%d0
+	moveb	#MCFINTC2_VECBASE,%d0
 	moveb	%d0,0x16b(%a1)			/* interrupt base register */
 
 	/*
diff --git a/arch/m68k/include/asm/m5272sim.h b/arch/m68k/include/asm/m5272sim.h
index 6217edc..df3332c 100644
--- a/arch/m68k/include/asm/m5272sim.h
+++ b/arch/m68k/include/asm/m5272sim.h
@@ -12,7 +12,6 @@
 #define	m5272sim_h
 /****************************************************************************/
 
-
 /*
  *	Define the 5272 SIM register set addresses.
  */
@@ -63,16 +62,59 @@
 #define	MCFSIM_DCMR1		0x5c		/* DRAM 1 Mask reg (r/w) */
 #define	MCFSIM_DCCR1		0x63		/* DRAM 1 Control reg (r/w) */
 
-#define	MCFSIM_PACNT		0x80		/* Port A Control (r/w) */
-#define	MCFSIM_PADDR		0x84		/* Port A Direction (r/w) */
-#define	MCFSIM_PADAT		0x86		/* Port A Data (r/w) */
-#define	MCFSIM_PBCNT		0x88		/* Port B Control (r/w) */
-#define	MCFSIM_PBDDR		0x8c		/* Port B Direction (r/w) */
-#define	MCFSIM_PBDAT		0x8e		/* Port B Data (r/w) */
-#define	MCFSIM_PCDDR		0x94		/* Port C Direction (r/w) */
-#define	MCFSIM_PCDAT		0x96		/* Port C Data (r/w) */
-#define	MCFSIM_PDCNT		0x98		/* Port D Control (r/w) */
+#define	MCFSIM_PACNT		(MCF_MBAR + 0x80) /* Port A Control (r/w) */
+#define	MCFSIM_PADDR		(MCF_MBAR + 0x84) /* Port A Direction (r/w) */
+#define	MCFSIM_PADAT		(MCF_MBAR + 0x86) /* Port A Data (r/w) */
+#define	MCFSIM_PBCNT		(MCF_MBAR + 0x88) /* Port B Control (r/w) */
+#define	MCFSIM_PBDDR		(MCF_MBAR + 0x8c) /* Port B Direction (r/w) */
+#define	MCFSIM_PBDAT		(MCF_MBAR + 0x8e) /* Port B Data (r/w) */
+#define	MCFSIM_PCDDR		(MCF_MBAR + 0x94) /* Port C Direction (r/w) */
+#define	MCFSIM_PCDAT		(MCF_MBAR + 0x96) /* Port C Data (r/w) */
+#define	MCFSIM_PDCNT		(MCF_MBAR + 0x98) /* Port D Control (r/w) */
 
+/*
+ *	Define system peripheral IRQ usage.
+ */
+#define	MCFINT_VECBASE		64		/* Base of interrupts */
+#define	MCF_IRQ_SPURIOUS	64		/* User Spurious */
+#define	MCF_IRQ_EINT1		65		/* External Interrupt 1 */
+#define	MCF_IRQ_EINT2		66		/* External Interrupt 2 */
+#define	MCF_IRQ_EINT3		67		/* External Interrupt 3 */
+#define	MCF_IRQ_EINT4		68		/* External Interrupt 4 */
+#define	MCF_IRQ_TIMER1		69		/* Timer 1 */
+#define	MCF_IRQ_TIMER2		70		/* Timer 2 */
+#define	MCF_IRQ_TIMER3		71		/* Timer 3 */
+#define	MCF_IRQ_TIMER4		72		/* Timer 4 */
+#define	MCF_IRQ_UART1		73		/* UART 1 */
+#define	MCF_IRQ_UART2		74		/* UART 2 */
+#define	MCF_IRQ_PLIP		75		/* PLIC 2Khz Periodic */
+#define	MCF_IRQ_PLIA		76		/* PLIC Asynchronous */
+#define	MCF_IRQ_USB0		77		/* USB Endpoint 0 */
+#define	MCF_IRQ_USB1		78		/* USB Endpoint 1 */
+#define	MCF_IRQ_USB2		79		/* USB Endpoint 2 */
+#define	MCF_IRQ_USB3		80		/* USB Endpoint 3 */
+#define	MCF_IRQ_USB4		81		/* USB Endpoint 4 */
+#define	MCF_IRQ_USB5		82		/* USB Endpoint 5 */
+#define	MCF_IRQ_USB6		83		/* USB Endpoint 6 */
+#define	MCF_IRQ_USB7		84		/* USB Endpoint 7 */
+#define	MCF_IRQ_DMA		85		/* DMA Controller */
+#define	MCF_IRQ_ERX		86		/* Ethernet Receiver */
+#define	MCF_IRQ_ETX		87		/* Ethernet Transmitter */
+#define	MCF_IRQ_ENTC		88		/* Ethernet Non-Time Critical */
+#define	MCF_IRQ_QSPI		89		/* Queued Serial Interface */
+#define	MCF_IRQ_EINT5		90		/* External Interrupt 5 */
+#define	MCF_IRQ_EINT6		91		/* External Interrupt 6 */
+#define	MCF_IRQ_SWTO		92		/* Software Watchdog */
+#define	MCFINT_VECMAX		95		/* Maxmum interrupt */
 
+#define	MCF_IRQ_TIMER		MCF_IRQ_TIMER1
+#define	MCF_IRQ_PROFILER	MCF_IRQ_TIMER2
+
+/*
+ * Generic GPIO support
+ */
+#define MCFGPIO_PIN_MAX			48
+#define MCFGPIO_IRQ_MAX			-1
+#define MCFGPIO_IRQ_VECBASE		-1
 /****************************************************************************/
 #endif	/* m5272sim_h */
diff --git a/arch/m68k/include/asm/m527xsim.h b/arch/m68k/include/asm/m527xsim.h
index 95f4f8e..453356d 100644
--- a/arch/m68k/include/asm/m527xsim.h
+++ b/arch/m68k/include/asm/m527xsim.h
@@ -54,6 +54,175 @@
 #define	MCFSIM_DMR1		0x5c		/* SDRAM address mask 1 */
 #endif
 
+
+#ifdef CONFIG_M5271
+#define MCFGPIO_PODR_ADDR	(MCF_IPSBAR + 0x100000)
+#define MCFGPIO_PODR_DATAH	(MCF_IPSBAR + 0x100001)
+#define MCFGPIO_PODR_DATAL	(MCF_IPSBAR + 0x100002)
+#define MCFGPIO_PODR_BUSCTL	(MCF_IPSBAR + 0x100003)
+#define MCFGPIO_PODR_BS		(MCF_IPSBAR + 0x100004)
+#define MCFGPIO_PODR_CS		(MCF_IPSBAR + 0x100005)
+#define MCFGPIO_PODR_SDRAM	(MCF_IPSBAR + 0x100006)
+#define MCFGPIO_PODR_FECI2C	(MCF_IPSBAR + 0x100007)
+#define MCFGPIO_PODR_UARTH	(MCF_IPSBAR + 0x100008)
+#define MCFGPIO_PODR_UARTL	(MCF_IPSBAR + 0x100009)
+#define MCFGPIO_PODR_QSPI	(MCF_IPSBAR + 0x10000A)
+#define MCFGPIO_PODR_TIMER	(MCF_IPSBAR + 0x10000B)
+
+#define MCFGPIO_PDDR_ADDR	(MCF_IPSBAR + 0x100010)
+#define MCFGPIO_PDDR_DATAH	(MCF_IPSBAR + 0x100011)
+#define MCFGPIO_PDDR_DATAL	(MCF_IPSBAR + 0x100012)
+#define MCFGPIO_PDDR_BUSCTL	(MCF_IPSBAR + 0x100013)
+#define MCFGPIO_PDDR_BS		(MCF_IPSBAR + 0x100014)
+#define MCFGPIO_PDDR_CS		(MCF_IPSBAR + 0x100015)
+#define MCFGPIO_PDDR_SDRAM	(MCF_IPSBAR + 0x100016)
+#define MCFGPIO_PDDR_FECI2C	(MCF_IPSBAR + 0x100017)
+#define MCFGPIO_PDDR_UARTH	(MCF_IPSBAR + 0x100018)
+#define MCFGPIO_PDDR_UARTL	(MCF_IPSBAR + 0x100019)
+#define MCFGPIO_PDDR_QSPI	(MCF_IPSBAR + 0x10001A)
+#define MCFGPIO_PDDR_TIMER	(MCF_IPSBAR + 0x10001B)
+
+#define MCFGPIO_PPDSDR_ADDR	(MCF_IPSBAR + 0x100020)
+#define MCFGPIO_PPDSDR_DATAH	(MCF_IPSBAR + 0x100021)
+#define MCFGPIO_PPDSDR_DATAL	(MCF_IPSBAR + 0x100022)
+#define MCFGPIO_PPDSDR_BUSCTL	(MCF_IPSBAR + 0x100023)
+#define MCFGPIO_PPDSDR_BS	(MCF_IPSBAR + 0x100024)
+#define MCFGPIO_PPDSDR_CS	(MCF_IPSBAR + 0x100025)
+#define MCFGPIO_PPDSDR_SDRAM	(MCF_IPSBAR + 0x100026)
+#define MCFGPIO_PPDSDR_FECI2C	(MCF_IPSBAR + 0x100027)
+#define MCFGPIO_PPDSDR_UARTH	(MCF_IPSBAR + 0x100028)
+#define MCFGPIO_PPDSDR_UARTL	(MCF_IPSBAR + 0x100029)
+#define MCFGPIO_PPDSDR_QSPI	(MCF_IPSBAR + 0x10002A)
+#define MCFGPIO_PPDSDR_TIMER	(MCF_IPSBAR + 0x10002B)
+
+#define MCFGPIO_PCLRR_ADDR	(MCF_IPSBAR + 0x100030)
+#define MCFGPIO_PCLRR_DATAH	(MCF_IPSBAR + 0x100031)
+#define MCFGPIO_PCLRR_DATAL	(MCF_IPSBAR + 0x100032)
+#define MCFGPIO_PCLRR_BUSCTL	(MCF_IPSBAR + 0x100033)
+#define MCFGPIO_PCLRR_BS	(MCF_IPSBAR + 0x100034)
+#define MCFGPIO_PCLRR_CS	(MCF_IPSBAR + 0x100035)
+#define MCFGPIO_PCLRR_SDRAM	(MCF_IPSBAR + 0x100036)
+#define MCFGPIO_PCLRR_FECI2C	(MCF_IPSBAR + 0x100037)
+#define MCFGPIO_PCLRR_UARTH	(MCF_IPSBAR + 0x100038)
+#define MCFGPIO_PCLRR_UARTL	(MCF_IPSBAR + 0x100039)
+#define MCFGPIO_PCLRR_QSPI	(MCF_IPSBAR + 0x10003A)
+#define MCFGPIO_PCLRR_TIMER	(MCF_IPSBAR + 0x10003B)
+
+/*
+ * Generic GPIO support
+ */
+#define MCFGPIO_PODR			MCFGPIO_PODR_ADDR
+#define MCFGPIO_PDDR			MCFGPIO_PDDR_ADDR
+#define MCFGPIO_PPDR			MCFGPIO_PPDSDR_ADDR
+#define MCFGPIO_SETR			MCFGPIO_PPDSDR_ADDR
+#define MCFGPIO_CLRR			MCFGPIO_PCLRR_ADDR
+
+#define MCFGPIO_PIN_MAX			100
+#define MCFGPIO_IRQ_MAX			8
+#define MCFGPIO_IRQ_VECBASE		MCFINT_VECBASE
+#endif
+
+#ifdef CONFIG_M5275
+#define MCFGPIO_PODR_BUSCTL	(MCF_IPSBAR + 0x100004)
+#define MCFGPIO_PODR_ADDR	(MCF_IPSBAR + 0x100005)
+#define MCFGPIO_PODR_CS		(MCF_IPSBAR + 0x100008)
+#define MCFGPIO_PODR_FEC0H	(MCF_IPSBAR + 0x10000A)
+#define MCFGPIO_PODR_FEC0L	(MCF_IPSBAR + 0x10000B)
+#define MCFGPIO_PODR_FECI2C	(MCF_IPSBAR + 0x10000C)
+#define MCFGPIO_PODR_QSPI	(MCF_IPSBAR + 0x10000D)
+#define MCFGPIO_PODR_SDRAM	(MCF_IPSBAR + 0x10000E)
+#define MCFGPIO_PODR_TIMERH	(MCF_IPSBAR + 0x10000F)
+#define MCFGPIO_PODR_TIMERL	(MCF_IPSBAR + 0x100010)
+#define MCFGPIO_PODR_UARTL	(MCF_IPSBAR + 0x100011)
+#define MCFGPIO_PODR_FEC1H	(MCF_IPSBAR + 0x100012)
+#define MCFGPIO_PODR_FEC1L	(MCF_IPSBAR + 0x100013)
+#define MCFGPIO_PODR_BS		(MCF_IPSBAR + 0x100014)
+#define MCFGPIO_PODR_IRQ	(MCF_IPSBAR + 0x100015)
+#define MCFGPIO_PODR_USBH	(MCF_IPSBAR + 0x100016)
+#define MCFGPIO_PODR_USBL	(MCF_IPSBAR + 0x100017)
+#define MCFGPIO_PODR_UARTH	(MCF_IPSBAR + 0x100018)
+
+#define MCFGPIO_PDDR_BUSCTL	(MCF_IPSBAR + 0x100020)
+#define MCFGPIO_PDDR_ADDR	(MCF_IPSBAR + 0x100021)
+#define MCFGPIO_PDDR_CS		(MCF_IPSBAR + 0x100024)
+#define MCFGPIO_PDDR_FEC0H	(MCF_IPSBAR + 0x100026)
+#define MCFGPIO_PDDR_FEC0L	(MCF_IPSBAR + 0x100027)
+#define MCFGPIO_PDDR_FECI2C	(MCF_IPSBAR + 0x100028)
+#define MCFGPIO_PDDR_QSPI	(MCF_IPSBAR + 0x100029)
+#define MCFGPIO_PDDR_SDRAM	(MCF_IPSBAR + 0x10002A)
+#define MCFGPIO_PDDR_TIMERH	(MCF_IPSBAR + 0x10002B)
+#define MCFGPIO_PDDR_TIMERL	(MCF_IPSBAR + 0x10002C)
+#define MCFGPIO_PDDR_UARTL	(MCF_IPSBAR + 0x10002D)
+#define MCFGPIO_PDDR_FEC1H	(MCF_IPSBAR + 0x10002E)
+#define MCFGPIO_PDDR_FEC1L	(MCF_IPSBAR + 0x10002F)
+#define MCFGPIO_PDDR_BS		(MCF_IPSBAR + 0x100030)
+#define MCFGPIO_PDDR_IRQ	(MCF_IPSBAR + 0x100031)
+#define MCFGPIO_PDDR_USBH	(MCF_IPSBAR + 0x100032)
+#define MCFGPIO_PDDR_USBL	(MCF_IPSBAR + 0x100033)
+#define MCFGPIO_PDDR_UARTH	(MCF_IPSBAR + 0x100034)
+
+#define MCFGPIO_PPDSDR_BUSCTL	(MCF_IPSBAR + 0x10003C)
+#define MCFGPIO_PPDSDR_ADDR	(MCF_IPSBAR + 0x10003D)
+#define MCFGPIO_PPDSDR_CS	(MCF_IPSBAR + 0x100040)
+#define MCFGPIO_PPDSDR_FEC0H	(MCF_IPSBAR + 0x100042)
+#define MCFGPIO_PPDSDR_FEC0L	(MCF_IPSBAR + 0x100043)
+#define MCFGPIO_PPDSDR_FECI2C	(MCF_IPSBAR + 0x100044)
+#define MCFGPIO_PPDSDR_QSPI	(MCF_IPSBAR + 0x100045)
+#define MCFGPIO_PPDSDR_SDRAM	(MCF_IPSBAR + 0x100046)
+#define MCFGPIO_PPDSDR_TIMERH	(MCF_IPSBAR + 0x100047)
+#define MCFGPIO_PPDSDR_TIMERL	(MCF_IPSBAR + 0x100048)
+#define MCFGPIO_PPDSDR_UARTL	(MCF_IPSBAR + 0x100049)
+#define MCFGPIO_PPDSDR_FEC1H	(MCF_IPSBAR + 0x10004A)
+#define MCFGPIO_PPDSDR_FEC1L	(MCF_IPSBAR + 0x10004B)
+#define MCFGPIO_PPDSDR_BS	(MCF_IPSBAR + 0x10004C)
+#define MCFGPIO_PPDSDR_IRQ	(MCF_IPSBAR + 0x10004D)
+#define MCFGPIO_PPDSDR_USBH	(MCF_IPSBAR + 0x10004E)
+#define MCFGPIO_PPDSDR_USBL	(MCF_IPSBAR + 0x10004F)
+#define MCFGPIO_PPDSDR_UARTH	(MCF_IPSBAR + 0x100050)
+
+#define MCFGPIO_PCLRR_BUSCTL	(MCF_IPSBAR + 0x100058)
+#define MCFGPIO_PCLRR_ADDR	(MCF_IPSBAR + 0x100059)
+#define MCFGPIO_PCLRR_CS	(MCF_IPSBAR + 0x10005C)
+#define MCFGPIO_PCLRR_FEC0H	(MCF_IPSBAR + 0x10005E)
+#define MCFGPIO_PCLRR_FEC0L	(MCF_IPSBAR + 0x10005F)
+#define MCFGPIO_PCLRR_FECI2C	(MCF_IPSBAR + 0x100060)
+#define MCFGPIO_PCLRR_QSPI	(MCF_IPSBAR + 0x100061)
+#define MCFGPIO_PCLRR_SDRAM	(MCF_IPSBAR + 0x100062)
+#define MCFGPIO_PCLRR_TIMERH	(MCF_IPSBAR + 0x100063)
+#define MCFGPIO_PCLRR_TIMERL	(MCF_IPSBAR + 0x100064)
+#define MCFGPIO_PCLRR_UARTL	(MCF_IPSBAR + 0x100065)
+#define MCFGPIO_PCLRR_FEC1H	(MCF_IPSBAR + 0x100066)
+#define MCFGPIO_PCLRR_FEC1L	(MCF_IPSBAR + 0x100067)
+#define MCFGPIO_PCLRR_BS	(MCF_IPSBAR + 0x100068)
+#define MCFGPIO_PCLRR_IRQ	(MCF_IPSBAR + 0x100069)
+#define MCFGPIO_PCLRR_USBH	(MCF_IPSBAR + 0x10006A)
+#define MCFGPIO_PCLRR_USBL	(MCF_IPSBAR + 0x10006B)
+#define MCFGPIO_PCLRR_UARTH	(MCF_IPSBAR + 0x10006C)
+
+
+/*
+ * Generic GPIO support
+ */
+#define MCFGPIO_PODR			MCFGPIO_PODR_BUSCTL
+#define MCFGPIO_PDDR			MCFGPIO_PDDR_BUSCTL
+#define MCFGPIO_PPDR			MCFGPIO_PPDSDR_BUSCTL
+#define MCFGPIO_SETR			MCFGPIO_PPDSDR_BUSCTL
+#define MCFGPIO_CLRR			MCFGPIO_PCLRR_BUSCTL
+
+#define MCFGPIO_PIN_MAX			148
+#define MCFGPIO_IRQ_MAX			8
+#define MCFGPIO_IRQ_VECBASE		MCFINT_VECBASE
+#endif
+
+/*
+ * EPort
+ */
+
+#define MCFEPORT_EPDDR		(MCF_IPSBAR + 0x130002)
+#define MCFEPORT_EPDR		(MCF_IPSBAR + 0x130004)
+#define MCFEPORT_EPPDR		(MCF_IPSBAR + 0x130005)
+
+
 /*
  *	GPIO pins setups to enable the UARTs.
  */
diff --git a/arch/m68k/include/asm/m528xsim.h b/arch/m68k/include/asm/m528xsim.h
index d79c49f..e2ad1f4 100644
--- a/arch/m68k/include/asm/m528xsim.h
+++ b/arch/m68k/include/asm/m528xsim.h
@@ -41,6 +41,157 @@
 #define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
 
 /*
+ * 	GPIO registers
+ */
+#define MCFGPIO_PORTA		(MCF_IPSBAR + 0x00100000)
+#define MCFGPIO_PORTB		(MCF_IPSBAR + 0x00100001)
+#define MCFGPIO_PORTC		(MCF_IPSBAR + 0x00100002)
+#define MCFGPIO_PORTD		(MCF_IPSBAR + 0x00100003)
+#define MCFGPIO_PORTE		(MCF_IPSBAR + 0x00100004)
+#define MCFGPIO_PORTF		(MCF_IPSBAR + 0x00100005)
+#define MCFGPIO_PORTG		(MCF_IPSBAR + 0x00100006)
+#define MCFGPIO_PORTH		(MCF_IPSBAR + 0x00100007)
+#define MCFGPIO_PORTJ		(MCF_IPSBAR + 0x00100008)
+#define MCFGPIO_PORTDD		(MCF_IPSBAR + 0x00100009)
+#define MCFGPIO_PORTEH		(MCF_IPSBAR + 0x0010000A)
+#define MCFGPIO_PORTEL		(MCF_IPSBAR + 0x0010000B)
+#define MCFGPIO_PORTAS		(MCF_IPSBAR + 0x0010000C)
+#define MCFGPIO_PORTQS		(MCF_IPSBAR + 0x0010000D)
+#define MCFGPIO_PORTSD		(MCF_IPSBAR + 0x0010000E)
+#define MCFGPIO_PORTTC		(MCF_IPSBAR + 0x0010000F)
+#define MCFGPIO_PORTTD		(MCF_IPSBAR + 0x00100010)
+#define MCFGPIO_PORTUA		(MCF_IPSBAR + 0x00100011)
+
+#define MCFGPIO_DDRA		(MCF_IPSBAR + 0x00100014)
+#define MCFGPIO_DDRB		(MCF_IPSBAR + 0x00100015)
+#define MCFGPIO_DDRC		(MCF_IPSBAR + 0x00100016)
+#define MCFGPIO_DDRD		(MCF_IPSBAR + 0x00100017)
+#define MCFGPIO_DDRE		(MCF_IPSBAR + 0x00100018)
+#define MCFGPIO_DDRF		(MCF_IPSBAR + 0x00100019)
+#define MCFGPIO_DDRG		(MCF_IPSBAR + 0x0010001A)
+#define MCFGPIO_DDRH		(MCF_IPSBAR + 0x0010001B)
+#define MCFGPIO_DDRJ		(MCF_IPSBAR + 0x0010001C)
+#define MCFGPIO_DDRDD		(MCF_IPSBAR + 0x0010001D)
+#define MCFGPIO_DDREH		(MCF_IPSBAR + 0x0010001E)
+#define MCFGPIO_DDREL		(MCF_IPSBAR + 0x0010001F)
+#define MCFGPIO_DDRAS		(MCF_IPSBAR + 0x00100020)
+#define MCFGPIO_DDRQS		(MCF_IPSBAR + 0x00100021)
+#define MCFGPIO_DDRSD		(MCF_IPSBAR + 0x00100022)
+#define MCFGPIO_DDRTC		(MCF_IPSBAR + 0x00100023)
+#define MCFGPIO_DDRTD		(MCF_IPSBAR + 0x00100024)
+#define MCFGPIO_DDRUA		(MCF_IPSBAR + 0x00100025)
+
+#define MCFGPIO_PORTAP		(MCF_IPSBAR + 0x00100028)
+#define MCFGPIO_PORTBP		(MCF_IPSBAR + 0x00100029)
+#define MCFGPIO_PORTCP		(MCF_IPSBAR + 0x0010002A)
+#define MCFGPIO_PORTDP		(MCF_IPSBAR + 0x0010002B)
+#define MCFGPIO_PORTEP		(MCF_IPSBAR + 0x0010002C)
+#define MCFGPIO_PORTFP		(MCF_IPSBAR + 0x0010002D)
+#define MCFGPIO_PORTGP		(MCF_IPSBAR + 0x0010002E)
+#define MCFGPIO_PORTHP		(MCF_IPSBAR + 0x0010002F)
+#define MCFGPIO_PORTJP		(MCF_IPSBAR + 0x00100030)
+#define MCFGPIO_PORTDDP		(MCF_IPSBAR + 0x00100031)
+#define MCFGPIO_PORTEHP		(MCF_IPSBAR + 0x00100032)
+#define MCFGPIO_PORTELP		(MCF_IPSBAR + 0x00100033)
+#define MCFGPIO_PORTASP		(MCF_IPSBAR + 0x00100034)
+#define MCFGPIO_PORTQSP		(MCF_IPSBAR + 0x00100035)
+#define MCFGPIO_PORTSDP		(MCF_IPSBAR + 0x00100036)
+#define MCFGPIO_PORTTCP		(MCF_IPSBAR + 0x00100037)
+#define MCFGPIO_PORTTDP		(MCF_IPSBAR + 0x00100038)
+#define MCFGPIO_PORTUAP		(MCF_IPSBAR + 0x00100039)
+
+#define MCFGPIO_SETA		(MCF_IPSBAR + 0x00100028)
+#define MCFGPIO_SETB		(MCF_IPSBAR + 0x00100029)
+#define MCFGPIO_SETC		(MCF_IPSBAR + 0x0010002A)
+#define MCFGPIO_SETD		(MCF_IPSBAR + 0x0010002B)
+#define MCFGPIO_SETE		(MCF_IPSBAR + 0x0010002C)
+#define MCFGPIO_SETF		(MCF_IPSBAR + 0x0010002D)
+#define MCFGPIO_SETG		(MCF_IPSBAR + 0x0010002E)
+#define MCFGPIO_SETH		(MCF_IPSBAR + 0x0010002F)
+#define MCFGPIO_SETJ		(MCF_IPSBAR + 0x00100030)
+#define MCFGPIO_SETDD		(MCF_IPSBAR + 0x00100031)
+#define MCFGPIO_SETEH		(MCF_IPSBAR + 0x00100032)
+#define MCFGPIO_SETEL		(MCF_IPSBAR + 0x00100033)
+#define MCFGPIO_SETAS		(MCF_IPSBAR + 0x00100034)
+#define MCFGPIO_SETQS		(MCF_IPSBAR + 0x00100035)
+#define MCFGPIO_SETSD		(MCF_IPSBAR + 0x00100036)
+#define MCFGPIO_SETTC		(MCF_IPSBAR + 0x00100037)
+#define MCFGPIO_SETTD		(MCF_IPSBAR + 0x00100038)
+#define MCFGPIO_SETUA		(MCF_IPSBAR + 0x00100039)
+
+#define MCFGPIO_CLRA		(MCF_IPSBAR + 0x0010003C)
+#define MCFGPIO_CLRB		(MCF_IPSBAR + 0x0010003D)
+#define MCFGPIO_CLRC		(MCF_IPSBAR + 0x0010003E)
+#define MCFGPIO_CLRD		(MCF_IPSBAR + 0x0010003F)
+#define MCFGPIO_CLRE		(MCF_IPSBAR + 0x00100040)
+#define MCFGPIO_CLRF		(MCF_IPSBAR + 0x00100041)
+#define MCFGPIO_CLRG		(MCF_IPSBAR + 0x00100042)
+#define MCFGPIO_CLRH		(MCF_IPSBAR + 0x00100043)
+#define MCFGPIO_CLRJ		(MCF_IPSBAR + 0x00100044)
+#define MCFGPIO_CLRDD		(MCF_IPSBAR + 0x00100045)
+#define MCFGPIO_CLREH		(MCF_IPSBAR + 0x00100046)
+#define MCFGPIO_CLREL		(MCF_IPSBAR + 0x00100047)
+#define MCFGPIO_CLRAS		(MCF_IPSBAR + 0x00100048)
+#define MCFGPIO_CLRQS		(MCF_IPSBAR + 0x00100049)
+#define MCFGPIO_CLRSD		(MCF_IPSBAR + 0x0010004A)
+#define MCFGPIO_CLRTC		(MCF_IPSBAR + 0x0010004B)
+#define MCFGPIO_CLRTD		(MCF_IPSBAR + 0x0010004C)
+#define MCFGPIO_CLRUA		(MCF_IPSBAR + 0x0010004D)
+
+#define MCFGPIO_PBCDPAR		(MCF_IPSBAR + 0x00100050)
+#define MCFGPIO_PFPAR		(MCF_IPSBAR + 0x00100051)
+#define MCFGPIO_PEPAR		(MCF_IPSBAR + 0x00100052)
+#define MCFGPIO_PJPAR		(MCF_IPSBAR + 0x00100054)
+#define MCFGPIO_PSDPAR		(MCF_IPSBAR + 0x00100055)
+#define MCFGPIO_PASPAR		(MCF_IPSBAR + 0x00100056)
+#define MCFGPIO_PEHLPAR		(MCF_IPSBAR + 0x00100058)
+#define MCFGPIO_PQSPAR		(MCF_IPSBAR + 0x00100059)
+#define MCFGPIO_PTCPAR		(MCF_IPSBAR + 0x0010005A)
+#define MCFGPIO_PTDPAR		(MCF_IPSBAR + 0x0010005B)
+#define MCFGPIO_PUAPAR		(MCF_IPSBAR + 0x0010005C)
+
+/*
+ * 	Edge Port registers
+ */
+#define MCFEPORT_EPPAR		(MCF_IPSBAR + 0x00130000)
+#define MCFEPORT_EPDDR		(MCF_IPSBAR + 0x00130002)
+#define MCFEPORT_EPIER		(MCF_IPSBAR + 0x00130003)
+#define MCFEPORT_EPDR		(MCF_IPSBAR + 0x00130004)
+#define MCFEPORT_EPPDR		(MCF_IPSBAR + 0x00130005)
+#define MCFEPORT_EPFR		(MCF_IPSBAR + 0x00130006)
+
+/*
+ * 	Queued ADC registers
+ */
+#define MCFQADC_PORTQA		(MCF_IPSBAR + 0x00190006)
+#define MCFQADC_PORTQB		(MCF_IPSBAR + 0x00190007)
+#define MCFQADC_DDRQA		(MCF_IPSBAR + 0x00190008)
+#define MCFQADC_DDRQB		(MCF_IPSBAR + 0x00190009)
+
+/*
+ * 	General Purpose Timers registers
+ */
+#define MCFGPTA_GPTPORT		(MCF_IPSBAR + 0x001A001D)
+#define MCFGPTA_GPTDDR		(MCF_IPSBAR + 0x001A001E)
+#define MCFGPTB_GPTPORT		(MCF_IPSBAR + 0x001B001D)
+#define MCFGPTB_GPTDDR		(MCF_IPSBAR + 0x001B001E)
+/*
+ *
+ * definitions for generic gpio support
+ *
+ */
+#define MCFGPIO_PODR		MCFGPIO_PORTA	/* port output data */
+#define MCFGPIO_PDDR		MCFGPIO_DDRA	/* port data direction */
+#define MCFGPIO_PPDR		MCFGPIO_PORTAP	/* port pin data */
+#define MCFGPIO_SETR		MCFGPIO_SETA	/* set output */
+#define MCFGPIO_CLRR		MCFGPIO_CLRA	/* clr output */
+
+#define MCFGPIO_IRQ_MAX		8
+#define MCFGPIO_IRQ_VECBASE	MCFINT_VECBASE
+#define MCFGPIO_PIN_MAX		180
+
+
+/*
  *	Derek Cheung - 6 Feb 2005
  *		add I2C and QSPI register definition using Freescale's MCF5282
  */
diff --git a/arch/m68k/include/asm/m5307sim.h b/arch/m68k/include/asm/m5307sim.h
index 5886728..c6830e5 100644
--- a/arch/m68k/include/asm/m5307sim.h
+++ b/arch/m68k/include/asm/m5307sim.h
@@ -90,8 +90,15 @@
 #define MCFSIM_DACR1		0x110		/* DRAM 1 Addr and Ctrl (r/w) */
 #define MCFSIM_DMR1		0x114		/* DRAM 1 Mask reg (r/w) */
 
-#define	MCFSIM_PADDR		0x244		/* Parallel Direction (r/w) */
-#define	MCFSIM_PADAT		0x248		/* Parallel Data (r/w) */
+#define	MCFSIM_PADDR		(MCF_MBAR + 0x244)
+#define	MCFSIM_PADAT		(MCF_MBAR + 0x248)
+
+/*
+ * Generic GPIO support
+ */
+#define MCFGPIO_PIN_MAX			16
+#define MCFGPIO_IRQ_MAX			-1
+#define MCFGPIO_IRQ_VECBASE		-1
 
 
 /* Definition offset address for CS2-7  -- old mask 5307 */
@@ -117,22 +124,6 @@
 #define	MCFSIM_DMA2ICR		MCFSIM_ICR8	/* DMA 2 ICR */
 #define	MCFSIM_DMA3ICR		MCFSIM_ICR9	/* DMA 3 ICR */
 
-#if defined(CONFIG_M5307)
-#define	MCFSIM_IMR_MASKALL	0x3fffe		/* All SIM intr sources */
-#endif
-
-/*
- *	Macro to set IMR register. It is 32 bits on the 5307.
- */
-#define	mcf_getimr()		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR))
-
-#define	mcf_setimr(imr)		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR)) = (imr);
-
-#define	mcf_getipr()		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPR))
-
 
 /*
  *	Some symbol defines for the Parallel Port Pin Assignment Register
@@ -149,6 +140,11 @@
 #define IRQ3_LEVEL6	0x40
 #define IRQ1_LEVEL2	0x20
 
+/*
+ *	Define system peripheral IRQ usage.
+ */
+#define	MCF_IRQ_TIMER		30		/* Timer0, Level 6 */
+#define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
 
 /*
  *	Define the Cache register flags.
diff --git a/arch/m68k/include/asm/m532xsim.h b/arch/m68k/include/asm/m532xsim.h
index eb7fd44..36bf15a 100644
--- a/arch/m68k/include/asm/m532xsim.h
+++ b/arch/m68k/include/asm/m532xsim.h
@@ -56,47 +56,21 @@
 #define	MCFSIM_DMA3ICR		MCFSIM_ICR9	/* DMA 3 ICR */
 
 
-#define	MCFSIM_IMR_MASKALL	0xFFFFFFFF	/* All SIM intr sources */
-
-#define MCFSIM_IMR_SIMR0	0xFC04801C
-#define MCFSIM_IMR_SIMR1	0xFC04C01C
-#define MCFSIM_IMR_CIMR0	0xFC04801D
-#define MCFSIM_IMR_CIMR1	0xFC04C01D
+#define	MCFINTC0_SIMR		0xFC04801C
+#define	MCFINTC0_CIMR		0xFC04801D
+#define	MCFINTC0_ICR0		0xFC048040
+#define	MCFINTC1_SIMR		0xFC04C01C
+#define	MCFINTC1_CIMR		0xFC04C01D
+#define	MCFINTC1_ICR0		0xFC04C040
 
 #define MCFSIM_ICR_TIMER1	(0xFC048040+32)
 #define MCFSIM_ICR_TIMER2	(0xFC048040+33)
 
-
 /*
- *	Macro to set IMR register. It is 32 bits on the 5307.
+ *	Define system peripheral IRQ usage.
  */
-#define	mcf_getimr()		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR))
-
-#define	mcf_setimr(imr)		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR)) = (imr);
-
-#define	mcf_getipr()		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPR))
-
-#define	mcf_getiprl()		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPRL))
-
-#define	mcf_getiprh()		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPRH))
-
-
-#define mcf_enable_irq0(irq)		\
-	*((volatile unsigned char*) (MCFSIM_IMR_CIMR0)) = (irq);
-
-#define mcf_enable_irq1(irq)		\
-	*((volatile unsigned char*) (MCFSIM_IMR_CIMR1)) = (irq);
-
-#define mcf_disable_irq0(irq)		\
-	*((volatile unsigned char*) (MCFSIM_IMR_SIMR0)) = (irq);
-
-#define mcf_disable_irq1(irq)		\
-	*((volatile unsigned char*) (MCFSIM_IMR_SIMR1)) = (irq);
+#define	MCF_IRQ_TIMER		(64 + 32)	/* Timer0 */
+#define	MCF_IRQ_PROFILER	(64 + 33)	/* Timer1 */
 
 /*
  *	Define the Cache register flags.
@@ -422,70 +396,70 @@
  *********************************************************************/
 
 /* Register read/write macros */
-#define MCF_GPIO_PODR_FECH		MCF_REG08(0xFC0A4000)
-#define MCF_GPIO_PODR_FECL		MCF_REG08(0xFC0A4001)
-#define MCF_GPIO_PODR_SSI		MCF_REG08(0xFC0A4002)
-#define MCF_GPIO_PODR_BUSCTL		MCF_REG08(0xFC0A4003)
-#define MCF_GPIO_PODR_BE		MCF_REG08(0xFC0A4004)
-#define MCF_GPIO_PODR_CS		MCF_REG08(0xFC0A4005)
-#define MCF_GPIO_PODR_PWM		MCF_REG08(0xFC0A4006)
-#define MCF_GPIO_PODR_FECI2C		MCF_REG08(0xFC0A4007)
-#define MCF_GPIO_PODR_UART		MCF_REG08(0xFC0A4009)
-#define MCF_GPIO_PODR_QSPI		MCF_REG08(0xFC0A400A)
-#define MCF_GPIO_PODR_TIMER		MCF_REG08(0xFC0A400B)
-#define MCF_GPIO_PODR_LCDDATAH		MCF_REG08(0xFC0A400D)
-#define MCF_GPIO_PODR_LCDDATAM		MCF_REG08(0xFC0A400E)
-#define MCF_GPIO_PODR_LCDDATAL		MCF_REG08(0xFC0A400F)
-#define MCF_GPIO_PODR_LCDCTLH		MCF_REG08(0xFC0A4010)
-#define MCF_GPIO_PODR_LCDCTLL		MCF_REG08(0xFC0A4011)
-#define MCF_GPIO_PDDR_FECH		MCF_REG08(0xFC0A4014)
-#define MCF_GPIO_PDDR_FECL		MCF_REG08(0xFC0A4015)
-#define MCF_GPIO_PDDR_SSI		MCF_REG08(0xFC0A4016)
-#define MCF_GPIO_PDDR_BUSCTL		MCF_REG08(0xFC0A4017)
-#define MCF_GPIO_PDDR_BE		MCF_REG08(0xFC0A4018)
-#define MCF_GPIO_PDDR_CS		MCF_REG08(0xFC0A4019)
-#define MCF_GPIO_PDDR_PWM		MCF_REG08(0xFC0A401A)
-#define MCF_GPIO_PDDR_FECI2C		MCF_REG08(0xFC0A401B)
-#define MCF_GPIO_PDDR_UART		MCF_REG08(0xFC0A401C)
-#define MCF_GPIO_PDDR_QSPI		MCF_REG08(0xFC0A401E)
-#define MCF_GPIO_PDDR_TIMER		MCF_REG08(0xFC0A401F)
-#define MCF_GPIO_PDDR_LCDDATAH		MCF_REG08(0xFC0A4021)
-#define MCF_GPIO_PDDR_LCDDATAM		MCF_REG08(0xFC0A4022)
-#define MCF_GPIO_PDDR_LCDDATAL		MCF_REG08(0xFC0A4023)
-#define MCF_GPIO_PDDR_LCDCTLH		MCF_REG08(0xFC0A4024)
-#define MCF_GPIO_PDDR_LCDCTLL		MCF_REG08(0xFC0A4025)
-#define MCF_GPIO_PPDSDR_FECH		MCF_REG08(0xFC0A4028)
-#define MCF_GPIO_PPDSDR_FECL		MCF_REG08(0xFC0A4029)
-#define MCF_GPIO_PPDSDR_SSI		MCF_REG08(0xFC0A402A)
-#define MCF_GPIO_PPDSDR_BUSCTL		MCF_REG08(0xFC0A402B)
-#define MCF_GPIO_PPDSDR_BE		MCF_REG08(0xFC0A402C)
-#define MCF_GPIO_PPDSDR_CS		MCF_REG08(0xFC0A402D)
-#define MCF_GPIO_PPDSDR_PWM		MCF_REG08(0xFC0A402E)
-#define MCF_GPIO_PPDSDR_FECI2C		MCF_REG08(0xFC0A402F)
-#define MCF_GPIO_PPDSDR_UART		MCF_REG08(0xFC0A4031)
-#define MCF_GPIO_PPDSDR_QSPI		MCF_REG08(0xFC0A4032)
-#define MCF_GPIO_PPDSDR_TIMER		MCF_REG08(0xFC0A4033)
-#define MCF_GPIO_PPDSDR_LCDDATAH	MCF_REG08(0xFC0A4035)
-#define MCF_GPIO_PPDSDR_LCDDATAM	MCF_REG08(0xFC0A4036)
-#define MCF_GPIO_PPDSDR_LCDDATAL	MCF_REG08(0xFC0A4037)
-#define MCF_GPIO_PPDSDR_LCDCTLH		MCF_REG08(0xFC0A4038)
-#define MCF_GPIO_PPDSDR_LCDCTLL		MCF_REG08(0xFC0A4039)
-#define MCF_GPIO_PCLRR_FECH		MCF_REG08(0xFC0A403C)
-#define MCF_GPIO_PCLRR_FECL		MCF_REG08(0xFC0A403D)
-#define MCF_GPIO_PCLRR_SSI		MCF_REG08(0xFC0A403E)
-#define MCF_GPIO_PCLRR_BUSCTL		MCF_REG08(0xFC0A403F)
-#define MCF_GPIO_PCLRR_BE		MCF_REG08(0xFC0A4040)
-#define MCF_GPIO_PCLRR_CS		MCF_REG08(0xFC0A4041)
-#define MCF_GPIO_PCLRR_PWM		MCF_REG08(0xFC0A4042)
-#define MCF_GPIO_PCLRR_FECI2C		MCF_REG08(0xFC0A4043)
-#define MCF_GPIO_PCLRR_UART		MCF_REG08(0xFC0A4045)
-#define MCF_GPIO_PCLRR_QSPI		MCF_REG08(0xFC0A4046)
-#define MCF_GPIO_PCLRR_TIMER		MCF_REG08(0xFC0A4047)
-#define MCF_GPIO_PCLRR_LCDDATAH		MCF_REG08(0xFC0A4049)
-#define MCF_GPIO_PCLRR_LCDDATAM		MCF_REG08(0xFC0A404A)
-#define MCF_GPIO_PCLRR_LCDDATAL		MCF_REG08(0xFC0A404B)
-#define MCF_GPIO_PCLRR_LCDCTLH		MCF_REG08(0xFC0A404C)
-#define MCF_GPIO_PCLRR_LCDCTLL		MCF_REG08(0xFC0A404D)
+#define MCFGPIO_PODR_FECH		(0xFC0A4000)
+#define MCFGPIO_PODR_FECL		(0xFC0A4001)
+#define MCFGPIO_PODR_SSI		(0xFC0A4002)
+#define MCFGPIO_PODR_BUSCTL		(0xFC0A4003)
+#define MCFGPIO_PODR_BE			(0xFC0A4004)
+#define MCFGPIO_PODR_CS			(0xFC0A4005)
+#define MCFGPIO_PODR_PWM		(0xFC0A4006)
+#define MCFGPIO_PODR_FECI2C		(0xFC0A4007)
+#define MCFGPIO_PODR_UART		(0xFC0A4009)
+#define MCFGPIO_PODR_QSPI		(0xFC0A400A)
+#define MCFGPIO_PODR_TIMER		(0xFC0A400B)
+#define MCFGPIO_PODR_LCDDATAH		(0xFC0A400D)
+#define MCFGPIO_PODR_LCDDATAM		(0xFC0A400E)
+#define MCFGPIO_PODR_LCDDATAL		(0xFC0A400F)
+#define MCFGPIO_PODR_LCDCTLH		(0xFC0A4010)
+#define MCFGPIO_PODR_LCDCTLL		(0xFC0A4011)
+#define MCFGPIO_PDDR_FECH		(0xFC0A4014)
+#define MCFGPIO_PDDR_FECL		(0xFC0A4015)
+#define MCFGPIO_PDDR_SSI		(0xFC0A4016)
+#define MCFGPIO_PDDR_BUSCTL		(0xFC0A4017)
+#define MCFGPIO_PDDR_BE			(0xFC0A4018)
+#define MCFGPIO_PDDR_CS			(0xFC0A4019)
+#define MCFGPIO_PDDR_PWM		(0xFC0A401A)
+#define MCFGPIO_PDDR_FECI2C		(0xFC0A401B)
+#define MCFGPIO_PDDR_UART		(0xFC0A401C)
+#define MCFGPIO_PDDR_QSPI		(0xFC0A401E)
+#define MCFGPIO_PDDR_TIMER		(0xFC0A401F)
+#define MCFGPIO_PDDR_LCDDATAH		(0xFC0A4021)
+#define MCFGPIO_PDDR_LCDDATAM		(0xFC0A4022)
+#define MCFGPIO_PDDR_LCDDATAL		(0xFC0A4023)
+#define MCFGPIO_PDDR_LCDCTLH		(0xFC0A4024)
+#define MCFGPIO_PDDR_LCDCTLL		(0xFC0A4025)
+#define MCFGPIO_PPDSDR_FECH		(0xFC0A4028)
+#define MCFGPIO_PPDSDR_FECL		(0xFC0A4029)
+#define MCFGPIO_PPDSDR_SSI		(0xFC0A402A)
+#define MCFGPIO_PPDSDR_BUSCTL		(0xFC0A402B)
+#define MCFGPIO_PPDSDR_BE		(0xFC0A402C)
+#define MCFGPIO_PPDSDR_CS		(0xFC0A402D)
+#define MCFGPIO_PPDSDR_PWM		(0xFC0A402E)
+#define MCFGPIO_PPDSDR_FECI2C		(0xFC0A402F)
+#define MCFGPIO_PPDSDR_UART		(0xFC0A4031)
+#define MCFGPIO_PPDSDR_QSPI		(0xFC0A4032)
+#define MCFGPIO_PPDSDR_TIMER		(0xFC0A4033)
+#define MCFGPIO_PPDSDR_LCDDATAH		(0xFC0A4035)
+#define MCFGPIO_PPDSDR_LCDDATAM		(0xFC0A4036)
+#define MCFGPIO_PPDSDR_LCDDATAL		(0xFC0A4037)
+#define MCFGPIO_PPDSDR_LCDCTLH		(0xFC0A4038)
+#define MCFGPIO_PPDSDR_LCDCTLL		(0xFC0A4039)
+#define MCFGPIO_PCLRR_FECH		(0xFC0A403C)
+#define MCFGPIO_PCLRR_FECL		(0xFC0A403D)
+#define MCFGPIO_PCLRR_SSI		(0xFC0A403E)
+#define MCFGPIO_PCLRR_BUSCTL		(0xFC0A403F)
+#define MCFGPIO_PCLRR_BE		(0xFC0A4040)
+#define MCFGPIO_PCLRR_CS		(0xFC0A4041)
+#define MCFGPIO_PCLRR_PWM		(0xFC0A4042)
+#define MCFGPIO_PCLRR_FECI2C		(0xFC0A4043)
+#define MCFGPIO_PCLRR_UART		(0xFC0A4045)
+#define MCFGPIO_PCLRR_QSPI		(0xFC0A4046)
+#define MCFGPIO_PCLRR_TIMER		(0xFC0A4047)
+#define MCFGPIO_PCLRR_LCDDATAH		(0xFC0A4049)
+#define MCFGPIO_PCLRR_LCDDATAM		(0xFC0A404A)
+#define MCFGPIO_PCLRR_LCDDATAL		(0xFC0A404B)
+#define MCFGPIO_PCLRR_LCDCTLH		(0xFC0A404C)
+#define MCFGPIO_PCLRR_LCDCTLL		(0xFC0A404D)
 #define MCF_GPIO_PAR_FEC		MCF_REG08(0xFC0A4050)
 #define MCF_GPIO_PAR_PWM		MCF_REG08(0xFC0A4051)
 #define MCF_GPIO_PAR_BUSCTL		MCF_REG08(0xFC0A4052)
@@ -1187,6 +1161,20 @@
 /* Bit definitions and macros for MCF_GPIO_DSCR_IRQ */
 #define MCF_GPIO_DSCR_IRQ_IRQ_DSE(x)               (((x)&0x03)<<0)
 
+/*
+ * Generic GPIO support
+ */
+#define MCFGPIO_PODR			MCFGPIO_PODR_FECH
+#define MCFGPIO_PDDR			MCFGPIO_PDDR_FECH
+#define MCFGPIO_PPDR			MCFGPIO_PPDSDR_FECH
+#define MCFGPIO_SETR			MCFGPIO_PPDSDR_FECH
+#define MCFGPIO_CLRR			MCFGPIO_PCLRR_FECH
+
+#define MCFGPIO_PIN_MAX			136
+#define MCFGPIO_IRQ_MAX			8
+#define MCFGPIO_IRQ_VECBASE		MCFINT_VECBASE
+
+
 /*********************************************************************
  *
  * Interrupt Controller (INTC)
@@ -2154,12 +2142,12 @@
  *********************************************************************/
 
 /* Register read/write macros */
-#define MCF_EPORT_EPPAR                MCF_REG16(0xFC094000)
-#define MCF_EPORT_EPDDR                MCF_REG08(0xFC094002)
-#define MCF_EPORT_EPIER                MCF_REG08(0xFC094003)
-#define MCF_EPORT_EPDR                 MCF_REG08(0xFC094004)
-#define MCF_EPORT_EPPDR                MCF_REG08(0xFC094005)
-#define MCF_EPORT_EPFR                 MCF_REG08(0xFC094006)
+#define MCFEPORT_EPPAR                (0xFC094000)
+#define MCFEPORT_EPDDR                (0xFC094002)
+#define MCFEPORT_EPIER                (0xFC094003)
+#define MCFEPORT_EPDR                 (0xFC094004)
+#define MCFEPORT_EPPDR                (0xFC094005)
+#define MCFEPORT_EPFR                 (0xFC094006)
 
 /* Bit definitions and macros for MCF_EPORT_EPPAR */
 #define MCF_EPORT_EPPAR_EPPA1(x)       (((x)&0x0003)<<2)
diff --git a/arch/m68k/include/asm/m5407sim.h b/arch/m68k/include/asm/m5407sim.h
index cc22c4a..c399abb 100644
--- a/arch/m68k/include/asm/m5407sim.h
+++ b/arch/m68k/include/asm/m5407sim.h
@@ -73,9 +73,15 @@
 #define MCFSIM_DACR1		0x110		/* DRAM 1 Addr and Ctrl (r/w) */
 #define MCFSIM_DMR1		0x114		/* DRAM 1 Mask reg (r/w) */
 
-#define	MCFSIM_PADDR		0x244		/* Parallel Direction (r/w) */
-#define	MCFSIM_PADAT		0x248		/* Parallel Data (r/w) */
+#define	MCFSIM_PADDR		(MCF_MBAR + 0x244)
+#define	MCFSIM_PADAT		(MCF_MBAR + 0x248)
 
+/*
+ * Generic GPIO support
+ */
+#define MCFGPIO_PIN_MAX			16
+#define MCFGPIO_IRQ_MAX			-1
+#define MCFGPIO_IRQ_VECBASE		-1
 
 /*
  *	Some symbol defines for the above...
@@ -91,19 +97,6 @@
 #define	MCFSIM_DMA3ICR		MCFSIM_ICR9	/* DMA 3 ICR */
 
 /*
- *	Macro to set IMR register. It is 32 bits on the 5407.
- */
-#define	mcf_getimr()		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR))
-
-#define	mcf_setimr(imr)		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR)) = (imr);
-
-#define	mcf_getipr()		\
-	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPR))
-
-
-/*
  *	Some symbol defines for the Parallel Port Pin Assignment Register
  */
 #define MCFSIM_PAR_DREQ0        0x40            /* Set to select DREQ0 input */
@@ -118,6 +111,11 @@
 #define IRQ3_LEVEL6	0x40
 #define IRQ1_LEVEL2	0x20
 
+/*
+ *	Define system peripheral IRQ usage.
+ */
+#define	MCF_IRQ_TIMER		30		/* Timer0, Level 6 */
+#define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
 
 /*
  *	Define the Cache register flags.
diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h
new file mode 100644
index 0000000..ee5e4cc
--- /dev/null
+++ b/arch/m68k/include/asm/mcfgpio.h
@@ -0,0 +1,40 @@
+/*
+ * Coldfire generic GPIO support.
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef mcfgpio_h
+#define mcfgpio_h
+
+#include <linux/io.h>
+#include <asm-generic/gpio.h>
+
+struct mcf_gpio_chip {
+	struct gpio_chip gpio_chip;
+	void __iomem *pddr;
+	void __iomem *podr;
+	void __iomem *ppdr;
+	void __iomem *setr;
+	void __iomem *clrr;
+	const u8 *gpio_to_pinmux;
+};
+
+int mcf_gpio_direction_input(struct gpio_chip *, unsigned);
+int mcf_gpio_get_value(struct gpio_chip *, unsigned);
+int mcf_gpio_direction_output(struct gpio_chip *, unsigned, int);
+void mcf_gpio_set_value(struct gpio_chip *, unsigned, int);
+void mcf_gpio_set_value_fast(struct gpio_chip *, unsigned, int);
+int mcf_gpio_request(struct gpio_chip *, unsigned);
+void mcf_gpio_free(struct gpio_chip *, unsigned);
+
+#endif
diff --git a/arch/m68k/include/asm/mcfintc.h b/arch/m68k/include/asm/mcfintc.h
new file mode 100644
index 0000000..4183320
--- /dev/null
+++ b/arch/m68k/include/asm/mcfintc.h
@@ -0,0 +1,89 @@
+/****************************************************************************/
+
+/*
+ *	mcfintc.h -- support definitions for the simple ColdFire
+ *		     Interrupt Controller
+ *
+ * 	(C) Copyright 2009,  Greg Ungerer <gerg@uclinux.org>
+ */
+
+/****************************************************************************/
+#ifndef	mcfintc_h
+#define	mcfintc_h
+/****************************************************************************/
+
+/*
+ * Most of the older ColdFire parts use the same simple interrupt
+ * controller. This is currently used on the 5206, 5206e, 5249, 5307
+ * and 5407 parts.
+ *
+ * The builtin peripherals are masked through dedicated bits in the
+ * Interrupt Mask register (IMR) - and this is not indexed (or in any way
+ * related to) the actual interrupt number they use. So knowing the IRQ
+ * number doesn't explicitly map to a certain internal device for
+ * interrupt control purposes.
+ */
+
+/*
+ * Bit definitions for the ICR family of registers.
+ */
+#define	MCFSIM_ICR_AUTOVEC	0x80		/* Auto-vectored intr */
+#define	MCFSIM_ICR_LEVEL0	0x00		/* Level 0 intr */
+#define	MCFSIM_ICR_LEVEL1	0x04		/* Level 1 intr */
+#define	MCFSIM_ICR_LEVEL2	0x08		/* Level 2 intr */
+#define	MCFSIM_ICR_LEVEL3	0x0c		/* Level 3 intr */
+#define	MCFSIM_ICR_LEVEL4	0x10		/* Level 4 intr */
+#define	MCFSIM_ICR_LEVEL5	0x14		/* Level 5 intr */
+#define	MCFSIM_ICR_LEVEL6	0x18		/* Level 6 intr */
+#define	MCFSIM_ICR_LEVEL7	0x1c		/* Level 7 intr */
+
+#define	MCFSIM_ICR_PRI0		0x00		/* Priority 0 intr */
+#define	MCFSIM_ICR_PRI1		0x01		/* Priority 1 intr */
+#define	MCFSIM_ICR_PRI2		0x02		/* Priority 2 intr */
+#define	MCFSIM_ICR_PRI3		0x03		/* Priority 3 intr */
+
+/*
+ * IMR bit position definitions. Not all ColdFire parts with this interrupt
+ * controller actually support all of these interrupt sources. But the bit
+ * numbers are the same in all cores.
+ */
+#define	MCFINTC_EINT1		1		/* External int #1 */
+#define	MCFINTC_EINT2		2		/* External int #2 */
+#define	MCFINTC_EINT3		3		/* External int #3 */
+#define	MCFINTC_EINT4		4		/* External int #4 */
+#define	MCFINTC_EINT5		5		/* External int #5 */
+#define	MCFINTC_EINT6		6		/* External int #6 */
+#define	MCFINTC_EINT7		7		/* External int #7 */
+#define	MCFINTC_SWT		8		/* Software Watchdog */
+#define	MCFINTC_TIMER1		9
+#define	MCFINTC_TIMER2		10
+#define	MCFINTC_I2C		11		/* I2C / MBUS */
+#define	MCFINTC_UART0		12
+#define	MCFINTC_UART1		13
+#define	MCFINTC_DMA0		14
+#define	MCFINTC_DMA1		15
+#define	MCFINTC_DMA2		16
+#define	MCFINTC_DMA3		17
+#define	MCFINTC_QSPI		18
+
+#ifndef __ASSEMBLER__
+
+/*
+ * There is no one-is-one correspondance between the interrupt number (irq)
+ * and the bit fields on the mask register. So we create a per-cpu type
+ * mapping of irq to mask bit. The CPU platform code needs to register
+ * its supported irq's at init time, using this function.
+ */
+extern unsigned char mcf_irq2imr[];
+static inline void mcf_mapirq2imr(int irq, int imr)
+{
+	mcf_irq2imr[irq] = imr;
+}
+
+void mcf_autovector(int irq);
+void mcf_setimr(int index);
+void mcf_clrimr(int index);
+#endif
+
+/****************************************************************************/
+#endif	/* mcfintc_h */
diff --git a/arch/m68k/include/asm/mcfne.h b/arch/m68k/include/asm/mcfne.h
index 431f63a..bf638be 100644
--- a/arch/m68k/include/asm/mcfne.h
+++ b/arch/m68k/include/asm/mcfne.h
@@ -239,87 +239,4 @@
 #endif /* NE2000_OFFOFFSET */
 
 /****************************************************************************/
-
-#ifdef COLDFIRE_NE2000_FUNCS
-
-/*
- *	Lastly the interrupt set up code...
- *	Minor differences between the different board types.
- */
-
-#if defined(CONFIG_ARN5206)
-void ne2000_irqsetup(int irq)
-{
-	volatile unsigned char  *icrp;
-
-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_ICR4);
-	*icrp = MCFSIM_ICR_LEVEL4 | MCFSIM_ICR_PRI2;
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT4);
-}
-#endif
-
-#if defined(CONFIG_M5206eC3)
-void ne2000_irqsetup(int irq)
-{
-	volatile unsigned char  *icrp;
-
-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_ICR4);
-	*icrp = MCFSIM_ICR_LEVEL4 | MCFSIM_ICR_PRI2 | MCFSIM_ICR_AUTOVEC;
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT4);
-}
-#endif
-
-#if defined(CONFIG_M5206e) && defined(CONFIG_NETtel)
-void ne2000_irqsetup(int irq)
-{
-	mcf_autovector(irq);
-}
-#endif
-
-#if defined(CONFIG_M5272) && defined(CONFIG_NETtel)
-void ne2000_irqsetup(int irq)
-{
-	volatile unsigned long	*icrp;
-	volatile unsigned long	*pitr;
-
-	/* The NE2000 device uses external IRQ3 */
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	*icrp = (*icrp & 0x77077777) | 0x00d00000;
-
-	pitr = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PITR);
-	*pitr = *pitr | 0x20000000;
-}
-
-void ne2000_irqack(int irq)
-{
-	volatile unsigned long	*icrp;
-
-	/* The NE2000 device uses external IRQ3 */
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	*icrp = (*icrp & 0x77777777) | 0x00800000;
-}
-#endif
-
-#if defined(CONFIG_M5307) || defined(CONFIG_M5407)
-#if defined(CONFIG_NETtel) || defined(CONFIG_SECUREEDGEMP3)
-
-void ne2000_irqsetup(int irq)
-{
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT3);
-	mcf_autovector(irq);
-}
-
-#else
-
-void ne2000_irqsetup(int irq)
-{
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT3);
-}
-
-#endif /* ! CONFIG_NETtel || CONFIG_SECUREEDGEMP3 */
-#endif /* CONFIG_M5307 || CONFIG_M5407 */
-
-#endif /* COLDFIRE_NE2000_FUNCS */
-
-/****************************************************************************/
 #endif	/* mcfne_h */
diff --git a/arch/m68k/include/asm/mcfsim.h b/arch/m68k/include/asm/mcfsim.h
index da3f2ce..9c70a67 100644
--- a/arch/m68k/include/asm/mcfsim.h
+++ b/arch/m68k/include/asm/mcfsim.h
@@ -4,7 +4,7 @@
  *	mcfsim.h -- ColdFire System Integration Module support.
  *
  *	(C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com)
- * 	(C) Copyright 2000, Lineo Inc. (www.lineo.com) 
+ * 	(C) Copyright 2000, Lineo Inc. (www.lineo.com)
  */
 
 /****************************************************************************/
@@ -12,19 +12,21 @@
 #define	mcfsim_h
 /****************************************************************************/
 
-
 /*
- *	Include 5204, 5206/e, 5235, 5249, 5270/5271, 5272, 5280/5282,
- *	5307 or 5407 specific addresses.
+ * Include the appropriate ColdFire CPU specific System Integration Module
+ * (SIM) definitions.
  */
 #if defined(CONFIG_M5206) || defined(CONFIG_M5206e)
 #include <asm/m5206sim.h>
+#include <asm/mcfintc.h>
 #elif defined(CONFIG_M520x)
 #include <asm/m520xsim.h>
 #elif defined(CONFIG_M523x)
 #include <asm/m523xsim.h>
+#include <asm/mcfintc.h>
 #elif defined(CONFIG_M5249)
 #include <asm/m5249sim.h>
+#include <asm/mcfintc.h>
 #elif defined(CONFIG_M527x)
 #include <asm/m527xsim.h>
 #elif defined(CONFIG_M5272)
@@ -33,94 +35,13 @@
 #include <asm/m528xsim.h>
 #elif defined(CONFIG_M5307)
 #include <asm/m5307sim.h>
+#include <asm/mcfintc.h>
 #elif defined(CONFIG_M532x)
 #include <asm/m532xsim.h>
 #elif defined(CONFIG_M5407)
 #include <asm/m5407sim.h>
+#include <asm/mcfintc.h>
 #endif
 
-
-/*
- *	Define the base address of the SIM within the MBAR address space.
- */
-#define	MCFSIM_BASE		0x0		/* Base address of SIM */
-
-
-/*
- *	Bit definitions for the ICR family of registers.
- */
-#define	MCFSIM_ICR_AUTOVEC	0x80		/* Auto-vectored intr */
-#define	MCFSIM_ICR_LEVEL0	0x00		/* Level 0 intr */
-#define	MCFSIM_ICR_LEVEL1	0x04		/* Level 1 intr */
-#define	MCFSIM_ICR_LEVEL2	0x08		/* Level 2 intr */
-#define	MCFSIM_ICR_LEVEL3	0x0c		/* Level 3 intr */
-#define	MCFSIM_ICR_LEVEL4	0x10		/* Level 4 intr */
-#define	MCFSIM_ICR_LEVEL5	0x14		/* Level 5 intr */
-#define	MCFSIM_ICR_LEVEL6	0x18		/* Level 6 intr */
-#define	MCFSIM_ICR_LEVEL7	0x1c		/* Level 7 intr */
-
-#define	MCFSIM_ICR_PRI0		0x00		/* Priority 0 intr */
-#define	MCFSIM_ICR_PRI1		0x01		/* Priority 1 intr */
-#define	MCFSIM_ICR_PRI2		0x02		/* Priority 2 intr */
-#define	MCFSIM_ICR_PRI3		0x03		/* Priority 3 intr */
-
-/*
- *	Bit definitions for the Interrupt Mask register (IMR).
- */
-#define	MCFSIM_IMR_EINT1	0x0002		/* External intr # 1 */
-#define	MCFSIM_IMR_EINT2	0x0004		/* External intr # 2 */
-#define	MCFSIM_IMR_EINT3	0x0008		/* External intr # 3 */
-#define	MCFSIM_IMR_EINT4	0x0010		/* External intr # 4 */
-#define	MCFSIM_IMR_EINT5	0x0020		/* External intr # 5 */
-#define	MCFSIM_IMR_EINT6	0x0040		/* External intr # 6 */
-#define	MCFSIM_IMR_EINT7	0x0080		/* External intr # 7 */
-
-#define	MCFSIM_IMR_SWD		0x0100		/* Software Watchdog intr */
-#define	MCFSIM_IMR_TIMER1	0x0200		/* TIMER 1 intr */
-#define	MCFSIM_IMR_TIMER2	0x0400		/* TIMER 2 intr */
-#define MCFSIM_IMR_MBUS		0x0800		/* MBUS intr	*/
-#define	MCFSIM_IMR_UART1	0x1000		/* UART 1 intr */
-#define	MCFSIM_IMR_UART2	0x2000		/* UART 2 intr */
-
-#if defined(CONFIG_M5206e)
-#define	MCFSIM_IMR_DMA1		0x4000		/* DMA 1 intr */
-#define	MCFSIM_IMR_DMA2		0x8000		/* DMA 2 intr */
-#elif defined(CONFIG_M5249) || defined(CONFIG_M5307)
-#define	MCFSIM_IMR_DMA0		0x4000		/* DMA 0 intr */
-#define	MCFSIM_IMR_DMA1		0x8000		/* DMA 1 intr */
-#define	MCFSIM_IMR_DMA2		0x10000		/* DMA 2 intr */
-#define	MCFSIM_IMR_DMA3		0x20000		/* DMA 3 intr */
-#endif
-
-/*
- *	Mask for all of the SIM devices. Some parts have more or less
- *	SIM devices. This is a catchall for the sandard set.
- */
-#ifndef MCFSIM_IMR_MASKALL
-#define	MCFSIM_IMR_MASKALL	0x3ffe		/* All intr sources */
-#endif
-
-
-/*
- *	PIT interrupt settings, if not found in mXXXXsim.h file.
- */
-#ifndef	ICR_INTRCONF
-#define	ICR_INTRCONF		0x2b            /* PIT1 level 5, priority 3 */
-#endif
-#ifndef	MCFPIT_IMR
-#define	MCFPIT_IMR		MCFINTC_IMRH
-#endif
-#ifndef	MCFPIT_IMR_IBIT
-#define	MCFPIT_IMR_IBIT		(1 << (MCFINT_PIT1 - 32))
-#endif
-
-
-#ifndef __ASSEMBLY__
-/*
- *	Definition for the interrupt auto-vectoring support.
- */
-extern void	mcf_autovector(unsigned int vec);
-#endif /* __ASSEMBLY__ */
-
 /****************************************************************************/
 #endif	/* mcfsim_h */
diff --git a/arch/m68k/include/asm/mcfsmc.h b/arch/m68k/include/asm/mcfsmc.h
index 2d7a4db..527bea5 100644
--- a/arch/m68k/include/asm/mcfsmc.h
+++ b/arch/m68k/include/asm/mcfsmc.h
@@ -167,15 +167,15 @@
 	static int		once = 0;
 	extern unsigned short	ppdata;
 	if (once++ == 0) {
-		*((volatile unsigned short *)(MCF_MBAR+MCFSIM_PADDR)) = 0x00ec;
+		*((volatile unsigned short *)MCFSIM_PADDR) = 0x00ec;
 		ppdata |= 0x0080;
-		*((volatile unsigned short *)(MCF_MBAR+MCFSIM_PADAT)) = ppdata;
+		*((volatile unsigned short *)MCFSIM_PADAT) = ppdata;
 		outw(0x0001, ioaddr + BANK_SELECT);
 		outw(0x0001, ioaddr + BANK_SELECT);
 		outw(0x0067, ioaddr + BASE);
 
 		ppdata &= ~0x0080;
-		*((volatile unsigned short *)(MCF_MBAR+MCFSIM_PADAT)) = ppdata;
+		*((volatile unsigned short *)MCFSIM_PADAT) = ppdata;
 	}
 	
 	*((volatile unsigned short *)(MCF_MBAR+MCFSIM_CSCR3)) = 0x1180;
diff --git a/arch/m68k/include/asm/nettel.h b/arch/m68k/include/asm/nettel.h
index 0299f6a..4dec2d9 100644
--- a/arch/m68k/include/asm/nettel.h
+++ b/arch/m68k/include/asm/nettel.h
@@ -48,14 +48,14 @@
 static __inline__ unsigned int mcf_getppdata(void)
 {
 	volatile unsigned short *pp;
-	pp = (volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT);
+	pp = (volatile unsigned short *) MCFSIM_PADAT;
 	return((unsigned int) *pp);
 }
 
 static __inline__ void mcf_setppdata(unsigned int mask, unsigned int bits)
 {
 	volatile unsigned short *pp;
-	pp = (volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT);
+	pp = (volatile unsigned short *) MCFSIM_PADAT;
 	ppdata = (ppdata & ~mask) | bits;
 	*pp = ppdata;
 }
diff --git a/arch/m68k/include/asm/page_no.h b/arch/m68k/include/asm/page_no.h
index 9aa3f90..1f31b06 100644
--- a/arch/m68k/include/asm/page_no.h
+++ b/arch/m68k/include/asm/page_no.h
@@ -1,10 +1,12 @@
 #ifndef _M68KNOMMU_PAGE_H
 #define _M68KNOMMU_PAGE_H
 
+#include <linux/const.h>
+
 /* PAGE_SHIFT determines the page size */
 
 #define PAGE_SHIFT	(12)
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_SIZE	(_AC(1,UL) << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
 #include <asm/setup.h>
diff --git a/arch/m68k/include/asm/pinmux.h b/arch/m68k/include/asm/pinmux.h
new file mode 100644
index 0000000..119ee68
--- /dev/null
+++ b/arch/m68k/include/asm/pinmux.h
@@ -0,0 +1,30 @@
+/*
+ * Coldfire generic GPIO pinmux support.
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef pinmux_h
+#define pinmux_h
+
+#define MCFPINMUX_NONE		-1
+
+extern int mcf_pinmux_request(unsigned, unsigned);
+extern void mcf_pinmux_release(unsigned, unsigned);
+
+static inline int mcf_pinmux_is_valid(unsigned pinmux)
+{
+	return pinmux != MCFPINMUX_NONE;
+}
+
+#endif
+
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index fc3f2c2..74fd674 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -1,5 +1,170 @@
-#ifdef __uClinux__
-#include "processor_no.h"
+/*
+ * include/asm-m68k/processor.h
+ *
+ * Copyright (C) 1995 Hamish Macdonald
+ */
+
+#ifndef __ASM_M68K_PROCESSOR_H
+#define __ASM_M68K_PROCESSOR_H
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+#include <linux/thread_info.h>
+#include <asm/segment.h>
+#include <asm/fpu.h>
+#include <asm/ptrace.h>
+
+static inline unsigned long rdusp(void)
+{
+#ifdef CONFIG_COLDFIRE
+	extern unsigned int sw_usp;
+	return sw_usp;
 #else
-#include "processor_mm.h"
+	unsigned long usp;
+	__asm__ __volatile__("move %/usp,%0" : "=a" (usp));
+	return usp;
+#endif
+}
+
+static inline void wrusp(unsigned long usp)
+{
+#ifdef CONFIG_COLDFIRE
+	extern unsigned int sw_usp;
+	sw_usp = usp;
+#else
+	__asm__ __volatile__("move %0,%/usp" : : "a" (usp));
+#endif
+}
+
+/*
+ * User space process size: 3.75GB. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing.
+ */
+#ifndef CONFIG_SUN3
+#define TASK_SIZE	(0xF0000000UL)
+#else
+#define TASK_SIZE	(0x0E000000UL)
+#endif
+
+#ifdef __KERNEL__
+#define STACK_TOP	TASK_SIZE
+#define STACK_TOP_MAX	STACK_TOP
+#endif
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#ifdef CONFIG_MMU
+#ifndef CONFIG_SUN3
+#define TASK_UNMAPPED_BASE	0xC0000000UL
+#else
+#define TASK_UNMAPPED_BASE	0x0A000000UL
+#endif
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
+#else
+#define TASK_UNMAPPED_BASE	0
+#endif
+
+struct thread_struct {
+	unsigned long  ksp;		/* kernel stack pointer */
+	unsigned long  usp;		/* user stack pointer */
+	unsigned short sr;		/* saved status register */
+	unsigned short fs;		/* saved fs (sfc, dfc) */
+	unsigned long  crp[2];		/* cpu root pointer */
+	unsigned long  esp0;		/* points to SR of stack frame */
+	unsigned long  faddr;		/* info about last fault */
+	int            signo, code;
+	unsigned long  fp[8*3];
+	unsigned long  fpcntl[3];	/* fp control regs */
+	unsigned char  fpstate[FPSTATESIZE];  /* floating point state */
+	struct thread_info info;
+};
+
+#define INIT_THREAD  {							\
+	.ksp	= sizeof(init_stack) + (unsigned long) init_stack,	\
+	.sr	= PS_S,							\
+	.fs	= __KERNEL_DS,						\
+	.info	= INIT_THREAD_INFO(init_task),				\
+}
+
+#ifdef CONFIG_MMU
+/*
+ * Do necessary setup to start up a newly executed thread.
+ */
+static inline void start_thread(struct pt_regs * regs, unsigned long pc,
+				unsigned long usp)
+{
+	/* reads from user space */
+	set_fs(USER_DS);
+
+	regs->pc = pc;
+	regs->sr &= ~0x2000;
+	wrusp(usp);
+}
+
+#else
+
+/*
+ * Coldfire stacks need to be re-aligned on trap exit, conventional
+ * 68k can handle this case cleanly.
+ */
+#ifdef CONFIG_COLDFIRE
+#define reformat(_regs)		do { (_regs)->format = 0x4; } while(0)
+#else
+#define reformat(_regs)		do { } while (0)
+#endif
+
+#define start_thread(_regs, _pc, _usp)                  \
+do {                                                    \
+	set_fs(USER_DS); /* reads from user space */    \
+	(_regs)->pc = (_pc);                            \
+	((struct switch_stack *)(_regs))[-1].a6 = 0;    \
+	reformat(_regs);                                \
+	if (current->mm)                                \
+		(_regs)->d5 = current->mm->start_data;  \
+	(_regs)->sr &= ~0x2000;                         \
+	wrusp(_usp);                                    \
+} while(0)
+
+#endif
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
+/* Free all resources held by a thread. */
+static inline void release_thread(struct task_struct *dead_task)
+{
+}
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+/*
+ * Free current thread data structures etc..
+ */
+static inline void exit_thread(void)
+{
+}
+
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define	KSTK_EIP(tsk)	\
+    ({			\
+	unsigned long eip = 0;	 \
+	if ((tsk)->thread.esp0 > PAGE_SIZE && \
+	    (virt_addr_valid((tsk)->thread.esp0))) \
+	      eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
+	eip; })
+#define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
+
+#define cpu_relax()	barrier()
+
 #endif
diff --git a/arch/m68k/include/asm/processor_mm.h b/arch/m68k/include/asm/processor_mm.h
deleted file mode 100644
index 1f61ef5..0000000
--- a/arch/m68k/include/asm/processor_mm.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * include/asm-m68k/processor.h
- *
- * Copyright (C) 1995 Hamish Macdonald
- */
-
-#ifndef __ASM_M68K_PROCESSOR_H
-#define __ASM_M68K_PROCESSOR_H
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
-
-#include <linux/thread_info.h>
-#include <asm/segment.h>
-#include <asm/fpu.h>
-#include <asm/ptrace.h>
-
-static inline unsigned long rdusp(void)
-{
-	unsigned long usp;
-
-	__asm__ __volatile__("move %/usp,%0" : "=a" (usp));
-	return usp;
-}
-
-static inline void wrusp(unsigned long usp)
-{
-	__asm__ __volatile__("move %0,%/usp" : : "a" (usp));
-}
-
-/*
- * User space process size: 3.75GB. This is hardcoded into a few places,
- * so don't change it unless you know what you are doing.
- */
-#ifndef CONFIG_SUN3
-#define TASK_SIZE	(0xF0000000UL)
-#else
-#define TASK_SIZE	(0x0E000000UL)
-#endif
-
-#ifdef __KERNEL__
-#define STACK_TOP	TASK_SIZE
-#define STACK_TOP_MAX	STACK_TOP
-#endif
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#ifndef CONFIG_SUN3
-#define TASK_UNMAPPED_BASE	0xC0000000UL
-#else
-#define TASK_UNMAPPED_BASE	0x0A000000UL
-#endif
-#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
-
-struct thread_struct {
-	unsigned long  ksp;		/* kernel stack pointer */
-	unsigned long  usp;		/* user stack pointer */
-	unsigned short sr;		/* saved status register */
-	unsigned short fs;		/* saved fs (sfc, dfc) */
-	unsigned long  crp[2];		/* cpu root pointer */
-	unsigned long  esp0;		/* points to SR of stack frame */
-	unsigned long  faddr;		/* info about last fault */
-	int            signo, code;
-	unsigned long  fp[8*3];
-	unsigned long  fpcntl[3];	/* fp control regs */
-	unsigned char  fpstate[FPSTATESIZE];  /* floating point state */
-	struct thread_info info;
-};
-
-#define INIT_THREAD  {							\
-	.ksp	= sizeof(init_stack) + (unsigned long) init_stack,	\
-	.sr	= PS_S,							\
-	.fs	= __KERNEL_DS,						\
-	.info	= INIT_THREAD_INFO(init_task),				\
-}
-
-/*
- * Do necessary setup to start up a newly executed thread.
- */
-static inline void start_thread(struct pt_regs * regs, unsigned long pc,
-				unsigned long usp)
-{
-	/* reads from user space */
-	set_fs(USER_DS);
-
-	regs->pc = pc;
-	regs->sr &= ~0x2000;
-	wrusp(usp);
-}
-
-/* Forward declaration, a strange C thing */
-struct task_struct;
-
-/* Free all resources held by a thread. */
-static inline void release_thread(struct task_struct *dead_task)
-{
-}
-
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk)	do { } while (0)
-
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
-/*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-extern unsigned long thread_saved_pc(struct task_struct *tsk);
-
-unsigned long get_wchan(struct task_struct *p);
-
-#define	KSTK_EIP(tsk)	\
-    ({			\
-	unsigned long eip = 0;	 \
-	if ((tsk)->thread.esp0 > PAGE_SIZE && \
-	    (virt_addr_valid((tsk)->thread.esp0))) \
-	      eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
-	eip; })
-#define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
-
-#define cpu_relax()	barrier()
-
-#endif
diff --git a/arch/m68k/include/asm/processor_no.h b/arch/m68k/include/asm/processor_no.h
deleted file mode 100644
index 7a1e0ba..0000000
--- a/arch/m68k/include/asm/processor_no.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * include/asm-m68knommu/processor.h
- *
- * Copyright (C) 1995 Hamish Macdonald
- */
-
-#ifndef __ASM_M68K_PROCESSOR_H
-#define __ASM_M68K_PROCESSOR_H
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
-
-#include <linux/compiler.h>
-#include <linux/threads.h>
-#include <asm/types.h>
-#include <asm/segment.h>
-#include <asm/fpu.h>
-#include <asm/ptrace.h>
-#include <asm/current.h>
-
-static inline unsigned long rdusp(void)
-{
-#ifdef CONFIG_COLDFIRE
-	extern unsigned int sw_usp;
-	return(sw_usp);
-#else
-  	unsigned long usp;
-	__asm__ __volatile__("move %/usp,%0" : "=a" (usp));
-	return usp;
-#endif
-}
-
-static inline void wrusp(unsigned long usp)
-{
-#ifdef CONFIG_COLDFIRE
-	extern unsigned int sw_usp;
-	sw_usp = usp;
-#else
-	__asm__ __volatile__("move %0,%/usp" : : "a" (usp));
-#endif
-}
-
-/*
- * User space process size: 3.75GB. This is hardcoded into a few places,
- * so don't change it unless you know what you are doing.
- */
-#define TASK_SIZE	(0xF0000000UL)
-
-/*
- * This decides where the kernel will search for a free chunk of vm
- * space during mmap's. We won't be using it
- */
-#define TASK_UNMAPPED_BASE	0
-
-/* 
- * if you change this structure, you must change the code and offsets
- * in m68k/machasm.S
- */
-   
-struct thread_struct {
-	unsigned long  ksp;		/* kernel stack pointer */
-	unsigned long  usp;		/* user stack pointer */
-	unsigned short sr;		/* saved status register */
-	unsigned short fs;		/* saved fs (sfc, dfc) */
-	unsigned long  crp[2];		/* cpu root pointer */
-	unsigned long  esp0;		/* points to SR of stack frame */
-	unsigned long  fp[8*3];
-	unsigned long  fpcntl[3];	/* fp control regs */
-	unsigned char  fpstate[FPSTATESIZE];  /* floating point state */
-};
-
-#define INIT_THREAD  {							\
-	.ksp	= sizeof(init_stack) + (unsigned long) init_stack,	\
-	.sr	= PS_S,							\
-	.fs	= __KERNEL_DS,						\
-}
-
-/*
- * Coldfire stacks need to be re-aligned on trap exit, conventional
- * 68k can handle this case cleanly.
- */
-#if defined(CONFIG_COLDFIRE)
-#define	reformat(_regs)		do { (_regs)->format = 0x4; } while(0)
-#else
-#define	reformat(_regs)		do { } while (0)
-#endif
-
-/*
- * Do necessary setup to start up a newly executed thread.
- *
- * pass the data segment into user programs if it exists,
- * it can't hurt anything as far as I can tell
- */
-#define start_thread(_regs, _pc, _usp)			\
-do {							\
-	set_fs(USER_DS); /* reads from user space */	\
-	(_regs)->pc = (_pc);				\
-	((struct switch_stack *)(_regs))[-1].a6 = 0;	\
-	reformat(_regs);				\
-	if (current->mm)				\
-		(_regs)->d5 = current->mm->start_data;	\
-	(_regs)->sr &= ~0x2000;				\
-	wrusp(_usp);					\
-} while(0)
-
-/* Forward declaration, a strange C thing */
-struct task_struct;
-
-/* Free all resources held by a thread. */
-static inline void release_thread(struct task_struct *dead_task)
-{
-}
-
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk)	do { } while (0)
-
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
-/*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-unsigned long thread_saved_pc(struct task_struct *tsk);
-unsigned long get_wchan(struct task_struct *p);
-
-#define	KSTK_EIP(tsk)	\
-    ({			\
-	unsigned long eip = 0;	 \
-	if ((tsk)->thread.esp0 > PAGE_SIZE && \
-	    (virt_addr_valid((tsk)->thread.esp0))) \
-	      eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
-	eip; })
-#define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
-
-#define cpu_relax()    barrier()
-
-#endif
diff --git a/arch/m68k/include/asm/timex.h b/arch/m68k/include/asm/timex.h
index b87f2f2..6759dad 100644
--- a/arch/m68k/include/asm/timex.h
+++ b/arch/m68k/include/asm/timex.h
@@ -3,10 +3,23 @@
  *
  * m68k architecture timex specifications
  */
-#ifndef _ASMm68k_TIMEX_H
-#define _ASMm68k_TIMEX_H
+#ifndef _ASMm68K_TIMEX_H
+#define _ASMm68K_TIMEX_H
 
+#ifdef CONFIG_COLDFIRE
+/*
+ * CLOCK_TICK_RATE should give the underlying frequency of the tick timer
+ * to make ntp work best.  For Coldfires, that's the main clock.
+ */
+#include <asm/coldfire.h>
+#define CLOCK_TICK_RATE	MCF_CLK
+#else
+/*
+ * This default CLOCK_TICK_RATE is probably wrong for many 68k boards
+ * Users of those boards will need to check and modify accordingly
+ */
 #define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+#endif
 
 typedef unsigned long cycles_t;
 
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 5343762..e2201b9 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -47,6 +47,10 @@
 	bool
 	default y
 
+config GENERIC_GPIO
+	bool
+	default n
+
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -182,6 +186,8 @@
 config COLDFIRE
 	bool
 	depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407)
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
 	default y
 
 config CLOCK_SET
diff --git a/arch/m68knommu/kernel/irq.c b/arch/m68knommu/kernel/irq.c
index 56e0f4c5..c9cac36 100644
--- a/arch/m68knommu/kernel/irq.c
+++ b/arch/m68knommu/kernel/irq.c
@@ -29,32 +29,6 @@
 	set_irq_regs(oldregs);
 }
 
-void ack_bad_irq(unsigned int irq)
-{
-	printk(KERN_ERR "IRQ: unexpected irq=%d\n", irq);
-}
-
-static struct irq_chip m_irq_chip = {
-	.name		= "M68K-INTC",
-	.enable		= enable_vector,
-	.disable	= disable_vector,
-	.ack		= ack_vector,
-};
-
-void __init init_IRQ(void)
-{
-	int irq;
-
-	init_vectors();
-
-	for (irq = 0; (irq < NR_IRQS); irq++) {
-		irq_desc[irq].status = IRQ_DISABLED;
-		irq_desc[irq].action = NULL;
-		irq_desc[irq].depth = 1;
-		irq_desc[irq].chip = &m_irq_chip;
-	}
-}
-
 int show_interrupts(struct seq_file *p, void *v)
 {
 	struct irqaction *ap;
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index d182b2f..c2aa717 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -69,7 +69,7 @@
 	if ((year += 1900) < 1970)
 		year += 100;
 
-	return  mktime(year, mon, day, hour, min, sec);;
+	return  mktime(year, mon, day, hour, min, sec);
 }
 
 unsigned long read_persistent_clock(void)
diff --git a/arch/m68knommu/lib/checksum.c b/arch/m68knommu/lib/checksum.c
index 269d83b..eccf25d 100644
--- a/arch/m68knommu/lib/checksum.c
+++ b/arch/m68knommu/lib/checksum.c
@@ -92,6 +92,7 @@
 	return result;
 }
 
+#ifdef CONFIG_COLDFIRE
 /*
  *	This is a version of ip_compute_csum() optimized for IP headers,
  *	which always checksum on 4 octet boundaries.
@@ -100,6 +101,7 @@
 {
 	return (__force __sum16)~do_csum(iph,ihl*4);
 }
+#endif
 
 /*
  * computes the checksum of a memory block at buff, length len,
@@ -127,15 +129,6 @@
 EXPORT_SYMBOL(csum_partial);
 
 /*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-__sum16 ip_compute_csum(const void *buff, int len)
-{
-	return (__force __sum16)~do_csum(buff,len);
-}
-
-/*
  * copy from fs while checksumming, otherwise like csum_partial
  */
 
diff --git a/arch/m68knommu/platform/5206/Makefile b/arch/m68knommu/platform/5206/Makefile
index a439d9a..113c333 100644
--- a/arch/m68knommu/platform/5206/Makefile
+++ b/arch/m68knommu/platform/5206/Makefile
@@ -14,5 +14,5 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-y := config.o
+obj-y := config.o gpio.o
 
diff --git a/arch/m68knommu/platform/5206/config.c b/arch/m68knommu/platform/5206/config.c
index f6f7987..9c33546 100644
--- a/arch/m68knommu/platform/5206/config.c
+++ b/arch/m68knommu/platform/5206/config.c
@@ -49,11 +49,11 @@
 	if (line == 0) {
 		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
 		writeb(irq, MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1);
+		mcf_mapirq2imr(irq, MCFINTC_UART0);
 	} else if (line == 1) {
 		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
 		writeb(irq, MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2);
+		mcf_mapirq2imr(irq, MCFINTC_UART1);
 	}
 }
 
@@ -68,38 +68,19 @@
 
 /***************************************************************************/
 
-void mcf_autovector(unsigned int vec)
+static void __init m5206_timers_init(void)
 {
-	volatile unsigned char  *mbar;
-	unsigned char		icr;
+	/* Timer1 is always used as system timer */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER1ICR);
+	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
 
-	if ((vec >= 25) && (vec <= 31)) {
-		vec -= 25;
-		mbar = (volatile unsigned char *) MCF_MBAR;
-		icr = MCFSIM_ICR_AUTOVEC | (vec << 3);
-		*(mbar + MCFSIM_ICR1 + vec) = icr;
-		vec = 0x1 << (vec + 1);
-		mcf_setimr(mcf_getimr() & ~vec);
-	}
-}
-
-/***************************************************************************/
-
-void mcf_settimericr(unsigned int timer, unsigned int level)
-{
-	volatile unsigned char *icrp;
-	unsigned int icr, imr;
-
-	if (timer <= 2) {
-		switch (timer) {
-		case 2:  icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
-		default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
-		}
-
-		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
-		*icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
-		mcf_setimr(mcf_getimr() & ~imr);
-	}
+#ifdef CONFIG_HIGHPROFILE
+	/* Timer2 is to be used as a high speed profile timer  */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER2ICR);
+	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
+#endif
 }
 
 /***************************************************************************/
@@ -117,15 +98,20 @@
 
 void __init config_BSP(char *commandp, int size)
 {
-	mcf_setimr(MCFSIM_IMR_MASKALL);
 	mach_reset = m5206_cpu_reset;
+	m5206_timers_init();
+	m5206_uarts_init();
+
+	/* Only support the external interrupts on their primary level */
+	mcf_mapirq2imr(25, MCFINTC_EINT1);
+	mcf_mapirq2imr(28, MCFINTC_EINT4);
+	mcf_mapirq2imr(31, MCFINTC_EINT7);
 }
 
 /***************************************************************************/
 
 static int __init init_BSP(void)
 {
-	m5206_uarts_init();
 	platform_add_devices(m5206_devices, ARRAY_SIZE(m5206_devices));
 	return 0;
 }
diff --git a/arch/m68knommu/platform/5206/gpio.c b/arch/m68knommu/platform/5206/gpio.c
new file mode 100644
index 0000000..60f779c
--- /dev/null
+++ b/arch/m68knommu/platform/5206/gpio.c
@@ -0,0 +1,49 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PP",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFSIM_PADDR,
+		.podr				= MCFSIM_PADAT,
+		.ppdr				= MCFSIM_PADAT,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/5206e/Makefile b/arch/m68knommu/platform/5206e/Makefile
index a439d9a..113c333 100644
--- a/arch/m68knommu/platform/5206e/Makefile
+++ b/arch/m68knommu/platform/5206e/Makefile
@@ -14,5 +14,5 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-y := config.o
+obj-y := config.o gpio.o
 
diff --git a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c
index 65887799..0f41ba8 100644
--- a/arch/m68knommu/platform/5206e/config.c
+++ b/arch/m68knommu/platform/5206e/config.c
@@ -15,6 +15,7 @@
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
 #include <asm/mcfdma.h>
 #include <asm/mcfuart.h>
 
@@ -49,11 +50,11 @@
 	if (line == 0) {
 		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
 		writeb(irq, MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1);
+		mcf_mapirq2imr(irq, MCFINTC_UART0);
 	} else if (line == 1) {
 		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
 		writeb(irq, MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2);
+		mcf_mapirq2imr(irq, MCFINTC_UART1);
 	}
 }
 
@@ -68,38 +69,19 @@
 
 /***************************************************************************/
 
-void mcf_autovector(unsigned int vec)
+static void __init m5206e_timers_init(void)
 {
-	volatile unsigned char  *mbar;
-	unsigned char		icr;
+	/* Timer1 is always used as system timer */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER1ICR);
+	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
 
-	if ((vec >= 25) && (vec <= 31)) {
-		vec -= 25;
-		mbar = (volatile unsigned char *) MCF_MBAR;
-		icr = MCFSIM_ICR_AUTOVEC | (vec << 3);
-		*(mbar + MCFSIM_ICR1 + vec) = icr;
-		vec = 0x1 << (vec + 1);
-		mcf_setimr(mcf_getimr() & ~vec);
-	}
-}
-
-/***************************************************************************/
-
-void mcf_settimericr(unsigned int timer, unsigned int level)
-{
-	volatile unsigned char *icrp;
-	unsigned int icr, imr;
-
-	if (timer <= 2) {
-		switch (timer) {
-		case 2:  icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
-		default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
-		}
-
-		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
-		*icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
-		mcf_setimr(mcf_getimr() & ~imr);
-	}
+#ifdef CONFIG_HIGHPROFILE
+	/* Timer2 is to be used as a high speed profile timer  */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER2ICR);
+	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
+#endif
 }
 
 /***************************************************************************/
@@ -117,8 +99,6 @@
 
 void __init config_BSP(char *commandp, int size)
 {
-	mcf_setimr(MCFSIM_IMR_MASKALL);
-
 #if defined(CONFIG_NETtel)
 	/* Copy command line from FLASH to local buffer... */
 	memcpy(commandp, (char *) 0xf0004000, size);
@@ -126,13 +106,19 @@
 #endif /* CONFIG_NETtel */
 
 	mach_reset = m5206e_cpu_reset;
+	m5206e_timers_init();
+	m5206e_uarts_init();
+
+	/* Only support the external interrupts on their primary level */
+	mcf_mapirq2imr(25, MCFINTC_EINT1);
+	mcf_mapirq2imr(28, MCFINTC_EINT4);
+	mcf_mapirq2imr(31, MCFINTC_EINT7);
 }
 
 /***************************************************************************/
 
 static int __init init_BSP(void)
 {
-	m5206e_uarts_init();
 	platform_add_devices(m5206e_devices, ARRAY_SIZE(m5206e_devices));
 	return 0;
 }
diff --git a/arch/m68knommu/platform/5206e/gpio.c b/arch/m68knommu/platform/5206e/gpio.c
new file mode 100644
index 0000000..60f779c
--- /dev/null
+++ b/arch/m68knommu/platform/5206e/gpio.c
@@ -0,0 +1,49 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PP",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFSIM_PADDR,
+		.podr				= MCFSIM_PADAT,
+		.ppdr				= MCFSIM_PADAT,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/520x/Makefile b/arch/m68knommu/platform/520x/Makefile
index a50e76a..435ab34 100644
--- a/arch/m68knommu/platform/520x/Makefile
+++ b/arch/m68knommu/platform/520x/Makefile
@@ -14,4 +14,4 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-y := config.o
+obj-y := config.o gpio.o
diff --git a/arch/m68knommu/platform/520x/config.c b/arch/m68knommu/platform/520x/config.c
index 1c43a8a..92614de 100644
--- a/arch/m68knommu/platform/520x/config.c
+++ b/arch/m68knommu/platform/520x/config.c
@@ -81,20 +81,11 @@
 
 /***************************************************************************/
 
-#define	INTC0	(MCF_MBAR + MCFICM_INTC0)
-
 static void __init m520x_uart_init_line(int line, int irq)
 {
-	u32 imr;
 	u16 par;
 	u8 par2;
 
-	writeb(0x03, INTC0 + MCFINTC_ICR0 + MCFINT_UART0 + line);
-
-	imr = readl(INTC0 + MCFINTC_IMRL);
-	imr &= ~((1 << (irq - MCFINT_VECBASE)) | 1);
-	writel(imr, INTC0 + MCFINTC_IMRL);
-
 	switch (line) {
 	case 0:
 		par = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
@@ -131,18 +122,8 @@
 
 static void __init m520x_fec_init(void)
 {
-	u32 imr;
 	u8 v;
 
-	/* Unmask FEC interrupts at ColdFire interrupt controller */
-	writeb(0x4, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 36);
-	writeb(0x4, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 40);
-	writeb(0x4, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 42);
-
-	imr = readl(MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
-	imr &= ~0x0001FFF0;
-	writel(imr, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
-
 	/* Set multi-function pins to ethernet mode */
 	v = readb(MCF_IPSBAR + MCF_GPIO_PAR_FEC);
 	writeb(v | 0xf0, MCF_IPSBAR + MCF_GPIO_PAR_FEC);
@@ -153,17 +134,6 @@
 
 /***************************************************************************/
 
-/*
- *  Program the vector to be an auto-vectored.
- */
-
-void mcf_autovector(unsigned int vec)
-{
-    /* Everything is auto-vectored on the 520x devices */
-}
-
-/***************************************************************************/
-
 static void m520x_cpu_reset(void)
 {
 	local_irq_disable();
diff --git a/arch/m68knommu/platform/520x/gpio.c b/arch/m68knommu/platform/520x/gpio.c
new file mode 100644
index 0000000..15b5bb6
--- /dev/null
+++ b/arch/m68knommu/platform/520x/gpio.c
@@ -0,0 +1,211 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PIRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFEPORT_EPDDR,
+		.podr				= MCFEPORT_EPDR,
+		.ppdr				= MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BUSCTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 8,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_BUSCTL,
+		.podr				= MCFGPIO_PODR_BUSCTL,
+		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= MCFGPIO_PCLRR_BUSCTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BE",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 16,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_BE,
+		.podr				= MCFGPIO_PODR_BE,
+		.ppdr				= MCFGPIO_PPDSDR_BE,
+		.setr				= MCFGPIO_PPDSDR_BE,
+		.clrr				= MCFGPIO_PCLRR_BE,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "CS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 25,
+			.ngpio			= 3,
+		},
+		.pddr				= MCFGPIO_PDDR_CS,
+		.podr				= MCFGPIO_PODR_CS,
+		.ppdr				= MCFGPIO_PPDSDR_CS,
+		.setr				= MCFGPIO_PPDSDR_CS,
+		.clrr				= MCFGPIO_PCLRR_CS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECI2C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_FECI2C,
+		.podr				= MCFGPIO_PODR_FECI2C,
+		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
+		.setr				= MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= MCFGPIO_PCLRR_FECI2C,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QSPI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_QSPI,
+		.podr				= MCFGPIO_PODR_QSPI,
+		.ppdr				= MCFGPIO_PPDSDR_QSPI,
+		.setr				= MCFGPIO_PPDSDR_QSPI,
+		.clrr				= MCFGPIO_PCLRR_QSPI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMER",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 48,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_TIMER,
+		.podr				= MCFGPIO_PODR_TIMER,
+		.ppdr				= MCFGPIO_PPDSDR_TIMER,
+		.setr				= MCFGPIO_PPDSDR_TIMER,
+		.clrr				= MCFGPIO_PCLRR_TIMER,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UART",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 56,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_UART,
+		.podr				= MCFGPIO_PODR_UART,
+		.ppdr				= MCFGPIO_PPDSDR_UART,
+		.setr				= MCFGPIO_PPDSDR_UART,
+		.clrr				= MCFGPIO_PCLRR_UART,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_FECH,
+		.podr				= MCFGPIO_PODR_FECH,
+		.ppdr				= MCFGPIO_PPDSDR_FECH,
+		.setr				= MCFGPIO_PPDSDR_FECH,
+		.clrr				= MCFGPIO_PCLRR_FECH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_FECL,
+		.podr				= MCFGPIO_PODR_FECL,
+		.ppdr				= MCFGPIO_PPDSDR_FECL,
+		.setr				= MCFGPIO_PPDSDR_FECL,
+		.clrr				= MCFGPIO_PCLRR_FECL,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/523x/Makefile b/arch/m68knommu/platform/523x/Makefile
index 5694d593..b8f9b45 100644
--- a/arch/m68knommu/platform/523x/Makefile
+++ b/arch/m68knommu/platform/523x/Makefile
@@ -14,4 +14,4 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-y := config.o
+obj-y := config.o gpio.o
diff --git a/arch/m68knommu/platform/523x/config.c b/arch/m68knommu/platform/523x/config.c
index 961fefe..6ba84f2 100644
--- a/arch/m68knommu/platform/523x/config.c
+++ b/arch/m68knommu/platform/523x/config.c
@@ -82,66 +82,20 @@
 
 /***************************************************************************/
 
-#define	INTC0	(MCF_MBAR + MCFICM_INTC0)
-
-static void __init m523x_uart_init_line(int line, int irq)
-{
-	u32 imr;
-
-	if ((line < 0) || (line > 2))
-		return;
-
-	writeb(0x30+line, (INTC0 + MCFINTC_ICR0 + MCFINT_UART0 + line));
-
-	imr = readl(INTC0 + MCFINTC_IMRL);
-	imr &= ~((1 << (irq - MCFINT_VECBASE)) | 1);
-	writel(imr, INTC0 + MCFINTC_IMRL);
-}
-
-static void __init m523x_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m523x_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m523x_uart_init_line(line, m523x_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
 static void __init m523x_fec_init(void)
 {
-	u32 imr;
+	u16 par;
+	u8 v;
 
-	/* Unmask FEC interrupts at ColdFire interrupt controller */
-	writeb(0x28, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 23);
-	writeb(0x27, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 27);
-	writeb(0x26, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 29);
-
-	imr = readl(MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
-	imr &= ~0xf;
-	writel(imr, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
-	imr = readl(MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
-	imr &= ~0xff800001;
-	writel(imr, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
+	/* Set multi-function pins to ethernet use */
+	par = readw(MCF_IPSBAR + 0x100082);
+	writew(par | 0xf00, MCF_IPSBAR + 0x100082);
+	v = readb(MCF_IPSBAR + 0x100078);
+	writeb(v | 0xc0, MCF_IPSBAR + 0x100078);
 }
 
 /***************************************************************************/
 
-void mcf_disableall(void)
-{
-	*((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff;
-	*((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff;
-}
-
-/***************************************************************************/
-
-void mcf_autovector(unsigned int vec)
-{
-	/* Everything is auto-vectored on the 523x */
-}
-/***************************************************************************/
-
 static void m523x_cpu_reset(void)
 {
 	local_irq_disable();
@@ -152,16 +106,14 @@
 
 void __init config_BSP(char *commandp, int size)
 {
-	mcf_disableall();
 	mach_reset = m523x_cpu_reset;
-	m523x_uarts_init();
-	m523x_fec_init();
 }
 
 /***************************************************************************/
 
 static int __init init_BSP(void)
 {
+	m523x_fec_init();
 	platform_add_devices(m523x_devices, ARRAY_SIZE(m523x_devices));
 	return 0;
 }
diff --git a/arch/m68knommu/platform/523x/gpio.c b/arch/m68knommu/platform/523x/gpio.c
new file mode 100644
index 0000000..f02840d
--- /dev/null
+++ b/arch/m68knommu/platform/523x/gpio.c
@@ -0,0 +1,283 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PIRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFEPORT_EPDDR,
+		.podr				= MCFEPORT_EPDR,
+		.ppdr				= MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "ADDR",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 13,
+			.ngpio			= 3,
+		},
+		.pddr				= MCFGPIO_PDDR_ADDR,
+		.podr				= MCFGPIO_PODR_ADDR,
+		.ppdr				= MCFGPIO_PPDSDR_ADDR,
+		.setr				= MCFGPIO_PPDSDR_ADDR,
+		.clrr				= MCFGPIO_PCLRR_ADDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "DATAH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 16,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_DATAH,
+		.podr				= MCFGPIO_PODR_DATAH,
+		.ppdr				= MCFGPIO_PPDSDR_DATAH,
+		.setr				= MCFGPIO_PPDSDR_DATAH,
+		.clrr				= MCFGPIO_PCLRR_DATAH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "DATAL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 24,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_DATAL,
+		.podr				= MCFGPIO_PODR_DATAL,
+		.ppdr				= MCFGPIO_PPDSDR_DATAL,
+		.setr				= MCFGPIO_PPDSDR_DATAL,
+		.clrr				= MCFGPIO_PCLRR_DATAL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BUSCTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_BUSCTL,
+		.podr				= MCFGPIO_PODR_BUSCTL,
+		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= MCFGPIO_PCLRR_BUSCTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_BS,
+		.podr				= MCFGPIO_PODR_BS,
+		.ppdr				= MCFGPIO_PPDSDR_BS,
+		.setr				= MCFGPIO_PPDSDR_BS,
+		.clrr				= MCFGPIO_PCLRR_BS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "CS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 49,
+			.ngpio			= 7,
+		},
+		.pddr				= MCFGPIO_PDDR_CS,
+		.podr				= MCFGPIO_PODR_CS,
+		.ppdr				= MCFGPIO_PPDSDR_CS,
+		.setr				= MCFGPIO_PPDSDR_CS,
+		.clrr				= MCFGPIO_PCLRR_CS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "SDRAM",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 56,
+			.ngpio			= 6,
+		},
+		.pddr				= MCFGPIO_PDDR_SDRAM,
+		.podr				= MCFGPIO_PODR_SDRAM,
+		.ppdr				= MCFGPIO_PPDSDR_SDRAM,
+		.setr				= MCFGPIO_PPDSDR_SDRAM,
+		.clrr				= MCFGPIO_PCLRR_SDRAM,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECI2C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_FECI2C,
+		.podr				= MCFGPIO_PODR_FECI2C,
+		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
+		.setr				= MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= MCFGPIO_PCLRR_FECI2C,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 2,
+		},
+		.pddr				= MCFGPIO_PDDR_UARTH,
+		.podr				= MCFGPIO_PODR_UARTH,
+		.ppdr				= MCFGPIO_PPDSDR_UARTH,
+		.setr				= MCFGPIO_PPDSDR_UARTH,
+		.clrr				= MCFGPIO_PCLRR_UARTH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 80,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_UARTL,
+		.podr				= MCFGPIO_PODR_UARTL,
+		.ppdr				= MCFGPIO_PPDSDR_UARTL,
+		.setr				= MCFGPIO_PPDSDR_UARTL,
+		.clrr				= MCFGPIO_PCLRR_UARTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QSPI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 88,
+			.ngpio			= 5,
+		},
+		.pddr				= MCFGPIO_PDDR_QSPI,
+		.podr				= MCFGPIO_PODR_QSPI,
+		.ppdr				= MCFGPIO_PPDSDR_QSPI,
+		.setr				= MCFGPIO_PPDSDR_QSPI,
+		.clrr				= MCFGPIO_PCLRR_QSPI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMER",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 96,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_TIMER,
+		.podr				= MCFGPIO_PODR_TIMER,
+		.ppdr				= MCFGPIO_PPDSDR_TIMER,
+		.setr				= MCFGPIO_PPDSDR_TIMER,
+		.clrr				= MCFGPIO_PCLRR_TIMER,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "ETPU",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 104,
+			.ngpio			= 3,
+		},
+		.pddr				= MCFGPIO_PDDR_ETPU,
+		.podr				= MCFGPIO_PODR_ETPU,
+		.ppdr				= MCFGPIO_PPDSDR_ETPU,
+		.setr				= MCFGPIO_PPDSDR_ETPU,
+		.clrr				= MCFGPIO_PCLRR_ETPU,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/5249/Makefile b/arch/m68knommu/platform/5249/Makefile
index a439d9a..f56225d 100644
--- a/arch/m68knommu/platform/5249/Makefile
+++ b/arch/m68knommu/platform/5249/Makefile
@@ -14,5 +14,5 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-y := config.o
+obj-y := config.o gpio.o intc2.o
 
diff --git a/arch/m68knommu/platform/5249/config.c b/arch/m68knommu/platform/5249/config.c
index 93d9988..646f5ba 100644
--- a/arch/m68knommu/platform/5249/config.c
+++ b/arch/m68knommu/platform/5249/config.c
@@ -48,11 +48,11 @@
 	if (line == 0) {
 		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
 		writeb(irq, MCF_MBAR + MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1);
+		mcf_mapirq2imr(irq, MCFINTC_UART0);
 	} else if (line == 1) {
 		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
 		writeb(irq, MCF_MBAR + MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2);
+		mcf_mapirq2imr(irq, MCFINTC_UART1);
 	}
 }
 
@@ -65,38 +65,21 @@
 		m5249_uart_init_line(line, m5249_uart_platform[line].irq);
 }
 
-
 /***************************************************************************/
 
-void mcf_autovector(unsigned int vec)
+static void __init m5249_timers_init(void)
 {
-	volatile unsigned char  *mbar;
+	/* Timer1 is always used as system timer */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER1ICR);
+	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
 
-	if ((vec >= 25) && (vec <= 31)) {
-		mbar = (volatile unsigned char *) MCF_MBAR;
-		vec = 0x1 << (vec - 24);
-		*(mbar + MCFSIM_AVR) |= vec;
-		mcf_setimr(mcf_getimr() & ~vec);
-	}
-}
-
-/***************************************************************************/
-
-void mcf_settimericr(unsigned int timer, unsigned int level)
-{
-	volatile unsigned char *icrp;
-	unsigned int icr, imr;
-
-	if (timer <= 2) {
-		switch (timer) {
-		case 2:  icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
-		default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
-		}
-
-		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
-		*icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
-		mcf_setimr(mcf_getimr() & ~imr);
-	}
+#ifdef CONFIG_HIGHPROFILE
+	/* Timer2 is to be used as a high speed profile timer  */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER2ICR);
+	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
+#endif
 }
 
 /***************************************************************************/
@@ -114,15 +97,15 @@
 
 void __init config_BSP(char *commandp, int size)
 {
-	mcf_setimr(MCFSIM_IMR_MASKALL);
 	mach_reset = m5249_cpu_reset;
+	m5249_timers_init();
+	m5249_uarts_init();
 }
 
 /***************************************************************************/
 
 static int __init init_BSP(void)
 {
-	m5249_uarts_init();
 	platform_add_devices(m5249_devices, ARRAY_SIZE(m5249_devices));
 	return 0;
 }
diff --git a/arch/m68knommu/platform/5249/gpio.c b/arch/m68knommu/platform/5249/gpio.c
new file mode 100644
index 0000000..c611eab
--- /dev/null
+++ b/arch/m68knommu/platform/5249/gpio.c
@@ -0,0 +1,65 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "GPIO0",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 32,
+		},
+		.pddr				= MCFSIM2_GPIOENABLE,
+		.podr				= MCFSIM2_GPIOWRITE,
+		.ppdr				= MCFSIM2_GPIOREAD,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "GPIO1",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 32,
+			.ngpio			= 32,
+		},
+		.pddr				= MCFSIM2_GPIO1ENABLE,
+		.podr				= MCFSIM2_GPIO1WRITE,
+		.ppdr				= MCFSIM2_GPIO1READ,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/5249/intc2.c b/arch/m68knommu/platform/5249/intc2.c
new file mode 100644
index 0000000..d09d9da
--- /dev/null
+++ b/arch/m68knommu/platform/5249/intc2.c
@@ -0,0 +1,59 @@
+/*
+ * intc2.c  -- support for the 2nd INTC controller of the 5249
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+static void intc2_irq_gpio_mask(unsigned int irq)
+{
+	u32 imr;
+	imr = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+	imr &= ~(0x1 << (irq - MCFINTC2_GPIOIRQ0));
+	writel(imr, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+}
+
+static void intc2_irq_gpio_unmask(unsigned int irq)
+{
+	u32 imr;
+	imr = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+	imr |= (0x1 << (irq - MCFINTC2_GPIOIRQ0));
+	writel(imr, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+}
+
+static void intc2_irq_gpio_ack(unsigned int irq)
+{
+	writel(0x1 << (irq - MCFINTC2_GPIOIRQ0), MCF_MBAR2 + MCFSIM2_GPIOINTCLEAR);
+}
+
+static struct irq_chip intc2_irq_gpio_chip = {
+	.name		= "CF-INTC2",
+	.mask		= intc2_irq_gpio_mask,
+	.unmask		= intc2_irq_gpio_unmask,
+	.ack		= intc2_irq_gpio_ack,
+};
+
+static int __init mcf_intc2_init(void)
+{
+	int irq;
+
+	/* GPIO interrupt sources */
+	for (irq = MCFINTC2_GPIOIRQ0; (irq <= MCFINTC2_GPIOIRQ7); irq++)
+		irq_desc[irq].chip = &intc2_irq_gpio_chip;
+
+	return 0;
+}
+
+arch_initcall(mcf_intc2_init);
diff --git a/arch/m68knommu/platform/5272/Makefile b/arch/m68knommu/platform/5272/Makefile
index 26135d9..93673ef 100644
--- a/arch/m68knommu/platform/5272/Makefile
+++ b/arch/m68knommu/platform/5272/Makefile
@@ -14,5 +14,5 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-y := config.o
+obj-y := config.o gpio.o intc.o
 
diff --git a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c
index 5f95fcd..59278c0 100644
--- a/arch/m68knommu/platform/5272/config.c
+++ b/arch/m68knommu/platform/5272/config.c
@@ -20,12 +20,6 @@
 
 /***************************************************************************/
 
-extern unsigned int mcf_timervector;
-extern unsigned int mcf_profilevector;
-extern unsigned int mcf_timerlevel;
-
-/***************************************************************************/
-
 /*
  *	Some platforms need software versions of the GPIO data registers.
  */
@@ -37,11 +31,11 @@
 static struct mcf_platform_uart m5272_uart_platform[] = {
 	{
 		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= 73,
+		.irq		= MCF_IRQ_UART1,
 	},
 	{
 		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= 74,
+		.irq		= MCF_IRQ_UART2,
 	},
 	{ },
 };
@@ -59,18 +53,18 @@
 		.flags		= IORESOURCE_MEM,
 	},
 	{
-		.start		= 86,
-		.end		= 86,
+		.start		= MCF_IRQ_ERX,
+		.end		= MCF_IRQ_ERX,
 		.flags		= IORESOURCE_IRQ,
 	},
 	{
-		.start		= 87,
-		.end		= 87,
+		.start		= MCF_IRQ_ETX,
+		.end		= MCF_IRQ_ETX,
 		.flags		= IORESOURCE_IRQ,
 	},
 	{
-		.start		= 88,
-		.end		= 88,
+		.start		= MCF_IRQ_ENTC,
+		.end		= MCF_IRQ_ENTC,
 		.flags		= IORESOURCE_IRQ,
 	},
 };
@@ -94,9 +88,6 @@
 	u32 v;
 
 	if ((line >= 0) && (line < 2)) {
-		v = (line) ? 0x0e000000 : 0xe0000000;
-		writel(v, MCF_MBAR + MCFSIM_ICR2);
-
 		/* Enable the output lines for the serial ports */
 		v = readl(MCF_MBAR + MCFSIM_PBCNT);
 		v = (v & ~0x000000ff) | 0x00000055;
@@ -119,54 +110,6 @@
 
 /***************************************************************************/
 
-static void __init m5272_fec_init(void)
-{
-	u32 imr;
-
-	/* Unmask FEC interrupts at ColdFire interrupt controller */
-	imr = readl(MCF_MBAR + MCFSIM_ICR3);
-	imr = (imr & ~0x00000fff) | 0x00000ddd;
-	writel(imr, MCF_MBAR + MCFSIM_ICR3);
-
-	imr = readl(MCF_MBAR + MCFSIM_ICR1);
-	imr = (imr & ~0x0f000000) | 0x0d000000;
-	writel(imr, MCF_MBAR + MCFSIM_ICR1);
-}
-
-/***************************************************************************/
-
-void mcf_disableall(void)
-{
-	volatile unsigned long	*icrp;
-
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	icrp[0] = 0x88888888;
-	icrp[1] = 0x88888888;
-	icrp[2] = 0x88888888;
-	icrp[3] = 0x88888888;
-}
-
-/***************************************************************************/
-
-void mcf_autovector(unsigned int vec)
-{
-	/* Everything is auto-vectored on the 5272 */
-}
-
-/***************************************************************************/
-
-void mcf_settimericr(int timer, int level)
-{
-	volatile unsigned long *icrp;
-
-	if ((timer >= 1 ) && (timer <= 4)) {
-		icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-		*icrp = (0x8 | level) << ((4 - timer) * 4);
-	}
-}
-
-/***************************************************************************/
-
 static void m5272_cpu_reset(void)
 {
 	local_irq_disable();
@@ -190,8 +133,6 @@
 	*pivrp = 0x40;
 #endif
 
-	mcf_disableall();
-
 #if defined(CONFIG_NETtel) || defined(CONFIG_SCALES)
 	/* Copy command line from FLASH to local buffer... */
 	memcpy(commandp, (char *) 0xf0004000, size);
@@ -202,8 +143,6 @@
 	commandp[size-1] = 0;
 #endif
 
-	mcf_timervector = 69;
-	mcf_profilevector = 70;
 	mach_reset = m5272_cpu_reset;
 }
 
@@ -212,7 +151,6 @@
 static int __init init_BSP(void)
 {
 	m5272_uarts_init();
-	m5272_fec_init();
 	platform_add_devices(m5272_devices, ARRAY_SIZE(m5272_devices));
 	return 0;
 }
diff --git a/arch/m68knommu/platform/5272/gpio.c b/arch/m68knommu/platform/5272/gpio.c
new file mode 100644
index 0000000..459db89
--- /dev/null
+++ b/arch/m68knommu/platform/5272/gpio.c
@@ -0,0 +1,81 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PA",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 16,
+		},
+		.pddr				= MCFSIM_PADDR,
+		.podr				= MCFSIM_PADAT,
+		.ppdr				= MCFSIM_PADAT,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "PB",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 16,
+			.ngpio			= 16,
+		},
+		.pddr				= MCFSIM_PBDDR,
+		.podr				= MCFSIM_PBDAT,
+		.ppdr				= MCFSIM_PBDAT,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "PC",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 32,
+			.ngpio			= 16,
+		},
+		.pddr				= MCFSIM_PCDDR,
+		.podr				= MCFSIM_PCDAT,
+		.ppdr				= MCFSIM_PCDAT,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/5272/intc.c b/arch/m68knommu/platform/5272/intc.c
new file mode 100644
index 0000000..7081e0a
--- /dev/null
+++ b/arch/m68knommu/platform/5272/intc.c
@@ -0,0 +1,138 @@
+/*
+ * intc.c  --  interrupt controller or ColdFire 5272 SoC
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/traps.h>
+
+/*
+ * The 5272 ColdFire interrupt controller is nothing like any other
+ * ColdFire interrupt controller - it truly is completely different.
+ * Given its age it is unlikely to be used on any other ColdFire CPU.
+ */
+
+/*
+ * The masking and priproty setting of interrupts on the 5272 is done
+ * via a set of 4 "Interrupt Controller Registers" (ICR). There is a
+ * loose mapping of vector number to register and internal bits, but
+ * a table is the easiest and quickest way to map them.
+ */
+struct irqmap {
+	unsigned char	icr;
+	unsigned char	index;
+	unsigned char	ack;
+};
+
+static struct irqmap intc_irqmap[MCFINT_VECMAX - MCFINT_VECBASE] = {
+	/*MCF_IRQ_SPURIOUS*/	{ .icr = 0,           .index = 0,  .ack = 0, },
+	/*MCF_IRQ_EINT1*/	{ .icr = MCFSIM_ICR1, .index = 28, .ack = 1, },
+	/*MCF_IRQ_EINT2*/	{ .icr = MCFSIM_ICR1, .index = 24, .ack = 1, },
+	/*MCF_IRQ_EINT3*/	{ .icr = MCFSIM_ICR1, .index = 20, .ack = 1, },
+	/*MCF_IRQ_EINT4*/	{ .icr = MCFSIM_ICR1, .index = 16, .ack = 1, },
+	/*MCF_IRQ_TIMER1*/	{ .icr = MCFSIM_ICR1, .index = 12, .ack = 0, },
+	/*MCF_IRQ_TIMER2*/	{ .icr = MCFSIM_ICR1, .index = 8,  .ack = 0, },
+	/*MCF_IRQ_TIMER3*/	{ .icr = MCFSIM_ICR1, .index = 4,  .ack = 0, },
+	/*MCF_IRQ_TIMER4*/	{ .icr = MCFSIM_ICR1, .index = 0,  .ack = 0, },
+	/*MCF_IRQ_UART1*/	{ .icr = MCFSIM_ICR2, .index = 28, .ack = 0, },
+	/*MCF_IRQ_UART2*/	{ .icr = MCFSIM_ICR2, .index = 24, .ack = 0, },
+	/*MCF_IRQ_PLIP*/	{ .icr = MCFSIM_ICR2, .index = 20, .ack = 0, },
+	/*MCF_IRQ_PLIA*/	{ .icr = MCFSIM_ICR2, .index = 16, .ack = 0, },
+	/*MCF_IRQ_USB0*/	{ .icr = MCFSIM_ICR2, .index = 12, .ack = 0, },
+	/*MCF_IRQ_USB1*/	{ .icr = MCFSIM_ICR2, .index = 8,  .ack = 0, },
+	/*MCF_IRQ_USB2*/	{ .icr = MCFSIM_ICR2, .index = 4,  .ack = 0, },
+	/*MCF_IRQ_USB3*/	{ .icr = MCFSIM_ICR2, .index = 0,  .ack = 0, },
+	/*MCF_IRQ_USB4*/	{ .icr = MCFSIM_ICR3, .index = 28, .ack = 0, },
+	/*MCF_IRQ_USB5*/	{ .icr = MCFSIM_ICR3, .index = 24, .ack = 0, },
+	/*MCF_IRQ_USB6*/	{ .icr = MCFSIM_ICR3, .index = 20, .ack = 0, },
+	/*MCF_IRQ_USB7*/	{ .icr = MCFSIM_ICR3, .index = 16, .ack = 0, },
+	/*MCF_IRQ_DMA*/		{ .icr = MCFSIM_ICR3, .index = 12, .ack = 0, },
+	/*MCF_IRQ_ERX*/		{ .icr = MCFSIM_ICR3, .index = 8,  .ack = 0, },
+	/*MCF_IRQ_ETX*/		{ .icr = MCFSIM_ICR3, .index = 4,  .ack = 0, },
+	/*MCF_IRQ_ENTC*/	{ .icr = MCFSIM_ICR3, .index = 0,  .ack = 0, },
+	/*MCF_IRQ_QSPI*/	{ .icr = MCFSIM_ICR4, .index = 28, .ack = 0, },
+	/*MCF_IRQ_EINT5*/	{ .icr = MCFSIM_ICR4, .index = 24, .ack = 1, },
+	/*MCF_IRQ_EINT6*/	{ .icr = MCFSIM_ICR4, .index = 20, .ack = 1, },
+	/*MCF_IRQ_SWTO*/	{ .icr = MCFSIM_ICR4, .index = 16, .ack = 0, },
+};
+
+static void intc_irq_mask(unsigned int irq)
+{
+	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
+		u32 v;
+		irq -= MCFINT_VECBASE;
+		v = 0x8 << intc_irqmap[irq].index;
+		writel(v, MCF_MBAR + intc_irqmap[irq].icr);
+	}
+}
+
+static void intc_irq_unmask(unsigned int irq)
+{
+	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
+		u32 v;
+		irq -= MCFINT_VECBASE;
+		v = 0xd << intc_irqmap[irq].index;
+		writel(v, MCF_MBAR + intc_irqmap[irq].icr);
+	}
+}
+
+static void intc_irq_ack(unsigned int irq)
+{
+	/* Only external interrupts are acked */
+	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
+		irq -= MCFINT_VECBASE;
+		if (intc_irqmap[irq].ack) {
+			u32 v;
+			v = 0xd << intc_irqmap[irq].index;
+			writel(v, MCF_MBAR + intc_irqmap[irq].icr);
+		}
+	}
+}
+
+static int intc_irq_set_type(unsigned int irq, unsigned int type)
+{
+	/* We can set the edge type here for external interrupts */
+	return 0;
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "CF-INTC",
+	.mask		= intc_irq_mask,
+	.unmask		= intc_irq_unmask,
+	.ack		= intc_irq_ack,
+	.set_type	= intc_irq_set_type,
+};
+
+void __init init_IRQ(void)
+{
+	int irq;
+
+	init_vectors();
+
+	/* Mask all interrupt sources */
+	writel(0x88888888, MCF_MBAR + MCFSIM_ICR1);
+	writel(0x88888888, MCF_MBAR + MCFSIM_ICR2);
+	writel(0x88888888, MCF_MBAR + MCFSIM_ICR3);
+	writel(0x88888888, MCF_MBAR + MCFSIM_ICR4);
+
+	for (irq = 0; (irq < NR_IRQS); irq++) {
+		irq_desc[irq].status = IRQ_DISABLED;
+		irq_desc[irq].action = NULL;
+		irq_desc[irq].depth = 1;
+		irq_desc[irq].chip = &intc_irq_chip;
+		intc_irq_set_type(irq, 0);
+	}
+}
+
diff --git a/arch/m68knommu/platform/527x/Makefile b/arch/m68knommu/platform/527x/Makefile
index 26135d9..3d90e6d 100644
--- a/arch/m68knommu/platform/527x/Makefile
+++ b/arch/m68knommu/platform/527x/Makefile
@@ -14,5 +14,5 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-y := config.o
+obj-y := config.o gpio.o
 
diff --git a/arch/m68knommu/platform/527x/config.c b/arch/m68knommu/platform/527x/config.c
index f746439..fa51be1 100644
--- a/arch/m68knommu/platform/527x/config.c
+++ b/arch/m68knommu/platform/527x/config.c
@@ -116,23 +116,13 @@
 
 /***************************************************************************/
 
-#define	INTC0	(MCF_MBAR + MCFICM_INTC0)
-
 static void __init m527x_uart_init_line(int line, int irq)
 {
 	u16 sepmask;
-	u32 imr;
 
 	if ((line < 0) || (line > 2))
 		return;
 
-	/* level 6, line based priority */
-	writeb(0x30+line, INTC0 + MCFINTC_ICR0 + MCFINT_UART0 + line);
-
-	imr = readl(INTC0 + MCFINTC_IMRL);
-	imr &= ~((1 << (irq - MCFINT_VECBASE)) | 1);
-	writel(imr, INTC0 + MCFINTC_IMRL);
-
 	/*
 	 * External Pin Mask Setting & Enable External Pin for Interface
 	 */
@@ -157,32 +147,11 @@
 
 /***************************************************************************/
 
-static void __init m527x_fec_irq_init(int nr)
-{
-	unsigned long base;
-	u32 imr;
-
-	base = MCF_IPSBAR + (nr ? MCFICM_INTC1 : MCFICM_INTC0);
-
-	writeb(0x28, base + MCFINTC_ICR0 + 23);
-	writeb(0x27, base + MCFINTC_ICR0 + 27);
-	writeb(0x26, base + MCFINTC_ICR0 + 29);
-
-	imr = readl(base + MCFINTC_IMRH);
-	imr &= ~0xf;
-	writel(imr, base + MCFINTC_IMRH);
-	imr = readl(base + MCFINTC_IMRL);
-	imr &= ~0xff800001;
-	writel(imr, base + MCFINTC_IMRL);
-}
-
 static void __init m527x_fec_init(void)
 {
 	u16 par;
 	u8 v;
 
-	m527x_fec_irq_init(0);
-
 	/* Set multi-function pins to ethernet mode for fec0 */
 #if defined(CONFIG_M5271)
 	v = readb(MCF_IPSBAR + 0x100047);
@@ -195,8 +164,6 @@
 #endif
 
 #ifdef CONFIG_FEC2
-	m527x_fec_irq_init(1);
-
 	/* Set multi-function pins to ethernet mode for fec1 */
 	par = readw(MCF_IPSBAR + 0x100082);
 	writew(par | 0xa0, MCF_IPSBAR + 0x100082);
@@ -207,21 +174,6 @@
 
 /***************************************************************************/
 
-void mcf_disableall(void)
-{
-	*((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff;
-	*((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff;
-}
-
-/***************************************************************************/
-
-void mcf_autovector(unsigned int vec)
-{
-	/* Everything is auto-vectored on the 5272 */
-}
-
-/***************************************************************************/
-
 static void m527x_cpu_reset(void)
 {
 	local_irq_disable();
@@ -232,7 +184,6 @@
 
 void __init config_BSP(char *commandp, int size)
 {
-	mcf_disableall();
 	mach_reset = m527x_cpu_reset;
 	m527x_uarts_init();
 	m527x_fec_init();
diff --git a/arch/m68knommu/platform/527x/gpio.c b/arch/m68knommu/platform/527x/gpio.c
new file mode 100644
index 0000000..1028142
--- /dev/null
+++ b/arch/m68knommu/platform/527x/gpio.c
@@ -0,0 +1,607 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+#if defined(CONFIG_M5271)
+	{
+		.gpio_chip			= {
+			.label			= "PIRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFEPORT_EPDDR,
+		.podr				= MCFEPORT_EPDR,
+		.ppdr				= MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "ADDR",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 13,
+			.ngpio			= 3,
+		},
+		.pddr				= MCFGPIO_PDDR_ADDR,
+		.podr				= MCFGPIO_PODR_ADDR,
+		.ppdr				= MCFGPIO_PPDSDR_ADDR,
+		.setr				= MCFGPIO_PPDSDR_ADDR,
+		.clrr				= MCFGPIO_PCLRR_ADDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "DATAH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 16,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_DATAH,
+		.podr				= MCFGPIO_PODR_DATAH,
+		.ppdr				= MCFGPIO_PPDSDR_DATAH,
+		.setr				= MCFGPIO_PPDSDR_DATAH,
+		.clrr				= MCFGPIO_PCLRR_DATAH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "DATAL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 24,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_DATAL,
+		.podr				= MCFGPIO_PODR_DATAL,
+		.ppdr				= MCFGPIO_PPDSDR_DATAL,
+		.setr				= MCFGPIO_PPDSDR_DATAL,
+		.clrr				= MCFGPIO_PCLRR_DATAL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BUSCTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_BUSCTL,
+		.podr				= MCFGPIO_PODR_BUSCTL,
+		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= MCFGPIO_PCLRR_BUSCTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_BS,
+		.podr				= MCFGPIO_PODR_BS,
+		.ppdr				= MCFGPIO_PPDSDR_BS,
+		.setr				= MCFGPIO_PPDSDR_BS,
+		.clrr				= MCFGPIO_PCLRR_BS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "CS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 49,
+			.ngpio			= 7,
+		},
+		.pddr				= MCFGPIO_PDDR_CS,
+		.podr				= MCFGPIO_PODR_CS,
+		.ppdr				= MCFGPIO_PPDSDR_CS,
+		.setr				= MCFGPIO_PPDSDR_CS,
+		.clrr				= MCFGPIO_PCLRR_CS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "SDRAM",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 56,
+			.ngpio			= 6,
+		},
+		.pddr				= MCFGPIO_PDDR_SDRAM,
+		.podr				= MCFGPIO_PODR_SDRAM,
+		.ppdr				= MCFGPIO_PPDSDR_SDRAM,
+		.setr				= MCFGPIO_PPDSDR_SDRAM,
+		.clrr				= MCFGPIO_PCLRR_SDRAM,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECI2C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_FECI2C,
+		.podr				= MCFGPIO_PODR_FECI2C,
+		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
+		.setr				= MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= MCFGPIO_PCLRR_FECI2C,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 2,
+		},
+		.pddr				= MCFGPIO_PDDR_UARTH,
+		.podr				= MCFGPIO_PODR_UARTH,
+		.ppdr				= MCFGPIO_PPDSDR_UARTH,
+		.setr				= MCFGPIO_PPDSDR_UARTH,
+		.clrr				= MCFGPIO_PCLRR_UARTH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 80,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_UARTL,
+		.podr				= MCFGPIO_PODR_UARTL,
+		.ppdr				= MCFGPIO_PPDSDR_UARTL,
+		.setr				= MCFGPIO_PPDSDR_UARTL,
+		.clrr				= MCFGPIO_PCLRR_UARTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QSPI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 88,
+			.ngpio			= 5,
+		},
+		.pddr				= MCFGPIO_PDDR_QSPI,
+		.podr				= MCFGPIO_PODR_QSPI,
+		.ppdr				= MCFGPIO_PPDSDR_QSPI,
+		.setr				= MCFGPIO_PPDSDR_QSPI,
+		.clrr				= MCFGPIO_PCLRR_QSPI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMER",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 96,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_TIMER,
+		.podr				= MCFGPIO_PODR_TIMER,
+		.ppdr				= MCFGPIO_PPDSDR_TIMER,
+		.setr				= MCFGPIO_PPDSDR_TIMER,
+		.clrr				= MCFGPIO_PCLRR_TIMER,
+	},
+#elif defined(CONFIG_M5275)
+	{
+		.gpio_chip			= {
+			.label			= "PIRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFEPORT_EPDDR,
+		.podr				= MCFEPORT_EPDR,
+		.ppdr				= MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BUSCTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 8,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_BUSCTL,
+		.podr				= MCFGPIO_PODR_BUSCTL,
+		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= MCFGPIO_PCLRR_BUSCTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "ADDR",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 21,
+			.ngpio			= 3,
+		},
+		.pddr				= MCFGPIO_PDDR_ADDR,
+		.podr				= MCFGPIO_PODR_ADDR,
+		.ppdr				= MCFGPIO_PPDSDR_ADDR,
+		.setr				= MCFGPIO_PPDSDR_ADDR,
+		.clrr				= MCFGPIO_PCLRR_ADDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "CS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 25,
+			.ngpio			= 7,
+		},
+		.pddr				= MCFGPIO_PDDR_CS,
+		.podr				= MCFGPIO_PODR_CS,
+		.ppdr				= MCFGPIO_PPDSDR_CS,
+		.setr				= MCFGPIO_PPDSDR_CS,
+		.clrr				= MCFGPIO_PCLRR_CS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FEC0H",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_FEC0H,
+		.podr				= MCFGPIO_PODR_FEC0H,
+		.ppdr				= MCFGPIO_PPDSDR_FEC0H,
+		.setr				= MCFGPIO_PPDSDR_FEC0H,
+		.clrr				= MCFGPIO_PCLRR_FEC0H,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FEC0L",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_FEC0L,
+		.podr				= MCFGPIO_PODR_FEC0L,
+		.ppdr				= MCFGPIO_PPDSDR_FEC0L,
+		.setr				= MCFGPIO_PPDSDR_FEC0L,
+		.clrr				= MCFGPIO_PCLRR_FEC0L,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECI2C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 48,
+			.ngpio			= 6,
+		},
+		.pddr				= MCFGPIO_PDDR_FECI2C,
+		.podr				= MCFGPIO_PODR_FECI2C,
+		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
+		.setr				= MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= MCFGPIO_PCLRR_FECI2C,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QSPI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 56,
+			.ngpio			= 7,
+		},
+		.pddr				= MCFGPIO_PDDR_QSPI,
+		.podr				= MCFGPIO_PODR_QSPI,
+		.ppdr				= MCFGPIO_PPDSDR_QSPI,
+		.setr				= MCFGPIO_PPDSDR_QSPI,
+		.clrr				= MCFGPIO_PCLRR_QSPI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "SDRAM",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_SDRAM,
+		.podr				= MCFGPIO_PODR_SDRAM,
+		.ppdr				= MCFGPIO_PPDSDR_SDRAM,
+		.setr				= MCFGPIO_PPDSDR_SDRAM,
+		.clrr				= MCFGPIO_PCLRR_SDRAM,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMERH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_TIMERH,
+		.podr				= MCFGPIO_PODR_TIMERH,
+		.ppdr				= MCFGPIO_PPDSDR_TIMERH,
+		.setr				= MCFGPIO_PPDSDR_TIMERH,
+		.clrr				= MCFGPIO_PCLRR_TIMERH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMERL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 80,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_TIMERL,
+		.podr				= MCFGPIO_PODR_TIMERL,
+		.ppdr				= MCFGPIO_PPDSDR_TIMERL,
+		.setr				= MCFGPIO_PPDSDR_TIMERL,
+		.clrr				= MCFGPIO_PCLRR_TIMERL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 88,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_UARTL,
+		.podr				= MCFGPIO_PODR_UARTL,
+		.ppdr				= MCFGPIO_PPDSDR_UARTL,
+		.setr				= MCFGPIO_PPDSDR_UARTL,
+		.clrr				= MCFGPIO_PCLRR_UARTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FEC1H",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 96,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_FEC1H,
+		.podr				= MCFGPIO_PODR_FEC1H,
+		.ppdr				= MCFGPIO_PPDSDR_FEC1H,
+		.setr				= MCFGPIO_PPDSDR_FEC1H,
+		.clrr				= MCFGPIO_PCLRR_FEC1H,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FEC1L",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 104,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_FEC1L,
+		.podr				= MCFGPIO_PODR_FEC1L,
+		.ppdr				= MCFGPIO_PPDSDR_FEC1L,
+		.setr				= MCFGPIO_PPDSDR_FEC1L,
+		.clrr				= MCFGPIO_PCLRR_FEC1L,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 114,
+			.ngpio			= 2,
+		},
+		.pddr				= MCFGPIO_PDDR_BS,
+		.podr				= MCFGPIO_PODR_BS,
+		.ppdr				= MCFGPIO_PPDSDR_BS,
+		.setr				= MCFGPIO_PPDSDR_BS,
+		.clrr				= MCFGPIO_PCLRR_BS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "IRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 121,
+			.ngpio			= 7,
+		},
+		.pddr				= MCFGPIO_PDDR_IRQ,
+		.podr				= MCFGPIO_PODR_IRQ,
+		.ppdr				= MCFGPIO_PPDSDR_IRQ,
+		.setr				= MCFGPIO_PPDSDR_IRQ,
+		.clrr				= MCFGPIO_PCLRR_IRQ,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "USBH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 128,
+			.ngpio			= 1,
+		},
+		.pddr				= MCFGPIO_PDDR_USBH,
+		.podr				= MCFGPIO_PODR_USBH,
+		.ppdr				= MCFGPIO_PPDSDR_USBH,
+		.setr				= MCFGPIO_PPDSDR_USBH,
+		.clrr				= MCFGPIO_PCLRR_USBH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "USBL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 136,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_USBL,
+		.podr				= MCFGPIO_PODR_USBL,
+		.ppdr				= MCFGPIO_PPDSDR_USBL,
+		.setr				= MCFGPIO_PPDSDR_USBL,
+		.clrr				= MCFGPIO_PCLRR_USBL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 144,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_UARTH,
+		.podr				= MCFGPIO_PODR_UARTH,
+		.ppdr				= MCFGPIO_PPDSDR_UARTH,
+		.setr				= MCFGPIO_PPDSDR_UARTH,
+		.clrr				= MCFGPIO_PCLRR_UARTH,
+	},
+#endif
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/528x/Makefile b/arch/m68knommu/platform/528x/Makefile
index 26135d9..3d90e6d 100644
--- a/arch/m68knommu/platform/528x/Makefile
+++ b/arch/m68knommu/platform/528x/Makefile
@@ -14,5 +14,5 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-y := config.o
+obj-y := config.o gpio.o
 
diff --git a/arch/m68knommu/platform/528x/config.c b/arch/m68knommu/platform/528x/config.c
index a1d1a61..6e608d1 100644
--- a/arch/m68knommu/platform/528x/config.c
+++ b/arch/m68knommu/platform/528x/config.c
@@ -3,8 +3,8 @@
 /*
  *	linux/arch/m68knommu/platform/528x/config.c
  *
- *	Sub-architcture dependant initialization code for the Motorola
- *	5280 and 5282 CPUs.
+ *	Sub-architcture dependant initialization code for the Freescale
+ *	5280, 5281 and 5282 CPUs.
  *
  *	Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
  *	Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
@@ -15,20 +15,13 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/flash.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
 
-#ifdef CONFIG_MTD_PARTITIONS
-#include <linux/mtd/partitions.h>
-#endif
-
 /***************************************************************************/
 
 static struct mcf_platform_uart m528x_uart_platform[] = {
@@ -91,23 +84,13 @@
 
 /***************************************************************************/
 
-#define	INTC0	(MCF_MBAR + MCFICM_INTC0)
-
 static void __init m528x_uart_init_line(int line, int irq)
 {
 	u8 port;
-	u32 imr;
 
 	if ((line < 0) || (line > 2))
 		return;
 
-	/* level 6, line based priority */
-	writeb(0x30+line, INTC0 + MCFINTC_ICR0 + MCFINT_UART0 + line);
-
-	imr = readl(INTC0 + MCFINTC_IMRL);
-	imr &= ~((1 << (irq - MCFINT_VECBASE)) | 1);
-	writel(imr, INTC0 + MCFINTC_IMRL);
-
 	/* make sure PUAPAR is set for UART0 and UART1 */
 	if (line < 2) {
 		port = readb(MCF_MBAR + MCF5282_GPIO_PUAPAR);
@@ -129,21 +112,8 @@
 
 static void __init m528x_fec_init(void)
 {
-	u32 imr;
 	u16 v16;
 
-	/* Unmask FEC interrupts at ColdFire interrupt controller */
-	writeb(0x28, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 23);
-	writeb(0x27, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 27);
-	writeb(0x26, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 29);
-
-	imr = readl(MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
-	imr &= ~0xf;
-	writel(imr, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
-	imr = readl(MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
-	imr &= ~0xff800001;
-	writel(imr, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
-
 	/* Set multi-function pins to ethernet mode for fec0 */
 	v16 = readw(MCF_IPSBAR + 0x100056);
 	writew(v16 | 0xf00, MCF_IPSBAR + 0x100056);
@@ -152,21 +122,6 @@
 
 /***************************************************************************/
 
-void mcf_disableall(void)
-{
-	*((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff;
-	*((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff;
-}
-
-/***************************************************************************/
-
-void mcf_autovector(unsigned int vec)
-{
-	/* Everything is auto-vectored on the 5272 */
-}
-
-/***************************************************************************/
-
 static void m528x_cpu_reset(void)
 {
 	local_irq_disable();
@@ -204,8 +159,6 @@
 
 void __init config_BSP(char *commandp, int size)
 {
-	mcf_disableall();
-
 #ifdef CONFIG_WILDFIRE
 	mach_halt = wildfire_halt;
 #endif
diff --git a/arch/m68knommu/platform/528x/gpio.c b/arch/m68knommu/platform/528x/gpio.c
new file mode 100644
index 0000000..ec59395
--- /dev/null
+++ b/arch/m68knommu/platform/528x/gpio.c
@@ -0,0 +1,438 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "NQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 1,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFEPORT_EPDDR,
+		.podr				= MCFEPORT_EPDR,
+		.ppdr				= MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TA",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 8,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPTA_GPTDDR,
+		.podr				= MCFGPTA_GPTPORT,
+		.ppdr				= MCFGPTB_GPTPORT,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TB",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 16,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPTB_GPTDDR,
+		.podr				= MCFGPTB_GPTPORT,
+		.ppdr				= MCFGPTB_GPTPORT,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QA",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 24,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFQADC_DDRQA,
+		.podr				= MCFQADC_PORTQA,
+		.ppdr				= MCFQADC_PORTQA,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QB",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFQADC_DDRQB,
+		.podr				= MCFQADC_PORTQB,
+		.ppdr				= MCFQADC_PORTQB,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "A",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDRA,
+		.podr				= MCFGPIO_PORTA,
+		.ppdr				= MCFGPIO_PORTAP,
+		.setr				= MCFGPIO_SETA,
+		.clrr				= MCFGPIO_CLRA,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "B",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 48,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDRB,
+		.podr				= MCFGPIO_PORTB,
+		.ppdr				= MCFGPIO_PORTBP,
+		.setr				= MCFGPIO_SETB,
+		.clrr				= MCFGPIO_CLRB,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 56,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDRC,
+		.podr				= MCFGPIO_PORTC,
+		.ppdr				= MCFGPIO_PORTCP,
+		.setr				= MCFGPIO_SETC,
+		.clrr				= MCFGPIO_CLRC,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "D",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDRD,
+		.podr				= MCFGPIO_PORTD,
+		.ppdr				= MCFGPIO_PORTDP,
+		.setr				= MCFGPIO_SETD,
+		.clrr				= MCFGPIO_CLRD,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "E",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDRE,
+		.podr				= MCFGPIO_PORTE,
+		.ppdr				= MCFGPIO_PORTEP,
+		.setr				= MCFGPIO_SETE,
+		.clrr				= MCFGPIO_CLRE,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "F",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 80,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDRF,
+		.podr				= MCFGPIO_PORTF,
+		.ppdr				= MCFGPIO_PORTFP,
+		.setr				= MCFGPIO_SETF,
+		.clrr				= MCFGPIO_CLRF,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "G",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 88,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDRG,
+		.podr				= MCFGPIO_PORTG,
+		.ppdr				= MCFGPIO_PORTGP,
+		.setr				= MCFGPIO_SETG,
+		.clrr				= MCFGPIO_CLRG,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "H",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 96,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDRH,
+		.podr				= MCFGPIO_PORTH,
+		.ppdr				= MCFGPIO_PORTHP,
+		.setr				= MCFGPIO_SETH,
+		.clrr				= MCFGPIO_CLRH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "J",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 104,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDRJ,
+		.podr				= MCFGPIO_PORTJ,
+		.ppdr				= MCFGPIO_PORTJP,
+		.setr				= MCFGPIO_SETJ,
+		.clrr				= MCFGPIO_CLRJ,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "DD",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 112,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDRDD,
+		.podr				= MCFGPIO_PORTDD,
+		.ppdr				= MCFGPIO_PORTDDP,
+		.setr				= MCFGPIO_SETDD,
+		.clrr				= MCFGPIO_CLRDD,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "EH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 120,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDREH,
+		.podr				= MCFGPIO_PORTEH,
+		.ppdr				= MCFGPIO_PORTEHP,
+		.setr				= MCFGPIO_SETEH,
+		.clrr				= MCFGPIO_CLREH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "EL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 128,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_DDREL,
+		.podr				= MCFGPIO_PORTEL,
+		.ppdr				= MCFGPIO_PORTELP,
+		.setr				= MCFGPIO_SETEL,
+		.clrr				= MCFGPIO_CLREL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "AS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 136,
+			.ngpio			= 6,
+		},
+		.pddr				= MCFGPIO_DDRAS,
+		.podr				= MCFGPIO_PORTAS,
+		.ppdr				= MCFGPIO_PORTASP,
+		.setr				= MCFGPIO_SETAS,
+		.clrr				= MCFGPIO_CLRAS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 144,
+			.ngpio			= 7,
+		},
+		.pddr				= MCFGPIO_DDRQS,
+		.podr				= MCFGPIO_PORTQS,
+		.ppdr				= MCFGPIO_PORTQSP,
+		.setr				= MCFGPIO_SETQS,
+		.clrr				= MCFGPIO_CLRQS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "SD",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 152,
+			.ngpio			= 6,
+		},
+		.pddr				= MCFGPIO_DDRSD,
+		.podr				= MCFGPIO_PORTSD,
+		.ppdr				= MCFGPIO_PORTSDP,
+		.setr				= MCFGPIO_SETSD,
+		.clrr				= MCFGPIO_CLRSD,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TC",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 160,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_DDRTC,
+		.podr				= MCFGPIO_PORTTC,
+		.ppdr				= MCFGPIO_PORTTCP,
+		.setr				= MCFGPIO_SETTC,
+		.clrr				= MCFGPIO_CLRTC,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TD",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 168,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_DDRTD,
+		.podr				= MCFGPIO_PORTTD,
+		.ppdr				= MCFGPIO_PORTTDP,
+		.setr				= MCFGPIO_SETTD,
+		.clrr				= MCFGPIO_CLRTD,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UA",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 176,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_DDRUA,
+		.podr				= MCFGPIO_PORTUA,
+		.ppdr				= MCFGPIO_PORTUAP,
+		.setr				= MCFGPIO_SETUA,
+		.clrr				= MCFGPIO_CLRUA,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
index cfd5868..667db65 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68knommu/platform/5307/Makefile
@@ -14,5 +14,5 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-y	+= config.o
+obj-y	+= config.o gpio.o
 
diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c
index 39da9e9..00900ac 100644
--- a/arch/m68knommu/platform/5307/config.c
+++ b/arch/m68knommu/platform/5307/config.c
@@ -21,12 +21,6 @@
 
 /***************************************************************************/
 
-extern unsigned int mcf_timervector;
-extern unsigned int mcf_profilevector;
-extern unsigned int mcf_timerlevel;
-
-/***************************************************************************/
-
 /*
  *	Some platforms need software versions of the GPIO data registers.
  */
@@ -64,11 +58,11 @@
 	if (line == 0) {
 		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
 		writeb(irq, MCF_MBAR + MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1);
+		mcf_mapirq2imr(irq, MCFINTC_UART0);
 	} else if (line == 1) {
 		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
 		writeb(irq, MCF_MBAR + MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2);
+		mcf_mapirq2imr(irq, MCFINTC_UART1);
 	}
 }
 
@@ -83,35 +77,19 @@
 
 /***************************************************************************/
 
-void mcf_autovector(unsigned int vec)
+static void __init m5307_timers_init(void)
 {
-	volatile unsigned char  *mbar;
+	/* Timer1 is always used as system timer */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER1ICR);
+	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
 
-	if ((vec >= 25) && (vec <= 31)) {
-		mbar = (volatile unsigned char *) MCF_MBAR;
-		vec = 0x1 << (vec - 24);
-		*(mbar + MCFSIM_AVR) |= vec;
-		mcf_setimr(mcf_getimr() & ~vec);
-	}
-}
-
-/***************************************************************************/
-
-void mcf_settimericr(unsigned int timer, unsigned int level)
-{
-	volatile unsigned char *icrp;
-	unsigned int icr, imr;
-
-	if (timer <= 2) {
-		switch (timer) {
-		case 2:  icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
-		default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
-		}
-
-		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
-		*icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
-		mcf_setimr(mcf_getimr() & ~imr);
-	}
+#ifdef CONFIG_HIGHPROFILE
+	/* Timer2 is to be used as a high speed profile timer  */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER2ICR);
+	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
+#endif
 }
 
 /***************************************************************************/
@@ -129,20 +107,22 @@
 
 void __init config_BSP(char *commandp, int size)
 {
-	mcf_setimr(MCFSIM_IMR_MASKALL);
-
 #if defined(CONFIG_NETtel) || \
     defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
 	/* Copy command line from FLASH to local buffer... */
 	memcpy(commandp, (char *) 0xf0004000, size);
 	commandp[size-1] = 0;
-	/* Different timer setup - to prevent device clash */
-	mcf_timervector = 30;
-	mcf_profilevector = 31;
-	mcf_timerlevel = 6;
 #endif
 
 	mach_reset = m5307_cpu_reset;
+	m5307_timers_init();
+	m5307_uarts_init();
+
+	/* Only support the external interrupts on their primary level */
+	mcf_mapirq2imr(25, MCFINTC_EINT1);
+	mcf_mapirq2imr(27, MCFINTC_EINT3);
+	mcf_mapirq2imr(29, MCFINTC_EINT5);
+	mcf_mapirq2imr(31, MCFINTC_EINT7);
 
 #ifdef CONFIG_BDM_DISABLE
 	/*
@@ -158,7 +138,6 @@
 
 static int __init init_BSP(void)
 {
-	m5307_uarts_init();
 	platform_add_devices(m5307_devices, ARRAY_SIZE(m5307_devices));
 	return 0;
 }
diff --git a/arch/m68knommu/platform/5307/gpio.c b/arch/m68knommu/platform/5307/gpio.c
new file mode 100644
index 0000000..8da5880
--- /dev/null
+++ b/arch/m68knommu/platform/5307/gpio.c
@@ -0,0 +1,49 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PP",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 16,
+		},
+		.pddr				= MCFSIM_PADDR,
+		.podr				= MCFSIM_PADAT,
+		.ppdr				= MCFSIM_PADAT,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/532x/Makefile b/arch/m68knommu/platform/532x/Makefile
index e431912..4cc2324 100644
--- a/arch/m68knommu/platform/532x/Makefile
+++ b/arch/m68knommu/platform/532x/Makefile
@@ -15,4 +15,4 @@
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
 #obj-y := config.o usb-mcf532x.o spi-mcf532x.o
-obj-y := config.o
+obj-y := config.o gpio.o
diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c
index cdb7619..d632948 100644
--- a/arch/m68knommu/platform/532x/config.c
+++ b/arch/m68knommu/platform/532x/config.c
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -31,12 +30,6 @@
 
 /***************************************************************************/
 
-extern unsigned int mcf_timervector;
-extern unsigned int mcf_profilevector;
-extern unsigned int mcf_timerlevel;
-
-/***************************************************************************/
-
 static struct mcf_platform_uart m532x_uart_platform[] = {
 	{
 		.mapbase	= MCFUART_BASE1,
@@ -88,6 +81,7 @@
 	.num_resources		= ARRAY_SIZE(m532x_fec_resources),
 	.resource		= m532x_fec_resources,
 };
+
 static struct platform_device *m532x_devices[] __initdata = {
 	&m532x_uart,
 	&m532x_fec,
@@ -98,18 +92,11 @@
 static void __init m532x_uart_init_line(int line, int irq)
 {
 	if (line == 0) {
-		MCF_INTC0_ICR26 = 0x3;
-		MCF_INTC0_CIMR = 26;
 		/* GPIO initialization */
 		MCF_GPIO_PAR_UART |= 0x000F;
 	} else if (line == 1) {
-		MCF_INTC0_ICR27 = 0x3;
-		MCF_INTC0_CIMR = 27;
 		/* GPIO initialization */
 		MCF_GPIO_PAR_UART |= 0x0FF0;
-	} else if (line == 2) {
-		MCF_INTC0_ICR28 = 0x3;
-		MCF_INTC0_CIMR = 28;
 	}
 }
 
@@ -125,14 +112,6 @@
 
 static void __init m532x_fec_init(void)
 {
-	/* Unmask FEC interrupts at ColdFire interrupt controller */
-	MCF_INTC0_ICR36 = 0x2;
-	MCF_INTC0_ICR40 = 0x2;
-	MCF_INTC0_ICR42 = 0x2;
-
-	MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK36 |
-		MCF_INTC_IMRH_INT_MASK40 | MCF_INTC_IMRH_INT_MASK42);
-
 	/* Set multi-function pins to ethernet mode for fec0 */
 	MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
 		MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
@@ -142,26 +121,6 @@
 
 /***************************************************************************/
 
-void mcf_settimericr(unsigned int timer, unsigned int level)
-{
-	volatile unsigned char *icrp;
-	unsigned int icr;
-	unsigned char irq;
-
-	if (timer <= 2) {
-		switch (timer) {
-		case 2:  irq = 33; icr = MCFSIM_ICR_TIMER2; break;
-		default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
-		}
-		
-		icrp = (volatile unsigned char *) (icr);
-		*icrp = level;
-		mcf_enable_irq0(irq);
-	}
-}
-
-/***************************************************************************/
-
 static void m532x_cpu_reset(void)
 {
 	local_irq_disable();
@@ -172,8 +131,6 @@
 
 void __init config_BSP(char *commandp, int size)
 {
-	mcf_setimr(MCFSIM_IMR_MASKALL);
-
 #if !defined(CONFIG_BOOTPARAM)
 	/* Copy command line from FLASH to local buffer... */
 	memcpy(commandp, (char *) 0x4000, 4);
@@ -185,10 +142,6 @@
 	}
 #endif
 
-	mcf_timervector = 64+32;
-	mcf_profilevector = 64+33;
-	mach_reset = m532x_cpu_reset;
-
 #ifdef CONFIG_BDM_DISABLE
 	/*
 	 * Disable the BDM clocking.  This also turns off most of the rest of
@@ -438,8 +391,8 @@
 	/* Initialize TIN3 as a GPIO output to enable the write
 	   half of the latch */
 	MCF_GPIO_PAR_TIMER = 0x00;
-	MCF_GPIO_PDDR_TIMER = 0x08;
-	MCF_GPIO_PCLRR_TIMER = 0x0;
+	__raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
+	__raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
 
 }
 
diff --git a/arch/m68knommu/platform/532x/gpio.c b/arch/m68knommu/platform/532x/gpio.c
new file mode 100644
index 0000000..184b773
--- /dev/null
+++ b/arch/m68knommu/platform/532x/gpio.c
@@ -0,0 +1,337 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PIRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFEPORT_EPDDR,
+		.podr				= MCFEPORT_EPDR,
+		.ppdr				= MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 8,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_FECH,
+		.podr				= MCFGPIO_PODR_FECH,
+		.ppdr				= MCFGPIO_PPDSDR_FECH,
+		.setr				= MCFGPIO_PPDSDR_FECH,
+		.clrr				= MCFGPIO_PCLRR_FECH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 16,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_FECL,
+		.podr				= MCFGPIO_PODR_FECL,
+		.ppdr				= MCFGPIO_PPDSDR_FECL,
+		.setr				= MCFGPIO_PPDSDR_FECL,
+		.clrr				= MCFGPIO_PCLRR_FECL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "SSI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 24,
+			.ngpio			= 5,
+		},
+		.pddr				= MCFGPIO_PDDR_SSI,
+		.podr				= MCFGPIO_PODR_SSI,
+		.ppdr				= MCFGPIO_PPDSDR_SSI,
+		.setr				= MCFGPIO_PPDSDR_SSI,
+		.clrr				= MCFGPIO_PCLRR_SSI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BUSCTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_BUSCTL,
+		.podr				= MCFGPIO_PODR_BUSCTL,
+		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= MCFGPIO_PCLRR_BUSCTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BE",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_BE,
+		.podr				= MCFGPIO_PODR_BE,
+		.ppdr				= MCFGPIO_PPDSDR_BE,
+		.setr				= MCFGPIO_PPDSDR_BE,
+		.clrr				= MCFGPIO_PCLRR_BE,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "CS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 49,
+			.ngpio			= 5,
+		},
+		.pddr				= MCFGPIO_PDDR_CS,
+		.podr				= MCFGPIO_PODR_CS,
+		.ppdr				= MCFGPIO_PPDSDR_CS,
+		.setr				= MCFGPIO_PPDSDR_CS,
+		.clrr				= MCFGPIO_PCLRR_CS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "PWM",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 58,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_PWM,
+		.podr				= MCFGPIO_PODR_PWM,
+		.ppdr				= MCFGPIO_PPDSDR_PWM,
+		.setr				= MCFGPIO_PPDSDR_PWM,
+		.clrr				= MCFGPIO_PCLRR_PWM,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECI2C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_FECI2C,
+		.podr				= MCFGPIO_PODR_FECI2C,
+		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
+		.setr				= MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= MCFGPIO_PCLRR_FECI2C,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UART",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_UART,
+		.podr				= MCFGPIO_PODR_UART,
+		.ppdr				= MCFGPIO_PPDSDR_UART,
+		.setr				= MCFGPIO_PPDSDR_UART,
+		.clrr				= MCFGPIO_PCLRR_UART,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QSPI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 80,
+			.ngpio			= 6,
+		},
+		.pddr				= MCFGPIO_PDDR_QSPI,
+		.podr				= MCFGPIO_PODR_QSPI,
+		.ppdr				= MCFGPIO_PPDSDR_QSPI,
+		.setr				= MCFGPIO_PPDSDR_QSPI,
+		.clrr				= MCFGPIO_PCLRR_QSPI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMER",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 88,
+			.ngpio			= 4,
+		},
+		.pddr				= MCFGPIO_PDDR_TIMER,
+		.podr				= MCFGPIO_PODR_TIMER,
+		.ppdr				= MCFGPIO_PPDSDR_TIMER,
+		.setr				= MCFGPIO_PPDSDR_TIMER,
+		.clrr				= MCFGPIO_PCLRR_TIMER,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "LCDDATAH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 96,
+			.ngpio			= 2,
+		},
+		.pddr				= MCFGPIO_PDDR_LCDDATAH,
+		.podr				= MCFGPIO_PODR_LCDDATAH,
+		.ppdr				= MCFGPIO_PPDSDR_LCDDATAH,
+		.setr				= MCFGPIO_PPDSDR_LCDDATAH,
+		.clrr				= MCFGPIO_PCLRR_LCDDATAH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "LCDDATAM",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 104,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_LCDDATAM,
+		.podr				= MCFGPIO_PODR_LCDDATAM,
+		.ppdr				= MCFGPIO_PPDSDR_LCDDATAM,
+		.setr				= MCFGPIO_PPDSDR_LCDDATAM,
+		.clrr				= MCFGPIO_PCLRR_LCDDATAM,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "LCDDATAL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 112,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_LCDDATAL,
+		.podr				= MCFGPIO_PODR_LCDDATAL,
+		.ppdr				= MCFGPIO_PPDSDR_LCDDATAL,
+		.setr				= MCFGPIO_PPDSDR_LCDDATAL,
+		.clrr				= MCFGPIO_PCLRR_LCDDATAL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "LCDCTLH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 120,
+			.ngpio			= 1,
+		},
+		.pddr				= MCFGPIO_PDDR_LCDCTLH,
+		.podr				= MCFGPIO_PODR_LCDCTLH,
+		.ppdr				= MCFGPIO_PPDSDR_LCDCTLH,
+		.setr				= MCFGPIO_PPDSDR_LCDCTLH,
+		.clrr				= MCFGPIO_PCLRR_LCDCTLH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "LCDCTLL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 128,
+			.ngpio			= 8,
+		},
+		.pddr				= MCFGPIO_PDDR_LCDCTLL,
+		.podr				= MCFGPIO_PODR_LCDCTLL,
+		.ppdr				= MCFGPIO_PPDSDR_LCDCTLL,
+		.setr				= MCFGPIO_PPDSDR_LCDCTLL,
+		.clrr				= MCFGPIO_PCLRR_LCDCTLL,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/5407/Makefile b/arch/m68knommu/platform/5407/Makefile
index e6035e7..dee62c5 100644
--- a/arch/m68knommu/platform/5407/Makefile
+++ b/arch/m68knommu/platform/5407/Makefile
@@ -14,5 +14,5 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-y := config.o
+obj-y := config.o gpio.o
 
diff --git a/arch/m68knommu/platform/5407/config.c b/arch/m68knommu/platform/5407/config.c
index b41d942..70ea789 100644
--- a/arch/m68knommu/platform/5407/config.c
+++ b/arch/m68knommu/platform/5407/config.c
@@ -20,12 +20,6 @@
 
 /***************************************************************************/
 
-extern unsigned int mcf_timervector;
-extern unsigned int mcf_profilevector;
-extern unsigned int mcf_timerlevel;
-
-/***************************************************************************/
-
 static struct mcf_platform_uart m5407_uart_platform[] = {
 	{
 		.mapbase	= MCF_MBAR + MCFUART_BASE1,
@@ -55,11 +49,11 @@
 	if (line == 0) {
 		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
 		writeb(irq, MCF_MBAR + MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1);
+		mcf_mapirq2imr(irq, MCFINTC_UART0);
 	} else if (line == 1) {
 		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
 		writeb(irq, MCF_MBAR + MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2);
+		mcf_mapirq2imr(irq, MCFINTC_UART1);
 	}
 }
 
@@ -74,35 +68,19 @@
 
 /***************************************************************************/
 
-void mcf_autovector(unsigned int vec)
+static void __init m5407_timers_init(void)
 {
-	volatile unsigned char  *mbar;
+	/* Timer1 is always used as system timer */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER1ICR);
+	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
 
-	if ((vec >= 25) && (vec <= 31)) {
-		mbar = (volatile unsigned char *) MCF_MBAR;
-		vec = 0x1 << (vec - 24);
-		*(mbar + MCFSIM_AVR) |= vec;
-		mcf_setimr(mcf_getimr() & ~vec);
-	}
-}
-
-/***************************************************************************/
-
-void mcf_settimericr(unsigned int timer, unsigned int level)
-{
-	volatile unsigned char *icrp;
-	unsigned int icr, imr;
-
-	if (timer <= 2) {
-		switch (timer) {
-		case 2:  icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
-		default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
-		}
-
-		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
-		*icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
-		mcf_setimr(mcf_getimr() & ~imr);
-	}
+#ifdef CONFIG_HIGHPROFILE
+	/* Timer2 is to be used as a high speed profile timer  */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER2ICR);
+	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
+#endif
 }
 
 /***************************************************************************/
@@ -120,23 +98,21 @@
 
 void __init config_BSP(char *commandp, int size)
 {
-	mcf_setimr(MCFSIM_IMR_MASKALL);
-
-#if defined(CONFIG_CLEOPATRA)
-	/* Different timer setup - to prevent device clash */
-	mcf_timervector = 30;
-	mcf_profilevector = 31;
-	mcf_timerlevel = 6;
-#endif
-
 	mach_reset = m5407_cpu_reset;
+	m5407_timers_init();
+	m5407_uarts_init();
+
+	/* Only support the external interrupts on their primary level */
+	mcf_mapirq2imr(25, MCFINTC_EINT1);
+	mcf_mapirq2imr(27, MCFINTC_EINT3);
+	mcf_mapirq2imr(29, MCFINTC_EINT5);
+	mcf_mapirq2imr(31, MCFINTC_EINT7);
 }
 
 /***************************************************************************/
 
 static int __init init_BSP(void)
 {
-	m5407_uarts_init();
 	platform_add_devices(m5407_devices, ARRAY_SIZE(m5407_devices));
 	return 0;
 }
diff --git a/arch/m68knommu/platform/5407/gpio.c b/arch/m68knommu/platform/5407/gpio.c
new file mode 100644
index 0000000..8da5880
--- /dev/null
+++ b/arch/m68knommu/platform/5407/gpio.c
@@ -0,0 +1,49 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PP",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 16,
+		},
+		.pddr				= MCFSIM_PADDR,
+		.podr				= MCFSIM_PADAT,
+		.ppdr				= MCFSIM_PADAT,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff --git a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c
index 72e56d5..b91ee85 100644
--- a/arch/m68knommu/platform/68328/ints.c
+++ b/arch/m68knommu/platform/68328/ints.c
@@ -73,34 +73,6 @@
 /* The number of spurious interrupts */
 volatile unsigned int num_spurious;
 
-/*
- * This function should be called during kernel startup to initialize
- * the machine vector table.
- */
-void __init init_vectors(void)
-{
-	int i;
-
-	/* set up the vectors */
-	for (i = 72; i < 256; ++i)
-		_ramvec[i] = (e_vector) bad_interrupt;
-
-	_ramvec[32] = system_call;
-
-	_ramvec[65] = (e_vector) inthandler1;
-	_ramvec[66] = (e_vector) inthandler2;
-	_ramvec[67] = (e_vector) inthandler3;
-	_ramvec[68] = (e_vector) inthandler4;
-	_ramvec[69] = (e_vector) inthandler5;
-	_ramvec[70] = (e_vector) inthandler6;
-	_ramvec[71] = (e_vector) inthandler7;
- 
-	IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */
-
-	/* turn off all interrupts */
-	IMR = ~0;
-}
-
 /* The 68k family did not have a good way to determine the source
  * of interrupts until later in the family.  The EC000 core does
  * not provide the vector number on the stack, we vector everything
@@ -163,18 +135,54 @@
 	}
 }
 
-void enable_vector(unsigned int irq)
+static void intc_irq_unmask(unsigned int irq)
 {
 	IMR &= ~(1<<irq);
 }
 
-void disable_vector(unsigned int irq)
+static void intc_irq_mask(unsigned int irq)
 {
 	IMR |= (1<<irq);
 }
 
-void ack_vector(unsigned int irq)
+static struct irq_chip intc_irq_chip = {
+	.name		= "M68K-INTC",
+	.mask		= intc_irq_mask,
+	.unmask		= intc_irq_unmask,
+};
+
+/*
+ * This function should be called during kernel startup to initialize
+ * the machine vector table.
+ */
+void __init init_IRQ(void)
 {
-	/* Nothing needed */
+	int i;
+
+	/* set up the vectors */
+	for (i = 72; i < 256; ++i)
+		_ramvec[i] = (e_vector) bad_interrupt;
+
+	_ramvec[32] = system_call;
+
+	_ramvec[65] = (e_vector) inthandler1;
+	_ramvec[66] = (e_vector) inthandler2;
+	_ramvec[67] = (e_vector) inthandler3;
+	_ramvec[68] = (e_vector) inthandler4;
+	_ramvec[69] = (e_vector) inthandler5;
+	_ramvec[70] = (e_vector) inthandler6;
+	_ramvec[71] = (e_vector) inthandler7;
+
+	IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */
+
+	/* turn off all interrupts */
+	IMR = ~0;
+
+	for (i = 0; (i < NR_IRQS); i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].chip = &intc_irq_chip;
+	}
 }
 
diff --git a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c
index c367811..1143f77 100644
--- a/arch/m68knommu/platform/68360/ints.c
+++ b/arch/m68knommu/platform/68360/ints.c
@@ -37,11 +37,33 @@
 /* The number of spurious interrupts */
 volatile unsigned int num_spurious;
 
+static void intc_irq_unmask(unsigned int irq)
+{
+	pquicc->intr_cimr |= (1 << irq);
+}
+
+static void intc_irq_mask(unsigned int irq)
+{
+	pquicc->intr_cimr &= ~(1 << irq);
+}
+
+static void intc_irq_ack(unsigned int irq)
+{
+	pquicc->intr_cisr = (1 << irq);
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "M68K-INTC",
+	.mask		= intc_irq_mask,
+	.unmask		= intc_irq_unmask,
+	.ack		= intc_irq_ack,
+};
+
 /*
  * This function should be called during kernel startup to initialize
  * the vector table.
  */
-void init_vectors(void)
+void init_IRQ(void)
 {
 	int i;
 	int vba = (CPM_VECTOR_BASE<<4);
@@ -109,20 +131,12 @@
 
 	/* turn off all CPM interrupts */
 	pquicc->intr_cimr = 0x00000000;
-}
 
-void enable_vector(unsigned int irq)
-{
-	pquicc->intr_cimr |= (1 << irq);
-}
-
-void disable_vector(unsigned int irq)
-{
-	pquicc->intr_cimr &= ~(1 << irq);
-}
-
-void ack_vector(unsigned int irq)
-{
-	pquicc->intr_cisr = (1 << irq);
+	for (i = 0; (i < NR_IRQS); i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].chip = &intc_irq_chip;
+	}
 }
 
diff --git a/arch/m68knommu/platform/coldfire/Makefile b/arch/m68knommu/platform/coldfire/Makefile
index 1bcb937..f72a0e5 100644
--- a/arch/m68knommu/platform/coldfire/Makefile
+++ b/arch/m68knommu/platform/coldfire/Makefile
@@ -15,16 +15,17 @@
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
 obj-$(CONFIG_COLDFIRE)	+= clk.o dma.o entry.o vectors.o
-obj-$(CONFIG_M5206)	+= timers.o
-obj-$(CONFIG_M5206e)	+= timers.o
-obj-$(CONFIG_M520x)	+= pit.o
-obj-$(CONFIG_M523x)	+= pit.o dma_timer.o
-obj-$(CONFIG_M5249)	+= timers.o
-obj-$(CONFIG_M527x)	+= pit.o
+obj-$(CONFIG_M5206)	+= timers.o intc.o
+obj-$(CONFIG_M5206e)	+= timers.o intc.o
+obj-$(CONFIG_M520x)	+= pit.o intc-simr.o
+obj-$(CONFIG_M523x)	+= pit.o dma_timer.o intc-2.o
+obj-$(CONFIG_M5249)	+= timers.o intc.o
+obj-$(CONFIG_M527x)	+= pit.o intc-2.o
 obj-$(CONFIG_M5272)	+= timers.o
-obj-$(CONFIG_M528x)	+= pit.o
-obj-$(CONFIG_M5307)	+= timers.o
-obj-$(CONFIG_M532x)	+= timers.o
-obj-$(CONFIG_M5407)	+= timers.o
+obj-$(CONFIG_M528x)	+= pit.o intc-2.o
+obj-$(CONFIG_M5307)	+= timers.o intc.o
+obj-$(CONFIG_M532x)	+= timers.o intc-simr.o
+obj-$(CONFIG_M5407)	+= timers.o intc.o
 
+obj-y			+= pinmux.o gpio.o
 extra-y := head.o
diff --git a/arch/m68knommu/platform/coldfire/gpio.c b/arch/m68knommu/platform/coldfire/gpio.c
new file mode 100644
index 0000000..ff004579
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/gpio.c
@@ -0,0 +1,127 @@
+/*
+ * Coldfire generic GPIO support.
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+
+#include <asm/gpio.h>
+#include <asm/pinmux.h>
+#include <asm/mcfgpio.h>
+
+#define MCF_CHIP(chip) container_of(chip, struct mcf_gpio_chip, gpio_chip)
+
+int mcf_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned long flags;
+	MCFGPIO_PORTTYPE dir;
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	local_irq_save(flags);
+	dir = mcfgpio_read(mcf_chip->pddr);
+	dir &= ~mcfgpio_bit(chip->base + offset);
+	mcfgpio_write(dir, mcf_chip->pddr);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+int mcf_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	return mcfgpio_read(mcf_chip->ppdr) & mcfgpio_bit(chip->base + offset);
+}
+
+int mcf_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	unsigned long flags;
+	MCFGPIO_PORTTYPE data;
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	local_irq_save(flags);
+	/* write the value to the output latch */
+	data = mcfgpio_read(mcf_chip->podr);
+	if (value)
+		data |= mcfgpio_bit(chip->base + offset);
+	else
+		data &= ~mcfgpio_bit(chip->base + offset);
+	mcfgpio_write(data, mcf_chip->podr);
+
+	/* now set the direction to output */
+	data = mcfgpio_read(mcf_chip->pddr);
+	data |= mcfgpio_bit(chip->base + offset);
+	mcfgpio_write(data, mcf_chip->pddr);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+void mcf_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	unsigned long flags;
+	MCFGPIO_PORTTYPE data;
+
+	local_irq_save(flags);
+	data = mcfgpio_read(mcf_chip->podr);
+	if (value)
+		data |= mcfgpio_bit(chip->base + offset);
+	else
+		data &= ~mcfgpio_bit(chip->base + offset);
+	mcfgpio_write(data, mcf_chip->podr);
+	local_irq_restore(flags);
+}
+
+void mcf_gpio_set_value_fast(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	if (value)
+		mcfgpio_write(mcfgpio_bit(chip->base + offset), mcf_chip->setr);
+	else
+		mcfgpio_write(~mcfgpio_bit(chip->base + offset), mcf_chip->clrr);
+}
+
+int mcf_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	return mcf_chip->gpio_to_pinmux ?
+		mcf_pinmux_request(mcf_chip->gpio_to_pinmux[offset], 0) : 0;
+}
+
+void mcf_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	mcf_gpio_direction_input(chip, offset);
+
+	if (mcf_chip->gpio_to_pinmux)
+		mcf_pinmux_release(mcf_chip->gpio_to_pinmux[offset], 0);
+}
+
+struct sysdev_class mcf_gpio_sysclass = {
+	.name	= "gpio",
+};
+
+static int __init mcf_gpio_sysinit(void)
+{
+	return sysdev_class_register(&mcf_gpio_sysclass);
+}
+
+core_initcall(mcf_gpio_sysinit);
diff --git a/arch/m68knommu/platform/coldfire/intc-2.c b/arch/m68knommu/platform/coldfire/intc-2.c
new file mode 100644
index 0000000..5598c8b
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/intc-2.c
@@ -0,0 +1,93 @@
+/*
+ * intc-1.c
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/traps.h>
+
+/*
+ *	Each vector needs a unique priority and level asscoiated with it.
+ *	We don't really care so much what they are, we don't rely on the
+ *	tranditional priority interrupt scheme of the m68k/ColdFire.
+ */
+static u8 intc_intpri = 0x36;
+
+static void intc_irq_mask(unsigned int irq)
+{
+	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
+		unsigned long imraddr;
+		u32 val, imrbit;
+
+		irq -= MCFINT_VECBASE;
+		imraddr = MCF_IPSBAR;
+		imraddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+		imraddr += (irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL;
+		imrbit = 0x1 << (irq & 0x1f);
+
+		val = __raw_readl(imraddr);
+		__raw_writel(val | imrbit, imraddr);
+	}
+}
+
+static void intc_irq_unmask(unsigned int irq)
+{
+	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
+		unsigned long intaddr, imraddr, icraddr;
+		u32 val, imrbit;
+
+		irq -= MCFINT_VECBASE;
+		intaddr = MCF_IPSBAR;
+		intaddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+		imraddr = intaddr + ((irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL);
+		icraddr = intaddr + MCFINTC_ICR0 + (irq & 0x3f);
+		imrbit = 0x1 << (irq & 0x1f);
+
+		/* Don't set the "maskall" bit! */
+		if ((irq & 0x20) == 0)
+			imrbit |= 0x1;
+
+		if (__raw_readb(icraddr) == 0)
+			__raw_writeb(intc_intpri--, icraddr);
+
+		val = __raw_readl(imraddr);
+		__raw_writel(val & ~imrbit, imraddr);
+	}
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "CF-INTC",
+	.mask		= intc_irq_mask,
+	.unmask		= intc_irq_unmask,
+};
+
+void __init init_IRQ(void)
+{
+	int irq;
+
+	init_vectors();
+
+	/* Mask all interrupt sources */
+	__raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
+	__raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_IMRL);
+
+	for (irq = 0; (irq < NR_IRQS); irq++) {
+		irq_desc[irq].status = IRQ_DISABLED;
+		irq_desc[irq].action = NULL;
+		irq_desc[irq].depth = 1;
+		irq_desc[irq].chip = &intc_irq_chip;
+	}
+}
+
diff --git a/arch/m68knommu/platform/coldfire/intc-simr.c b/arch/m68knommu/platform/coldfire/intc-simr.c
new file mode 100644
index 0000000..1b01e79
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/intc-simr.c
@@ -0,0 +1,78 @@
+/*
+ * intc-simr.c
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/traps.h>
+
+static void intc_irq_mask(unsigned int irq)
+{
+	if (irq >= MCFINT_VECBASE) {
+		if (irq < MCFINT_VECBASE + 64)
+			__raw_writeb(irq - MCFINT_VECBASE, MCFINTC0_SIMR);
+		else if ((irq < MCFINT_VECBASE + 128) && MCFINTC1_SIMR)
+			__raw_writeb(irq - MCFINT_VECBASE - 64, MCFINTC1_SIMR);
+	}
+}
+
+static void intc_irq_unmask(unsigned int irq)
+{
+	if (irq >= MCFINT_VECBASE) {
+		if (irq < MCFINT_VECBASE + 64)
+			__raw_writeb(irq - MCFINT_VECBASE, MCFINTC0_CIMR);
+		else if ((irq < MCFINT_VECBASE + 128) && MCFINTC1_CIMR)
+			__raw_writeb(irq - MCFINT_VECBASE - 64, MCFINTC1_CIMR);
+	}
+}
+
+static int intc_irq_set_type(unsigned int irq, unsigned int type)
+{
+	if (irq >= MCFINT_VECBASE) {
+		if (irq < MCFINT_VECBASE + 64)
+			__raw_writeb(5, MCFINTC0_ICR0 + irq - MCFINT_VECBASE);
+		else if ((irq < MCFINT_VECBASE) && MCFINTC1_ICR0)
+			__raw_writeb(5, MCFINTC1_ICR0 + irq - MCFINT_VECBASE - 64);
+	}
+	return 0;
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "CF-INTC",
+	.mask		= intc_irq_mask,
+	.unmask		= intc_irq_unmask,
+	.set_type	= intc_irq_set_type,
+};
+
+void __init init_IRQ(void)
+{
+	int irq;
+
+	init_vectors();
+
+	/* Mask all interrupt sources */
+	__raw_writeb(0xff, MCFINTC0_SIMR);
+	if (MCFINTC1_SIMR)
+		__raw_writeb(0xff, MCFINTC1_SIMR);
+
+	for (irq = 0; (irq < NR_IRQS); irq++) {
+		irq_desc[irq].status = IRQ_DISABLED;
+		irq_desc[irq].action = NULL;
+		irq_desc[irq].depth = 1;
+		irq_desc[irq].chip = &intc_irq_chip;
+		intc_irq_set_type(irq, 0);
+	}
+}
+
diff --git a/arch/m68knommu/platform/coldfire/intc.c b/arch/m68knommu/platform/coldfire/intc.c
new file mode 100644
index 0000000..a4560c8
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/intc.c
@@ -0,0 +1,153 @@
+/*
+ * intc.c  -- support for the old ColdFire interrupt controller
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/traps.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+/*
+ * The mapping of irq number to a mask register bit is not one-to-one.
+ * The irq numbers are either based on "level" of interrupt or fixed
+ * for an autovector-able interrupt. So we keep a local data structure
+ * that maps from irq to mask register. Not all interrupts will have
+ * an IMR bit.
+ */
+unsigned char mcf_irq2imr[NR_IRQS];
+
+/*
+ * Define the miniumun and maximum external interrupt numbers.
+ * This is also used as the "level" interrupt numbers.
+ */
+#define	EIRQ1	25
+#define	EIRQ7	31
+
+/*
+ * In the early version 2 core ColdFire parts the IMR register was 16 bits
+ * in size. Version 3 (and later version 2) core parts have a 32 bit
+ * sized IMR register. Provide some size independant methods to access the
+ * IMR register.
+ */
+#ifdef MCFSIM_IMR_IS_16BITS
+
+void mcf_setimr(int index)
+{
+	u16 imr;
+	imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
+	__raw_writew(imr | (0x1 << index), MCF_MBAR + MCFSIM_IMR);
+}
+
+void mcf_clrimr(int index)
+{
+	u16 imr;
+	imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
+	__raw_writew(imr & ~(0x1 << index), MCF_MBAR + MCFSIM_IMR);
+}
+
+void mcf_maskimr(unsigned int mask)
+{
+	u16 imr;
+	imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
+	imr |= mask;
+	__raw_writew(imr, MCF_MBAR + MCFSIM_IMR);
+}
+
+#else
+
+void mcf_setimr(int index)
+{
+	u32 imr;
+	imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
+	__raw_writel(imr | (0x1 << index), MCF_MBAR + MCFSIM_IMR);
+}
+
+void mcf_clrimr(int index)
+{
+	u32 imr;
+	imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
+	__raw_writel(imr & ~(0x1 << index), MCF_MBAR + MCFSIM_IMR);
+}
+
+void mcf_maskimr(unsigned int mask)
+{
+	u32 imr;
+	imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
+	imr |= mask;
+	__raw_writel(imr, MCF_MBAR + MCFSIM_IMR);
+}
+
+#endif
+
+/*
+ * Interrupts can be "vectored" on the ColdFire cores that support this old
+ * interrupt controller. That is, the device raising the interrupt can also
+ * supply the vector number to interrupt through. The AVR register of the
+ * interrupt controller enables or disables this for each external interrupt,
+ * so provide generic support for this. Setting this up is out-of-band for
+ * the interrupt system API's, and needs to be done by the driver that
+ * supports this device. Very few devices actually use this.
+ */
+void mcf_autovector(int irq)
+{
+#ifdef MCFSIM_AVR
+	if ((irq >= EIRQ1) && (irq <= EIRQ7)) {
+		u8 avec;
+		avec = __raw_readb(MCF_MBAR + MCFSIM_AVR);
+		avec |= (0x1 << (irq - EIRQ1 + 1));
+		__raw_writeb(avec, MCF_MBAR + MCFSIM_AVR);
+	}
+#endif
+}
+
+static void intc_irq_mask(unsigned int irq)
+{
+	if (mcf_irq2imr[irq])
+		mcf_setimr(mcf_irq2imr[irq]);
+}
+
+static void intc_irq_unmask(unsigned int irq)
+{
+	if (mcf_irq2imr[irq])
+		mcf_clrimr(mcf_irq2imr[irq]);
+}
+
+static int intc_irq_set_type(unsigned int irq, unsigned int type)
+{
+	return 0;
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "CF-INTC",
+	.mask		= intc_irq_mask,
+	.unmask		= intc_irq_unmask,
+	.set_type	= intc_irq_set_type,
+};
+
+void __init init_IRQ(void)
+{
+	int irq;
+
+	init_vectors();
+	mcf_maskimr(0xffffffff);
+
+	for (irq = 0; (irq < NR_IRQS); irq++) {
+		irq_desc[irq].status = IRQ_DISABLED;
+		irq_desc[irq].action = NULL;
+		irq_desc[irq].depth = 1;
+		irq_desc[irq].chip = &intc_irq_chip;
+		intc_irq_set_type(irq, 0);
+	}
+}
+
diff --git a/arch/m68knommu/platform/coldfire/pinmux.c b/arch/m68knommu/platform/coldfire/pinmux.c
new file mode 100644
index 0000000..8c62b82
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/pinmux.c
@@ -0,0 +1,28 @@
+/*
+ * Coldfire generic GPIO pinmux support.
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; version 2 of the License.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/pinmux.h>
+
+int mcf_pinmux_request(unsigned pinmux, unsigned func)
+{
+	return 0;
+}
+
+void mcf_pinmux_release(unsigned pinmux, unsigned func)
+{
+}
diff --git a/arch/m68knommu/platform/coldfire/pit.c b/arch/m68knommu/platform/coldfire/pit.c
index 61b9621..d8720ee 100644
--- a/arch/m68knommu/platform/coldfire/pit.c
+++ b/arch/m68knommu/platform/coldfire/pit.c
@@ -32,7 +32,6 @@
  */
 #define	FREQ	((MCF_CLK / 2) / 64)
 #define	TA(a)	(MCF_IPSBAR + MCFPIT_BASE1 + (a))
-#define	INTC0	(MCF_IPSBAR + MCFICM_INTC0)
 #define PIT_CYCLES_PER_JIFFY (FREQ / HZ)
 
 static u32 pit_cnt;
@@ -154,8 +153,6 @@
 
 void hw_timer_init(void)
 {
-	u32 imr;
-
 	cf_pit_clockevent.cpumask = cpumask_of(smp_processor_id());
 	cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32);
 	cf_pit_clockevent.max_delta_ns =
@@ -166,11 +163,6 @@
 
 	setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq);
 
-	__raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1);
-	imr = __raw_readl(INTC0 + MCFPIT_IMR);
-	imr &= ~MCFPIT_IMR_IBIT;
-	__raw_writel(imr, INTC0 + MCFPIT_IMR);
-
 	pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift);
 	clocksource_register(&pit_clk);
 }
diff --git a/arch/m68knommu/platform/coldfire/timers.c b/arch/m68knommu/platform/coldfire/timers.c
index 1ba8a37..2304d73 100644
--- a/arch/m68knommu/platform/coldfire/timers.c
+++ b/arch/m68knommu/platform/coldfire/timers.c
@@ -31,19 +31,9 @@
 #define	TA(a)	(MCF_MBAR + MCFTIMER_BASE1 + (a))
 
 /*
- *	Default the timer and vector to use for ColdFire. Some ColdFire
- *	CPU's and some boards may want different. Their sub-architecture
- *	startup code (in config.c) can change these if they want.
- */
-unsigned int	mcf_timervector = 29;
-unsigned int	mcf_profilevector = 31;
-unsigned int	mcf_timerlevel = 5;
-
-/*
  *	These provide the underlying interrupt vector support.
  *	Unfortunately it is a little different on each ColdFire.
  */
-extern void mcf_settimericr(int timer, int level);
 void coldfire_profile_init(void);
 
 #if defined(CONFIG_M532x)
@@ -107,8 +97,6 @@
 
 void hw_timer_init(void)
 {
-	setup_irq(mcf_timervector, &mcftmr_timer_irq);
-
 	__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
 	mcftmr_cycles_per_jiffy = FREQ / HZ;
 	/*
@@ -124,7 +112,7 @@
 	mcftmr_clk.mult = clocksource_hz2mult(FREQ, mcftmr_clk.shift);
 	clocksource_register(&mcftmr_clk);
 
-	mcf_settimericr(1, mcf_timerlevel);
+	setup_irq(MCF_IRQ_TIMER, &mcftmr_timer_irq);
 
 #ifdef CONFIG_HIGHPROFILE
 	coldfire_profile_init();
@@ -171,8 +159,6 @@
 	printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n",
 	       PROFILEHZ);
 
-	setup_irq(mcf_profilevector, &coldfire_profile_irq);
-
 	/* Set up TIMER 2 as high speed profile clock */
 	__raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR));
 
@@ -180,7 +166,7 @@
 	__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
 		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR));
 
-	mcf_settimericr(2, 7);
+	setup_irq(MCF_IRQ_PROFILER, &coldfire_profile_irq);
 }
 
 /***************************************************************************/
diff --git a/arch/m68knommu/platform/coldfire/vectors.c b/arch/m68knommu/platform/coldfire/vectors.c
index bdca029..a21d3f8 100644
--- a/arch/m68knommu/platform/coldfire/vectors.c
+++ b/arch/m68knommu/platform/coldfire/vectors.c
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *	linux/arch/m68knommu/platform/5307/vectors.c
+ *	linux/arch/m68knommu/platform/coldfire/vectors.c
  *
  *	Copyright (C) 1999-2007, Greg Ungerer <gerg@snapgear.com>
  */
@@ -15,7 +15,6 @@
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
-#include <asm/mcfdma.h>
 #include <asm/mcfwdebug.h>
 
 /***************************************************************************/
@@ -79,20 +78,3 @@
 }
 
 /***************************************************************************/
-
-void enable_vector(unsigned int irq)
-{
-	/* Currently no action on ColdFire */
-}
-
-void disable_vector(unsigned int irq)
-{
-	/* Currently no action on ColdFire */
-}
-
-void ack_vector(unsigned int irq)
-{
-	/* Currently no action on ColdFire */
-}
-
-/***************************************************************************/
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 2e25b7a..461abb1 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -28,6 +28,17 @@
 	tristate
 	default n
 
+config HWMON_DEBUG_CHIP
+	bool "Hardware Monitoring Chip debugging messages"
+	default n
+	help
+	  Say Y here if you want the I2C chip drivers to produce a bunch of
+	  debug messages to the system log.  Select this if you are having
+	  a problem with I2C support and want to see more of what is going
+	  on.
+
+comment "Native drivers"
+
 config SENSORS_ABITUGURU
 	tristate "Abit uGuru (rev 1 & 2)"
 	depends on X86 && EXPERIMENTAL
@@ -248,18 +259,6 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called asb100.
 
-config SENSORS_ATK0110
-	tristate "ASUS ATK0110 ACPI hwmon"
-	depends on X86 && ACPI && EXPERIMENTAL
-	help
-	  If you say yes here you get support for the ACPI hardware
-	  monitoring interface found in many ASUS motherboards. This
-	  driver will provide readings of fans, voltages and temperatures
-	  through the system firmware.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called asus_atk0110.
-
 config SENSORS_ATXP1
 	tristate "Attansic ATXP1 VID controller"
 	depends on I2C && EXPERIMENTAL
@@ -814,6 +813,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called tmp401.
 
+config SENSORS_TMP421
+	tristate "Texas Instruments TMP421 and compatible"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for Texas Instruments TMP421,
+	  TMP422 and TMP423 temperature sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tmp421.
+
 config SENSORS_VIA686A
 	tristate "VIA686A"
 	depends on PCI
@@ -964,34 +973,6 @@
 	  Say Y here if you have an applicable laptop and want to experience
 	  the awesome power of hdaps.
 
-config SENSORS_LIS3LV02D
-	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer"
-	depends on ACPI && INPUT
-	select INPUT_POLLDEV
-	select NEW_LEDS
-	select LEDS_CLASS
-	default n
-	help
-	  This driver provides support for the LIS3LV02Dx accelerometer. In
-	  particular, it can be found in a number of HP laptops, which have the
-	  "Mobile Data Protection System 3D" or "3D DriveGuard" feature. On such
-	  systems the driver should load automatically (via ACPI). The
-	  accelerometer might also be found in other systems, connected via SPI
-	  or I2C.  The accelerometer data is readable via
-	  /sys/devices/platform/lis3lv02d.
-
-	  This driver also provides an absolute input class device, allowing
-	  the laptop to act as a pinball machine-esque joystick. On HP laptops,
-	  if the led infrastructure is activated, support for a led indicating
-	  disk protection will be provided as hp:red:hddprotection.
-
-	  This driver can also be built as modules.  If so, the core module
-	  will be called lis3lv02d and a specific module for HP laptops will be
-	  called hp_accel.
-
-	  Say Y here if you have an applicable laptop and want to experience
-	  the awesome power of lis3lv02d.
-
 config SENSORS_LIS3_SPI
 	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
 	depends on !ACPI && SPI_MASTER && INPUT
@@ -1034,13 +1015,50 @@
 	  Say Y here if you have an applicable laptop and want to experience
 	  the awesome power of applesmc.
 
-config HWMON_DEBUG_CHIP
-	bool "Hardware Monitoring Chip debugging messages"
+if ACPI
+
+comment "ACPI drivers"
+
+config SENSORS_ATK0110
+	tristate "ASUS ATK0110"
+	depends on X86 && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the ACPI hardware
+	  monitoring interface found in many ASUS motherboards. This
+	  driver will provide readings of fans, voltages and temperatures
+	  through the system firmware.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called asus_atk0110.
+
+config SENSORS_LIS3LV02D
+	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer"
+	depends on INPUT
+	select INPUT_POLLDEV
+	select NEW_LEDS
+	select LEDS_CLASS
 	default n
 	help
-	  Say Y here if you want the I2C chip drivers to produce a bunch of
-	  debug messages to the system log.  Select this if you are having
-	  a problem with I2C support and want to see more of what is going
-	  on.
+	  This driver provides support for the LIS3LV02Dx accelerometer. In
+	  particular, it can be found in a number of HP laptops, which have the
+	  "Mobile Data Protection System 3D" or "3D DriveGuard" feature. On such
+	  systems the driver should load automatically (via ACPI). The
+	  accelerometer might also be found in other systems, connected via SPI
+	  or I2C.  The accelerometer data is readable via
+	  /sys/devices/platform/lis3lv02d.
+
+	  This driver also provides an absolute input class device, allowing
+	  the laptop to act as a pinball machine-esque joystick. On HP laptops,
+	  if the led infrastructure is activated, support for a led indicating
+	  disk protection will be provided as hp:red:hddprotection.
+
+	  This driver can also be built as modules.  If so, the core module
+	  will be called lis3lv02d and a specific module for HP laptops will be
+	  called hp_accel.
+
+	  Say Y here if you have an applicable laptop and want to experience
+	  the awesome power of lis3lv02d.
+
+endif # ACPI
 
 endif # HWMON
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 7f239a2..2e54788 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -5,6 +5,10 @@
 obj-$(CONFIG_HWMON)		+= hwmon.o
 obj-$(CONFIG_HWMON_VID)		+= hwmon-vid.o
 
+# APCI drivers
+obj-$(CONFIG_SENSORS_ATK0110)	+= asus_atk0110.o
+
+# Native drivers
 # asb100, then w83781d go first, as they can override other drivers' addresses.
 obj-$(CONFIG_SENSORS_ASB100)	+= asb100.o
 obj-$(CONFIG_SENSORS_W83627HF)	+= w83627hf.o
@@ -29,10 +33,8 @@
 obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
 obj-$(CONFIG_SENSORS_ADT7473)	+= adt7473.o
 obj-$(CONFIG_SENSORS_ADT7475)	+= adt7475.o
-
 obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
 obj-$(CONFIG_SENSORS_AMS)	+= ams/
-obj-$(CONFIG_SENSORS_ATK0110)	+= asus_atk0110.o
 obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_CORETEMP)	+= coretemp.o
 obj-$(CONFIG_SENSORS_DME1737)	+= dme1737.o
@@ -84,6 +86,7 @@
 obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
 obj-$(CONFIG_SENSORS_THMC50)	+= thmc50.o
 obj-$(CONFIG_SENSORS_TMP401)	+= tmp401.o
+obj-$(CONFIG_SENSORS_TMP421)	+= tmp421.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_VT1211)	+= vt1211.o
 obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 4dbdb81..03694cc 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -32,7 +32,7 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/dmi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 /* Banks */
 #define ABIT_UGURU_ALARM_BANK			0x20 /* 1x 3 bytes */
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index 7d3f15d..3cf28af 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -34,7 +34,7 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/dmi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 /* uGuru3 bank addresses */
 #define ABIT_UGURU3_SETTINGS_BANK		0x01
@@ -117,9 +117,12 @@
 	int offset;
 };
 
+/* Avoid use of flexible array members */
+#define ABIT_UGURU3_MAX_DMI_NAMES 2
+
 struct abituguru3_motherboard_info {
 	u16 id;
-	const char *dmi_name;
+	const char *dmi_name[ABIT_UGURU3_MAX_DMI_NAMES + 1];
 	/* + 1 -> end of sensors indicated by a sensor with name == NULL */
 	struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1];
 };
@@ -164,7 +167,7 @@
 
 /* Constants */
 static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
-	{ 0x000C, NULL /* Unknown, need DMI string */, {
+	{ 0x000C, { NULL } /* Unknown, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -186,7 +189,7 @@
 		{ "AUX1 Fan",		35, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x000D, NULL /* Abit AW8, need DMI string */, {
+	{ 0x000D, { NULL } /* Abit AW8, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -215,7 +218,7 @@
 		{ "AUX5 Fan",		39, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x000E, NULL /* AL-8, need DMI string */, {
+	{ 0x000E, { NULL } /* AL-8, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -236,7 +239,8 @@
 		{ "SYS Fan",		34, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x000F, NULL /* Unknown, need DMI string */, {
+	{ 0x000F, { NULL } /* Unknown, need DMI string */, {
+
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -257,7 +261,7 @@
 		{ "SYS Fan",		34, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0010, NULL /* Abit NI8 SLI GR, need DMI string */, {
+	{ 0x0010, { NULL } /* Abit NI8 SLI GR, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -279,7 +283,7 @@
 		{ "OTES1 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0011, "AT8 32X", {
+	{ 0x0011, { "AT8 32X", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 20, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -306,7 +310,7 @@
 		{ "AUX3 Fan",		37, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0012, NULL /* Abit AN8 32X, need DMI string */, {
+	{ 0x0012, { NULL } /* Abit AN8 32X, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 20, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -328,7 +332,7 @@
 		{ "AUX1 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0013, NULL /* Abit AW8D, need DMI string */, {
+	{ 0x0013, { NULL } /* Abit AW8D, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -357,7 +361,7 @@
 		{ "AUX5 Fan",		39, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0014, "AB9", /* + AB9 Pro */ {
+	{ 0x0014, { "AB9", "AB9 Pro", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -378,7 +382,7 @@
 		{ "SYS Fan",		34, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0015, NULL /* Unknown, need DMI string */, {
+	{ 0x0015, { NULL } /* Unknown, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 20, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -402,7 +406,7 @@
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0016, "AW9D-MAX", {
+	{ 0x0016, { "AW9D-MAX", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -430,7 +434,7 @@
 		{ "OTES1 Fan",		38, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0017, NULL /* Unknown, need DMI string */, {
+	{ 0x0017, { NULL } /* Unknown, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -455,7 +459,7 @@
 		{ "AUX3 FAN",		37, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0018, "AB9 QuadGT", {
+	{ 0x0018, { "AB9 QuadGT", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -482,7 +486,7 @@
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0019, "IN9 32X MAX", {
+	{ 0x0019, { "IN9 32X MAX", NULL }, {
 		{ "CPU Core",		 7, 0, 10, 1, 0 },
 		{ "DDR2",		13, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		14, 0, 10, 1, 0 },
@@ -509,7 +513,7 @@
 		{ "AUX3 FAN",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x001A, "IP35 Pro", {
+	{ 0x001A, { "IP35 Pro", "IP35 Pro XE", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -537,7 +541,7 @@
 		{ "AUX4 Fan",		37, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x001B, NULL /* Unknown, need DMI string */, {
+	{ 0x001B, { NULL } /* Unknown, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR3",		 1, 0, 20, 1, 0 },
 		{ "DDR3 VTT",		 2, 0, 10, 1, 0 },
@@ -564,7 +568,7 @@
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x001C, "IX38 QuadGT", {
+	{ 0x001C, { "IX38 QuadGT", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -591,7 +595,7 @@
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
+	{ 0x0000, { NULL }, { { NULL, 0, 0, 0, 0, 0 } } }
 };
 
 
@@ -946,15 +950,6 @@
 	printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard "
 		"ID: %04X\n", (unsigned int)id);
 
-#ifdef CONFIG_DMI
-	if (!abituguru3_motherboards[i].dmi_name) {
-		printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was "
-			"not detected using DMI. Please send the output of "
-			"\"dmidecode\" to the abituguru3 maintainer "
-			"(see MAINTAINERS)\n");
-	}
-#endif
-
 	/* Fill the sysfs attr array */
 	sysfs_attr_i = 0;
 	sysfs_filename = data->sysfs_names;
@@ -1131,6 +1126,7 @@
 {
 	const char *board_vendor, *board_name;
 	int i, err = (force) ? 1 : -ENODEV;
+	const char *const *dmi_name;
 	size_t sublen;
 
 	board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
@@ -1151,17 +1147,17 @@
 		sublen--;
 
 	for (i = 0; abituguru3_motherboards[i].id; i++) {
-		const char *dmi_name = abituguru3_motherboards[i].dmi_name;
-		if (!dmi_name || strlen(dmi_name) != sublen)
-			continue;
-		if (!strncasecmp(board_name, dmi_name, sublen))
-			break;
+		dmi_name = abituguru3_motherboards[i].dmi_name;
+		for ( ; *dmi_name; dmi_name++) {
+			if (strlen(*dmi_name) != sublen)
+				continue;
+			if (!strncasecmp(board_name, *dmi_name, sublen))
+				return 0;
+		}
 	}
 
-	if (!abituguru3_motherboards[i].id)
-		return 1;
-
-	return 0;
+	/* No match found */
+	return 1;
 }
 
 #else /* !CONFIG_DMI */
@@ -1221,6 +1217,13 @@
 		err = abituguru3_detect();
 		if (err)
 			return err;
+
+#ifdef CONFIG_DMI
+		printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was "
+			"not detected using DMI. Please send the output of "
+			"\"dmidecode\" to the abituguru3 maintainer "
+			"(see MAINTAINERS)\n");
+#endif
 	}
 
 	err = platform_driver_register(&abituguru3_driver);
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 678e34b..753b348 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -35,7 +35,7 @@
 #include <linux/dmi.h>
 #include <linux/mutex.h>
 #include <linux/hwmon-sysfs.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/leds.h>
 #include <linux/hwmon.h>
 #include <linux/workqueue.h>
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index 3df202a..9814d51 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -35,7 +35,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 /* ISA device, if found */
 static struct platform_device *pdev;
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 89987657..525a00b 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -40,7 +40,7 @@
 #include <linux/sysfs.h>
 #include <linux/ioport.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index d3612a1..be2d131 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -35,8 +35,7 @@
 #include <linux/timer.h>
 #include <linux/dmi.h>
 #include <linux/jiffies.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
 
 #define HDAPS_LOW_PORT		0x1600	/* first port used by hdaps */
 #define HDAPS_NR_PORTS		0x30	/* number of ports: 0x1600 - 0x162f */
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index bfc2961..bf0862a8 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -179,8 +179,14 @@
 static struct vrm_model vrm_models[] = {
 	{X86_VENDOR_AMD, 0x6, ANY, ANY, 90},		/* Athlon Duron etc */
 	{X86_VENDOR_AMD, 0xF, 0x3F, ANY, 24},		/* Athlon 64, Opteron */
-	{X86_VENDOR_AMD, 0xF, ANY, ANY, 25},		/* NPT family 0Fh */
+	/* In theory, all NPT family 0Fh processors have 6 VID pins and should
+	   thus use vrm 25, however in practice not all mainboards route the
+	   6th VID pin because it is never needed. So we use the 5 VID pin
+	   variant (vrm 24) for the models which exist today. */
+	{X86_VENDOR_AMD, 0xF, 0x7F, ANY, 24},		/* NPT family 0Fh */
+	{X86_VENDOR_AMD, 0xF, ANY, ANY, 25},		/* future fam. 0Fh */
 	{X86_VENDOR_AMD, 0x10, ANY, ANY, 25},		/* NPT family 10h */
+
 	{X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13},		/* Pentium M (130 nm) */
 	{X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85},		/* Tualatin */
 	{X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13},		/* Pentium M (90 nm) */
@@ -191,12 +197,14 @@
 	{X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90},		/* P4 Willamette */
 	{X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90},		/* P4 Northwood */
 	{X86_VENDOR_INTEL, 0xF, ANY, ANY, 100},		/* Prescott and above assume VRD 10 */
+
 	{X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85},	/* Eden ESP/Ezra */
 	{X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85},	/* Ezra T */
 	{X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85},	/* Nemiah */
 	{X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17},	/* C3-M, Eden-N */
 	{X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0},		/* No information */
 	{X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13},	/* C7, Esther */
+
 	{X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0}		/* stop here */
 };
 
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 9157247..ffeb2a1 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -50,7 +50,7 @@
 #include <linux/string.h>
 #include <linux/dmi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 #define DRVNAME "it87"
 
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index a1787fd..f7e7016 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -31,7 +31,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 /* ISA device, if found */
 static struct platform_device *pdev;
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index b251d86..6c53d98 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -75,6 +75,8 @@
 #define	LM85_VERSTEP_GENERIC2		0x70
 #define	LM85_VERSTEP_LM85C		0x60
 #define	LM85_VERSTEP_LM85B		0x62
+#define	LM85_VERSTEP_LM96000_1		0x68
+#define	LM85_VERSTEP_LM96000_2		0x69
 #define	LM85_VERSTEP_ADM1027		0x60
 #define	LM85_VERSTEP_ADT7463		0x62
 #define	LM85_VERSTEP_ADT7463C		0x6A
@@ -1133,6 +1135,26 @@
 		dev_warn(&client->dev, "Device is not ready\n");
 }
 
+static int lm85_is_fake(struct i2c_client *client)
+{
+	/*
+	 * Differenciate between real LM96000 and Winbond WPCD377I. The latter
+	 * emulate the former except that it has no hardware monitoring function
+	 * so the readings are always 0.
+	 */
+	int i;
+	u8 in_temp, fan;
+
+	for (i = 0; i < 8; i++) {
+		in_temp = i2c_smbus_read_byte_data(client, 0x20 + i);
+		fan = i2c_smbus_read_byte_data(client, 0x28 + i);
+		if (in_temp != 0x00 || fan != 0xff)
+			return 0;
+	}
+
+	return 1;
+}
+
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int lm85_detect(struct i2c_client *client, int kind,
 		       struct i2c_board_info *info)
@@ -1173,6 +1195,16 @@
 			case LM85_VERSTEP_LM85B:
 				kind = lm85b;
 				break;
+			case LM85_VERSTEP_LM96000_1:
+			case LM85_VERSTEP_LM96000_2:
+				/* Check for Winbond WPCD377I */
+				if (lm85_is_fake(client)) {
+					dev_dbg(&adapter->dev,
+						"Found Winbond WPCD377I, "
+						"ignoring\n");
+					return -ENODEV;
+				}
+				break;
 			}
 		} else if (company == LM85_COMPANY_ANALOG_DEV) {
 			switch (verstep) {
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index fb052fe..4a64b85 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -44,7 +44,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 static u8 devid;
 static struct platform_device *pdev;
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index 3a8a0f7..3170b26 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -33,7 +33,7 @@
 #include <linux/sysfs.h>
 #include <linux/ioport.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -435,7 +435,7 @@
 	/* This will need to be revisited when we add support for
 	   temperature and voltage monitoring. */
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) {
+	if (!request_region(res->start, resource_size(res), DRVNAME)) {
 		err = -EBUSY;
 		dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
 			(unsigned long)res->start, (unsigned long)res->end);
@@ -475,7 +475,7 @@
 		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
 	}
 exit_release_region:
-	release_region(res->start, res->end - res->start + 1);
+	release_region(res->start, resource_size(res));
 exit_kfree:
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
@@ -500,7 +500,7 @@
 	kfree(data);
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	release_region(res->start, res->end - res->start + 1);
+	release_region(res->start, resource_size(res));
 
 	return 0;
 }
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index aa2e831..12f2e70 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -63,7 +63,7 @@
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 /* If force_addr is set to anything different from 0, we forcibly enable
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 6f6d52b..f46d936 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -37,7 +37,7 @@
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index ba75bfc..8ad50fd 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -38,7 +38,7 @@
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
new file mode 100644
index 0000000..2092434
--- /dev/null
+++ b/drivers/hwmon/tmp421.c
@@ -0,0 +1,347 @@
+/* tmp421.c
+ *
+ * Copyright (C) 2009 Andre Prendel <andre.prendel@gmx.de>
+ * Preliminary support by:
+ * Melvin Rook, Raymond Ng
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Driver for the Texas Instruments TMP421 SMBus temperature sensor IC.
+ * Supported models: TMP421, TMP422, TMP423
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f,
+				       I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_3(tmp421, tmp422, tmp423);
+
+/* The TMP421 registers */
+#define TMP421_CONFIG_REG_1			0x09
+#define TMP421_CONVERSION_RATE_REG		0x0B
+#define TMP421_MANUFACTURER_ID_REG		0xFE
+#define TMP421_DEVICE_ID_REG			0xFF
+
+static const u8 TMP421_TEMP_MSB[4]		= { 0x00, 0x01, 0x02, 0x03 };
+static const u8 TMP421_TEMP_LSB[4]		= { 0x10, 0x11, 0x12, 0x13 };
+
+/* Flags */
+#define TMP421_CONFIG_SHUTDOWN			0x40
+#define TMP421_CONFIG_RANGE			0x04
+
+/* Manufacturer / Device ID's */
+#define TMP421_MANUFACTURER_ID			0x55
+#define TMP421_DEVICE_ID			0x21
+#define TMP422_DEVICE_ID			0x22
+#define TMP423_DEVICE_ID			0x23
+
+static const struct i2c_device_id tmp421_id[] = {
+	{ "tmp421", tmp421 },
+	{ "tmp422", tmp422 },
+	{ "tmp423", tmp423 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tmp421_id);
+
+struct tmp421_data {
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	char valid;
+	unsigned long last_updated;
+	int kind;
+	u8 config;
+	s16 temp[4];
+};
+
+static int temp_from_s16(s16 reg)
+{
+	int temp = reg;
+
+	return (temp * 1000 + 128) / 256;
+}
+
+static int temp_from_u16(u16 reg)
+{
+	int temp = reg;
+
+	/* Add offset for extended temperature range. */
+	temp -= 64 * 256;
+
+	return (temp * 1000 + 128) / 256;
+}
+
+static struct tmp421_data *tmp421_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tmp421_data *data = i2c_get_clientdata(client);
+	int i;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
+		data->config = i2c_smbus_read_byte_data(client,
+			TMP421_CONFIG_REG_1);
+
+		for (i = 0; i <= data->kind; i++) {
+			data->temp[i] = i2c_smbus_read_byte_data(client,
+				TMP421_TEMP_MSB[i]) << 8;
+			data->temp[i] |= i2c_smbus_read_byte_data(client,
+				TMP421_TEMP_LSB[i]);
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+static ssize_t show_temp_value(struct device *dev,
+			       struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp421_data *data = tmp421_update_device(dev);
+	int temp;
+
+	mutex_lock(&data->update_lock);
+	if (data->config & TMP421_CONFIG_RANGE)
+		temp = temp_from_u16(data->temp[index]);
+	else
+		temp = temp_from_s16(data->temp[index]);
+	mutex_unlock(&data->update_lock);
+
+	return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t show_fault(struct device *dev,
+			  struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp421_data *data = tmp421_update_device(dev);
+
+	/*
+	 * The OPEN bit signals a fault. This is bit 0 of the temperature
+	 * register (low byte).
+	 */
+	if (data->temp[index] & 0x01)
+		return sprintf(buf, "1\n");
+	else
+		return sprintf(buf, "0\n");
+}
+
+static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
+				int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct tmp421_data *data = dev_get_drvdata(dev);
+	struct device_attribute *devattr;
+	unsigned int index;
+
+	devattr = container_of(a, struct device_attribute, attr);
+	index = to_sensor_dev_attr(devattr)->index;
+
+	if (data->kind > index)
+		return a->mode;
+
+	return 0;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3);
+
+static struct attribute *tmp421_attr[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_fault.dev_attr.attr,
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_fault.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group tmp421_group = {
+	.attrs = tmp421_attr,
+	.is_visible = tmp421_is_visible,
+};
+
+static int tmp421_init_client(struct i2c_client *client)
+{
+	int config, config_orig;
+
+	/* Set the conversion rate to 2 Hz */
+	i2c_smbus_write_byte_data(client, TMP421_CONVERSION_RATE_REG, 0x05);
+
+	/* Start conversions (disable shutdown if necessary) */
+	config = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1);
+	if (config < 0) {
+		dev_err(&client->dev, "Could not read configuration"
+			 " register (%d)\n", config);
+		return -ENODEV;
+	}
+
+	config_orig = config;
+	config &= ~TMP421_CONFIG_SHUTDOWN;
+
+	if (config != config_orig) {
+		dev_info(&client->dev, "Enable monitoring chip\n");
+		i2c_smbus_write_byte_data(client, TMP421_CONFIG_REG_1, config);
+	}
+
+	return 0;
+}
+
+static int tmp421_detect(struct i2c_client *client, int kind,
+			 struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	const char *names[] = { "TMP421", "TMP422", "TMP423" };
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	if (kind <= 0) {
+		u8 reg;
+
+		reg = i2c_smbus_read_byte_data(client,
+					       TMP421_MANUFACTURER_ID_REG);
+		if (reg != TMP421_MANUFACTURER_ID)
+			return -ENODEV;
+
+		reg = i2c_smbus_read_byte_data(client,
+					       TMP421_DEVICE_ID_REG);
+		switch (reg) {
+		case TMP421_DEVICE_ID:
+			kind = tmp421;
+			break;
+		case TMP422_DEVICE_ID:
+			kind = tmp422;
+			break;
+		case TMP423_DEVICE_ID:
+			kind = tmp423;
+			break;
+		default:
+			return -ENODEV;
+		}
+	}
+	strlcpy(info->type, tmp421_id[kind - 1].name, I2C_NAME_SIZE);
+	dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n",
+		 names[kind - 1], client->addr);
+
+	return 0;
+}
+
+static int tmp421_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct tmp421_data *data;
+	int err;
+
+	data = kzalloc(sizeof(struct tmp421_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+	data->kind = id->driver_data;
+
+	err = tmp421_init_client(client);
+	if (err)
+		goto exit_free;
+
+	err = sysfs_create_group(&client->dev.kobj, &tmp421_group);
+	if (err)
+		goto exit_free;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		data->hwmon_dev = NULL;
+		goto exit_remove;
+	}
+	return 0;
+
+exit_remove:
+	sysfs_remove_group(&client->dev.kobj, &tmp421_group);
+
+exit_free:
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+
+	return err;
+}
+
+static int tmp421_remove(struct i2c_client *client)
+{
+	struct tmp421_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &tmp421_group);
+
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+
+	return 0;
+}
+
+static struct i2c_driver tmp421_driver = {
+	.class = I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "tmp421",
+	},
+	.probe = tmp421_probe,
+	.remove = tmp421_remove,
+	.id_table = tmp421_id,
+	.detect = tmp421_detect,
+	.address_data = &addr_data,
+};
+
+static int __init tmp421_init(void)
+{
+	return i2c_add_driver(&tmp421_driver);
+}
+
+static void __exit tmp421_exit(void)
+{
+	i2c_del_driver(&tmp421_driver);
+}
+
+MODULE_AUTHOR("Andre Prendel <andre.prendel@gmx.de>");
+MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor"
+		   " driver");
+MODULE_LICENSE("GPL");
+
+module_init(tmp421_init);
+module_exit(tmp421_exit);
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index a022aed..39e82a4 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -42,7 +42,7 @@
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 /* If force_addr is set to anything different from 0, we forcibly enable
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index 73f77a9..ae33bbb 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -33,7 +33,7 @@
 #include <linux/mutex.h>
 #include <linux/ioport.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 static int uch_config = -1;
 module_param(uch_config, int, 0);
@@ -1136,7 +1136,7 @@
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) {
+	if (!request_region(res->start, resource_size(res), DRVNAME)) {
 		err = -EBUSY;
 		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
 			(unsigned long)res->start, (unsigned long)res->end);
@@ -1209,7 +1209,7 @@
 	dev_err(dev, "Sysfs interface creation failed (%d)\n", err);
 EXIT_DEV_REMOVE_SILENT:
 	vt1211_remove_sysfs(pdev);
-	release_region(res->start, res->end - res->start + 1);
+	release_region(res->start, resource_size(res));
 EXIT_KFREE:
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
@@ -1228,7 +1228,7 @@
 	kfree(data);
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	release_region(res->start, res->end - res->start + 1);
+	release_region(res->start, resource_size(res));
 
 	return 0;
 }
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 9982b45..470a122 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -36,7 +36,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 static int force_addr;
 module_param(force_addr, int, 0);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 0e97469..bb5e787 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -51,7 +51,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include "lm75.h"
 
 enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg };
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 389150b..2be28ac 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -51,7 +51,7 @@
 #include <linux/mutex.h>
 #include <linux/ioport.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include "lm75.h"
 
 static struct platform_device *pdev;
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 0bdab95..d27ed1b 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -48,7 +48,7 @@
 #ifdef CONFIG_ISA
 #include <linux/platform_device.h>
 #include <linux/ioport.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #endif
 
 #include "lm75.h"
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index b472018..2923438 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1154,19 +1154,9 @@
 		printk("FEC: Could not allocate fec(MII) IRQ(66)!\n");
 }
 
-static void __inline__ fec_disable_phy_intr(void)
+static void __inline__ fec_disable_phy_intr(struct net_device *dev)
 {
-	volatile unsigned long *icrp;
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	*icrp = 0x08000000;
-}
-
-static void __inline__ fec_phy_ack_intr(void)
-{
-	volatile unsigned long *icrp;
-	/* Acknowledge the interrupt */
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	*icrp = 0x0d000000;
+	free_irq(66, dev);
 }
 #endif
 
@@ -1398,7 +1388,7 @@
 		writel(0, fep->hwp + FEC_MII_SPEED);
 		fep->phy_speed = 0;
 #ifdef HAVE_mii_link_interrupt
-		fec_disable_phy_intr();
+		fec_disable_phy_intr(dev);
 #endif
 	}
 }
@@ -1411,8 +1401,6 @@
 	struct	net_device *dev = dev_id;
 	struct fec_enet_private *fep = netdev_priv(dev);
 
-	fec_phy_ack_intr();
-
 	mii_do_cmd(dev, fep->phy->ack_int);
 	mii_do_cmd(dev, phy_cmd_relink);  /* restart and display status */
 
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c
index 9052bcb..e7eeb63 100644
--- a/drivers/uwb/hwa-rc.c
+++ b/drivers/uwb/hwa-rc.c
@@ -887,8 +887,7 @@
 	struct hwarc *hwarc = usb_get_intfdata(iface);
 	struct uwb_rc *uwb_rc = hwarc->uwb_rc;
 
-	uwb_rc_post_reset(uwb_rc);
-	return 0;
+	return uwb_rc_post_reset(uwb_rc);
 }
 
 /** USB device ID's that we handle */
diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c
index 9cf21e6..9611ef3 100644
--- a/drivers/uwb/lc-rc.c
+++ b/drivers/uwb/lc-rc.c
@@ -288,8 +288,8 @@
 error_dev_add:
 error_rc_setup:
 	rc->stop(rc);
-	uwbd_stop(rc);
 error_rc_start:
+	uwbd_stop(rc);
 	return result;
 }
 EXPORT_SYMBOL_GPL(uwb_rc_add);
diff --git a/drivers/uwb/reset.c b/drivers/uwb/reset.c
index 70f8050..7f0512e 100644
--- a/drivers/uwb/reset.c
+++ b/drivers/uwb/reset.c
@@ -30,6 +30,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/err.h>
+#include <linux/delay.h>
 
 #include "uwb-internal.h"
 
@@ -323,13 +324,15 @@
 
 	dev_info(&rc->uwb_dev.dev, "resetting radio controller\n");
 	ret = rc->reset(rc);
-	if (ret) {
+	if (ret < 0) {
 		dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret);
 		goto error;
 	}
 	return 0;
 error:
-	/* Nothing can be done except try the reset again. */
+	/* Nothing can be done except try the reset again. Wait a bit
+	   to avoid reset loops during probe() or remove(). */
+	msleep(1000);
 	uwb_rc_reset_all(rc);
 	return ret;
 }
@@ -368,22 +371,20 @@
 }
 EXPORT_SYMBOL_GPL(uwb_rc_pre_reset);
 
-void uwb_rc_post_reset(struct uwb_rc *rc)
+int uwb_rc_post_reset(struct uwb_rc *rc)
 {
 	int ret;
 
 	ret = rc->start(rc);
 	if (ret)
-		goto error;
+		goto out;
 	ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr);
 	if (ret)
-		goto error;
+		goto out;
 	ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr);
 	if (ret)
-		goto error;
-	return;
-error:
-	/* Nothing can be done except try the reset again. */
-	uwb_rc_reset_all(rc);
+		goto out;
+out:
+	return ret;
 }
 EXPORT_SYMBOL_GPL(uwb_rc_post_reset);
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c
index 5ad3616..cdd6c8e 100644
--- a/drivers/uwb/umc-bus.c
+++ b/drivers/uwb/umc-bus.c
@@ -66,7 +66,7 @@
 		return -EAGAIN;
 	ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper);
 	if (ret >= 0)
-		device_for_each_child(parent, parent, umc_bus_post_reset_helper);
+		ret = device_for_each_child(parent, parent, umc_bus_post_reset_helper);
 	up(&parent->sem);
 
 	return ret;
diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c
index 57bd6bf..5a777d8 100644
--- a/drivers/uwb/uwbd.c
+++ b/drivers/uwb/uwbd.c
@@ -187,12 +187,12 @@
 	event = le16_to_cpu(evt->notif.rceb->wEvent);
 	context = evt->notif.rceb->bEventContext;
 
-	if (type > ARRAY_SIZE(uwbd_urc_evt_type_handlers))
+	if (type >= ARRAY_SIZE(uwbd_urc_evt_type_handlers))
 		goto out;
 	type_table = &uwbd_urc_evt_type_handlers[type];
 	if (type_table->uwbd_events == NULL)
 		goto out;
-	if (event > type_table->size)
+	if (event >= type_table->size)
 		goto out;
 	handler = type_table->uwbd_events[event].handler;
 	if (handler == NULL)
diff --git a/drivers/uwb/whc-rc.c b/drivers/uwb/whc-rc.c
index 19a1dd1..1d9a6f5 100644
--- a/drivers/uwb/whc-rc.c
+++ b/drivers/uwb/whc-rc.c
@@ -443,8 +443,7 @@
 	struct whcrc *whcrc = umc_get_drvdata(umc);
 	struct uwb_rc *uwb_rc = whcrc->uwb_rc;
 
-	uwb_rc_post_reset(uwb_rc);
-	return 0;
+	return uwb_rc_post_reset(uwb_rc);
 }
 
 /* PCI device ID's that we handle [so it gets loaded] */
diff --git a/include/linux/uwb.h b/include/linux/uwb.h
index c021289..7fc9746 100644
--- a/include/linux/uwb.h
+++ b/include/linux/uwb.h
@@ -597,7 +597,7 @@
 void uwb_rc_neh_error(struct uwb_rc *, int);
 void uwb_rc_reset_all(struct uwb_rc *rc);
 void uwb_rc_pre_reset(struct uwb_rc *rc);
-void uwb_rc_post_reset(struct uwb_rc *rc);
+int uwb_rc_post_reset(struct uwb_rc *rc);
 
 /**
  * uwb_rsv_is_owner - is the owner of this reservation the RC?