[PATCH] ARM: 2752/1: disable ixp2000 PCI I/O software workaround on chips that don't need it

Patch from Lennert Buytenhek

The later ixp2000 models don't need the PCI I/O workaround that we
currently perform.  Add a config option to disable the workaround,
and panic on boot if a kernel without the workaround is booted on a
buggy chip.  As only pre-production ixp2000s need the workaround,
the default is for it not to be configured in.

Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Deepak Saxena
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
index af21534..b8c51ee 100644
--- a/arch/arm/configs/enp2611_defconfig
+++ b/arch/arm/configs/enp2611_defconfig
@@ -99,6 +99,7 @@
 # CONFIG_ARCH_IXDP2800 is not set
 # CONFIG_ARCH_IXDP2401 is not set
 # CONFIG_ARCH_IXDP2801 is not set
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
 #
 # Processor Type
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
index a7ee1a4..3cfbe2e 100644
--- a/arch/arm/configs/ixdp2400_defconfig
+++ b/arch/arm/configs/ixdp2400_defconfig
@@ -100,6 +100,7 @@
 CONFIG_ARCH_IXDP2X00=y
 # CONFIG_ARCH_IXDP2401 is not set
 # CONFIG_ARCH_IXDP2801 is not set
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
 #
 # Processor Type
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
index 2da48fc..5c87e8e 100644
--- a/arch/arm/configs/ixdp2401_defconfig
+++ b/arch/arm/configs/ixdp2401_defconfig
@@ -100,6 +100,7 @@
 CONFIG_ARCH_IXDP2401=y
 # CONFIG_ARCH_IXDP2801 is not set
 CONFIG_ARCH_IXDP2X01=y
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
 #
 # Processor Type
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
index 7ba867f..3cb561a 100644
--- a/arch/arm/configs/ixdp2800_defconfig
+++ b/arch/arm/configs/ixdp2800_defconfig
@@ -100,6 +100,7 @@
 CONFIG_ARCH_IXDP2X00=y
 # CONFIG_ARCH_IXDP2401 is not set
 # CONFIG_ARCH_IXDP2801 is not set
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
 #
 # Processor Type
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
index c4df0ec..b1e162f 100644
--- a/arch/arm/configs/ixdp2801_defconfig
+++ b/arch/arm/configs/ixdp2801_defconfig
@@ -100,6 +100,7 @@
 # CONFIG_ARCH_IXDP2401 is not set
 CONFIG_ARCH_IXDP2801=y
 CONFIG_ARCH_IXDP2X01=y
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
 #
 # Processor Type
diff --git a/arch/arm/mach-ixp2000/Kconfig b/arch/arm/mach-ixp2000/Kconfig
index 9361e05..ecb58d8 100644
--- a/arch/arm/mach-ixp2000/Kconfig
+++ b/arch/arm/mach-ixp2000/Kconfig
@@ -54,6 +54,14 @@
 	depends on ARCH_IXDP2401 || ARCH_IXDP2801
 	default y	
 
+config IXP2000_SUPPORT_BROKEN_PCI_IO
+	bool "Support broken PCI I/O on older IXP2000s"
+	default y
+	help
+	  Say 'N' here if you only intend to run your kernel on an
+	  IXP2000 B0 or later model and do not need the PCI I/O
+	  byteswap workaround.  Say 'Y' otherwise.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
index 5ff2f27..0788fb2 100644
--- a/arch/arm/mach-ixp2000/pci.c
+++ b/arch/arm/mach-ixp2000/pci.c
@@ -198,6 +198,19 @@
 void __init
 ixp2000_pci_preinit(void)
 {
+#ifndef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
+	/*
+	 * Configure the PCI unit to properly byteswap I/O transactions,
+	 * and verify that it worked.
+	 */
+	ixp2000_reg_write(IXP2000_PCI_CONTROL,
+			  (*IXP2000_PCI_CONTROL | PCI_CONTROL_IEE));
+
+	if ((*IXP2000_PCI_CONTROL & PCI_CONTROL_IEE) == 0)
+		panic("IXP2000: PCI I/O is broken on this ixp model, and "
+			"the needed workaround has not been configured in");
+#endif
+
 	hook_fault_code(16+6, ixp2000_pci_abort_handler, SIGBUS,
 				"PCI config cycle to non-existent device");
 }