Subject: [PATCH][2.4] Fixed PCI config founctions for vr41xx

From: Yoichi Yuasa <[email-masked]>
Date: Tue, 10 Feb 2004 17:47:59 +0900

Hello Ralf,

I made a patch for PCI config functions for vr41xx.

I found my mistake about PCI config functions of vr41xx,
and also include some fixes.

Please apply this patch to v2.4.

Yoichi

diff -urN -X dontdiff linux-orig/arch/mips/vr41xx/common/pciu.c linux/arch/mips/vr41xx/common/pciu.c
--- linux-orig/arch/mips/vr41xx/common/pciu.c	2003-12-02 04:31:49.000000000 +0900
+++ linux/arch/mips/vr41xx/common/pciu.c	2004-02-10 15:52:00.000000000 +0900
@@ -1,40 +1,17 @@
 /*
- * FILE NAME
- *	arch/mips/vr41xx/common/pciu.c
+ * arch/mips/vr41xx/common/pciu.c
  *
- * BRIEF MODULE DESCRIPTION
- *	PCI Control Unit routines for the NEC VR4100 series.
+ * PCI Control Unit routines for the NEC VR4100 series.
  *
- * Author: Yoichi Yuasa
- *         [email-masked] or [email-masked]
+ * Author: Yoichi Yuasa <[email-masked], or [email-masked]>
  *
- * Copyright 2001,2002 MontaVista Software Inc.
- *
- *  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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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.
+ * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
  */
 /*
  * Changes:
- *  Paul Mundt <[email-masked]>
- *  - Fix deadlock-causing PCIU access race for VR4131.
- *
  *  MontaVista Software Inc. <[email-masked]> or <[email-masked]>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  */
@@ -42,7 +19,6 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/types.h>
-#include <linux/delay.h>
 
 #include <asm/cpu.h>
 #include <asm/io.h>
@@ -60,49 +36,48 @@
 		/*
 		 * Type 0 configuration
 		 */
-		if (PCI_SLOT(dev_fn) < 11 || PCI_SLOT(dev_fn) > 31 || where > 255)
-			return -1;
+		if (PCI_SLOT(dev_fn) < 11 || PCI_SLOT(dev_fn) > 31 || where > 0xff)
+			return -EINVAL;
 
-		writel((1UL << PCI_SLOT(dev_fn))|
+		writel((1U << PCI_SLOT(dev_fn))	|
 		       (PCI_FUNC(dev_fn) << 8)	|
 		       (where & 0xfc),
 		       PCICONFAREG);
-	}
-	else {
+	} else {
 		/*
 		 * Type 1 configuration
 		 */
-		if (PCI_SLOT(dev_fn) > 31 || where > 255)
-			return -1;
+		if (PCI_SLOT(dev_fn) > 31 || where > 0xff)
+			return -EINVAL;
 
 		writel((bus << 16)	|
 		       (dev_fn << 8)	|
 		       (where & 0xfc)	|
-		       1UL,
+		       1U,
 		       PCICONFAREG);
 	}
 
 	return 0;
 }
 
-static int vr41xx_pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
+static int vr41xx_pci_config_read_byte(struct pci_dev *dev, int where, uint8_t *val)
 {
-	u32 data;
+	uint32_t data;
 
 	*val = 0xff;
 	if (vr41xx_pci_config_access(dev, where) < 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	data = readl(PCICONFDREG);
-	*val = (u8)(data >> ((where & 3) << 3));
+	*val = (uint8_t)(data >> ((where & 3) << 3));
 
 	return PCIBIOS_SUCCESSFUL;
 
 }
 
-static int vr41xx_pci_read_config_word(struct pci_dev *dev, int where, u16 *val)
+static int vr41xx_pci_config_read_word(struct pci_dev *dev, int where, uint16_t *val)
 {
-	u32 data;
+	uint32_t data;
 
 	*val = 0xffff;
 	if (where & 1)
@@ -112,12 +87,12 @@
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	data = readl(PCICONFDREG);
-	*val = (u16)(data >> ((where & 2) << 3));
+	*val = (uint16_t)(data >> ((where & 2) << 3));
 
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int vr41xx_pci_read_config_dword(struct pci_dev *dev, int where, u32 *val)
+static int vr41xx_pci_config_read_dword(struct pci_dev *dev, int where, uint32_t *val)
 {
 	*val = 0xffffffff;
 	if (where & 3)
@@ -131,9 +106,9 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int vr41xx_pci_write_config_byte(struct pci_dev *dev, int where, u8 val)
+static int vr41xx_pci_config_write_byte(struct pci_dev *dev, int where, uint8_t val)
 {
-	u32 data;
+	uint32_t data;
 	int shift;
 
 	if (vr41xx_pci_config_access(dev, where) < 0)
@@ -141,17 +116,16 @@
 
 	data = readl(PCICONFDREG);
 	shift = (where & 3) << 3;
-	data &= ~(0xff << shift);
-	data |= (((u32)val) << shift);
-
+	data &= ~(0xffU << shift);
+	data |= (uint32_t)val << shift;
 	writel(data, PCICONFDREG);
 
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int vr41xx_pci_write_config_word(struct pci_dev *dev, int where, u16 val)
+static int vr41xx_pci_config_write_word(struct pci_dev *dev, int where, uint16_t val)
 {
-	u32 data;
+	uint32_t data;
 	int shift;
 
 	if (where & 1)
@@ -162,14 +136,14 @@
 
 	data = readl(PCICONFDREG);
 	shift = (where & 2) << 3;
-	data &= ~(0xffff << shift);
-	data |= (((u32)val) << shift);
+	data &= ~(0xffffU << shift);
+	data |= (uint32_t)val << shift;
 	writel(data, PCICONFDREG);
 
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int vr41xx_pci_write_config_dword(struct pci_dev *dev, int where, u32 val)
+static int vr41xx_pci_config_write_dword(struct pci_dev *dev, int where, uint32_t val)
 {
 	if (where & 3)
 		return PCIBIOS_BAD_REGISTER_NUMBER;
@@ -183,22 +157,21 @@
 }
 
 struct pci_ops vr41xx_pci_ops = {
-	vr41xx_pci_read_config_byte,
-	vr41xx_pci_read_config_word,
-	vr41xx_pci_read_config_dword,
-	vr41xx_pci_write_config_byte,
-	vr41xx_pci_write_config_word,
-	vr41xx_pci_write_config_dword
+	.read_byte	= vr41xx_pci_config_read_byte,
+	.read_word	= vr41xx_pci_config_read_word,
+	.read_dword	= vr41xx_pci_config_read_dword,
+	.write_byte	= vr41xx_pci_config_write_byte,
+	.write_word	= vr41xx_pci_config_write_word,
+	.write_dword	= vr41xx_pci_config_write_dword,
 };
 
 void __init vr41xx_pciu_init(struct vr41xx_pci_address_map *map)
 {
 	struct vr41xx_pci_address_space *s;
 	unsigned long vtclock;
-	u32 config;
-	int n;
+	uint32_t config;
 
-	if (!map)
+	if (map == NULL)
 		return;
 
 	/* Disable PCI interrupt */
@@ -207,11 +180,9 @@
 	/* Supply VTClock to PCIU */
 	vr41xx_clock_supply(PCIU_CLOCK);
 
-	/*
-	 * Sleep for 1us after setting MSKPPCIU bit in CMUCLKMSK
-	 * before doing any PCIU access to avoid deadlock on VR4131.
-	 */
-	udelay(1);
+	/* Dummy read/write, waiting for supply of VTClock. */
+	readw(MPCIINTREG);
+	writew(0, MPCIINTREG);
 
 	/* Select PCI clock */
 	vtclock = vr41xx_get_vtclock_frequency();
@@ -233,48 +204,52 @@
 	 */
 	if (map->mem1 != NULL) {
 		s = map->mem1;
-		config = (s->internal_base & 0xff000000) |
-		         ((s->address_mask & 0x7f000000) >> 11) | (1UL << 12) |
-		         ((s->pci_base & 0xff000000) >> 24);
+		config = (s->internal_base & INTERNAL_BUS_BASE_ADDRESS)	|
+		         ((s->address_mask >> 11) & ADDRESS_MASK)	|
+		         PCI_ACCESS_ENABLE				|
+		         ((s->pci_base >> 24) & PCI_ADDRESS_SETTING);
 		writel(config, PCIMMAW1REG);
 	}
 	if (map->mem2 != NULL) {
 		s = map->mem2;
-		config = (s->internal_base & 0xff000000) |
-		         ((s->address_mask & 0x7f000000) >> 11) | (1UL << 12) |
-		         ((s->pci_base & 0xff000000) >> 24);
+		config = (s->internal_base & INTERNAL_BUS_BASE_ADDRESS)	|
+		         ((s->address_mask >> 11) & ADDRESS_MASK)	|
+		         PCI_ACCESS_ENABLE				|
+		         ((s->pci_base >> 24) & PCI_ADDRESS_SETTING);
 		writel(config, PCIMMAW2REG);
 	}
 	if (map->io != NULL) {
 		s = map->io;
-		config = (s->internal_base & 0xff000000) |
-		         ((s->address_mask & 0x7f000000) >> 11) | (1UL << 12) |
-		         ((s->pci_base & 0xff000000) >> 24);
+		config = (s->internal_base & INTERNAL_BUS_BASE_ADDRESS) |
+		         ((s->address_mask >> 11) & ADDRESS_MASK) |
+		         PCI_ACCESS_ENABLE |
+		         ((s->pci_base >> 24) & PCI_ADDRESS_SETTING);
 		writel(config, PCIMIOAWREG);
 	}
 
 	/* Set target memory windows */
-	writel(0x00081000, PCITAW1REG);
-	writel(0UL, PCITAW2REG);
-	pciu_write_config_dword(PCI_BASE_ADDRESS_0, 0UL);
-	pciu_write_config_dword(PCI_BASE_ADDRESS_1, 0UL);
+	writel(0x00081000U, PCITAW1REG);
+	writel(0U, PCITAW2REG);
+
+	pciu_write_config_dword(PCI_BASE_ADDRESS_0, 0U);
+	pciu_write_config_dword(PCI_BASE_ADDRESS_1, 0U);
 
 	/* Clear bus error */
-	n = readl(BUSERRADREG);
+	readl(BUSERRADREG);
 
 	if (current_cpu_data.cputype == CPU_VR4122) {
-		writel(0UL, PCITRDYVREG);
-		pciu_write_config_dword(PCI_CACHE_LINE_SIZE, 0x0000f804);
+		writel(0U, PCITRDYVREG);
+		pciu_write_config_byte(PCI_LATENCY_TIMER, 0xf8);
 	} else {
-		writel(100UL, PCITRDYVREG);
-		pciu_write_config_dword(PCI_CACHE_LINE_SIZE, 0x00008004);
+		writel(100U, PCITRDYVREG);
+		pciu_write_config_byte(PCI_LATENCY_TIMER, 0x80);
 	}
 
 	writel(CONFIG_DONE, PCIENREG);
-	pciu_write_config_dword(PCI_COMMAND,
-	                        PCI_COMMAND_IO |
-	                        PCI_COMMAND_MEMORY |
-	                        PCI_COMMAND_MASTER |
-	                        PCI_COMMAND_PARITY |
-	                        PCI_COMMAND_SERR);
+	pciu_write_config_word(PCI_COMMAND,
+	                       PCI_COMMAND_IO |
+	                       PCI_COMMAND_MEMORY |
+	                       PCI_COMMAND_MASTER |
+	                       PCI_COMMAND_PARITY |
+	                       PCI_COMMAND_SERR);
 }
diff -urN -X dontdiff linux-orig/arch/mips/vr41xx/common/pciu.h linux/arch/mips/vr41xx/common/pciu.h
--- linux-orig/arch/mips/vr41xx/common/pciu.h	2003-10-31 10:43:08.000000000 +0900
+++ linux/arch/mips/vr41xx/common/pciu.h	2004-02-10 15:53:07.000000000 +0900
@@ -1,34 +1,14 @@
 /*
- * FILE NAME
- *	arch/mips/vr41xx/common/pciu.h
+ * arch/mips/vr41xx/common/pciu.h
  *
- * BRIEF MODULE DESCRIPTION
- *	Include file for PCI Control Unit of the NEC VR4100 series.
+ * Include file for PCI Control Unit of the NEC VR4100 series.
  *
- * Author: Yoichi Yuasa
- *         [email-masked] or [email-masked]
+ * Author: Yoichi Yuasa <[email-masked], or [email-masked]>
  *
- * Copyright 2002 MontaVista Software Inc.
- *
- *  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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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.
+ * 2002-2003 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
  */
 /*
  * Changes:
@@ -41,24 +21,24 @@
 #include <linux/config.h>
 #include <asm/addrspace.h>
 
-#define BIT(x)	(1 << (x))
+#define BIT(x)	(1U << (x))
 
 #define PCIMMAW1REG			KSEG1ADDR(0x0f000c00)
 #define PCIMMAW2REG			KSEG1ADDR(0x0f000c04)
 #define PCITAW1REG			KSEG1ADDR(0x0f000c08)
 #define PCITAW2REG			KSEG1ADDR(0x0f000c0c)
 #define PCIMIOAWREG			KSEG1ADDR(0x0f000c10)
-#define INTERNAL_BUS_BASE_ADDRESS	0xff000000
-#define ADDRESS_MASK			0x000fe000
+#define INTERNAL_BUS_BASE_ADDRESS	0xff000000U
+#define ADDRESS_MASK			0x000fe000U
 #define PCI_ACCESS_ENABLE		BIT(12)
-#define PCI_ADDRESS_SETTING		0x000000ff
+#define PCI_ADDRESS_SETTING		0x000000ffU
 
 #define PCICONFDREG			KSEG1ADDR(0x0f000c14)
 #define PCICONFAREG			KSEG1ADDR(0x0f000c18)
 #define PCIMAILREG			KSEG1ADDR(0x0f000c1c)
 
 #define BUSERRADREG			KSEG1ADDR(0x0f000c24)
-#define ERROR_ADDRESS			0xfffffffc
+#define ERROR_ADDRESS			0xfffffffcU
 
 #define INTCNTSTAREG			KSEG1ADDR(0x0f000c28)
 #define MABTCLR				BIT(31)
@@ -72,91 +52,102 @@
 #define EAREQ				BIT(0)
 
 #define PCIRECONTREG			KSEG1ADDR(0x0f000c30)
-#define RTRYCNT				0x000000ff
+#define RTRYCNT				0xffU
 
 #define PCIENREG			KSEG1ADDR(0x0f000c34)
 #define CONFIG_DONE			BIT(2)
 
 #define PCICLKSELREG			KSEG1ADDR(0x0f000c38)
-#define EQUAL_VTCLOCK			0x00000002
-#define HALF_VTCLOCK			0x00000000
-#define QUARTER_VTCLOCK			0x00000001
+#define EQUAL_VTCLOCK			0x2U
+#define HALF_VTCLOCK			0x0U
+#define QUARTER_VTCLOCK			0x1U
 
 #define PCITRDYVREG			KSEG1ADDR(0x0f000c3c)
 
 #define PCICLKRUNREG			KSEG1ADDR(0x0f000c60)
 
-#define PCIU_CONFIGREGS_BASE		KSEG1ADDR(0x0f000d00)
 #define VENDORIDREG			KSEG1ADDR(0x0f000d00)
-#define DEVICEIDREG			KSEG1ADDR(0x0f000d00)
-#define COMMANDREG			KSEG1ADDR(0x0f000d04)
-#define STATUSREG			KSEG1ADDR(0x0f000d04)
-#define REVIDREG			KSEG1ADDR(0x0f000d08)
-#define CLASSREG			KSEG1ADDR(0x0f000d08)
-#define CACHELSREG			KSEG1ADDR(0x0f000d0c)
-#define LATTIMEREG			KSEG1ADDR(0x0f000d0c)
-#define MAILBAREG			KSEG1ADDR(0x0f000d10)
-#define PCIMBA1REG			KSEG1ADDR(0x0f000d14)
-#define PCIMBA2REG			KSEG1ADDR(0x0f000d18)
-#define INTLINEREG			KSEG1ADDR(0x0f000d3c)
-#define INTPINREG			KSEG1ADDR(0x0f000d3c)
-#define RETVALREG			KSEG1ADDR(0x0f000d40)
-#define PCIAPCNTREG			KSEG1ADDR(0x0f000d40)
 
 #define MPCIINTREG			KSEG1ADDR(0x0f0000b2)
 
 #define MAX_PCI_CLOCK			33333333
 
-static inline int pciu_read_config_byte(int where, u8 *val)
+static inline int pciu_read_config_byte(int where, uint8_t *val)
 {
-	u32 data;
+	uint32_t data;
 
-	data = readl(PCIU_CONFIGREGS_BASE + where);
-	*val = (u8)(data >> ((where & 3) << 3));
+	if (where > 0xff)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	data = readl(VENDORIDREG + (where & 0xfc));
+	*val = (uint8_t)(data >> ((where & 3) << 3));
 
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static inline int pciu_read_config_word(int where, u16 *val)
+static inline int pciu_read_config_word(int where, uint16_t *val)
 {
-	u32 data;
+	uint32_t data;
 
-	if (where & 1)
+	if (where > 0xff || (where & 1))
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	data = readl(PCIU_CONFIGREGS_BASE + where);
-	*val = (u16)(data >> ((where & 2) << 3));
+	data = readl(VENDORIDREG + (where & 0xfc));
+	*val = (uint16_t)(data >> ((where & 2) << 3));
 
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static inline int pciu_read_config_dword(int where, u32 *val)
+static inline int pciu_read_config_dword(int where, uint32_t *val)
 {
-	if (where & 3)
+	if (where > 0xff || (where & 3))
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	*val = readl(PCIU_CONFIGREGS_BASE + where);
+	*val = readl(VENDORIDREG + where);
 
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static inline int pciu_write_config_byte(int where, u8 val)
+static inline int pciu_write_config_byte(int where, uint8_t val)
 {
-	writel(val, PCIU_CONFIGREGS_BASE + where);
+	uint32_t data;
+	int shift;
+
+	if (where > 0xff)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	data = readl(VENDORIDREG + (where & 0xfc));
+	shift = (where & 3) << 3;
+	data &= ~(0xffU << shift);
+	data |= (uint32_t)val << shift;
+	writel(data, VENDORIDREG + (where & 0xfc));
 
 	return 0;
 }
 
-static inline int pciu_write_config_word(int where, u16 val)
+static inline int pciu_write_config_word(int where, uint16_t val)
 {
-	writel(val, PCIU_CONFIGREGS_BASE + where);
+	uint32_t data;
+	int shift;
+
+	if (where > 0xff || (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	data = readl(VENDORIDREG + (where & 0xfc));
+	shift = (where & 2) << 3;
+	data &= ~(0xffffU << shift);
+	data |= (uint32_t)val << shift;
+	writel(data, VENDORIDREG + (where & 0xfc));
 
 	return 0;
 }
 
-static inline int pciu_write_config_dword(int where, u32 val)
+static inline int pciu_write_config_dword(int where, uint32_t val)
 {
-	writel(val, PCIU_CONFIGREGS_BASE + where);
+	if (where > 0xff || (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	writel(val, VENDORIDREG + where);
 
 	return 0;
 }
diff -urN -X dontdiff linux-orig/include/asm-mips/vr41xx/vr41xx.h linux/include/asm-mips/vr41xx/vr41xx.h
--- linux-orig/include/asm-mips/vr41xx/vr41xx.h	2004-02-09 10:43:52.000000000 +0900
+++ linux/include/asm-mips/vr41xx/vr41xx.h	2004-02-10 15:58:45.000000000 +0900
@@ -208,9 +208,9 @@
  * PCI Control Unit
  */
 struct vr41xx_pci_address_space {
-	u32 internal_base;
-	u32 address_mask;
-	u32 pci_base;
+	uint32_t internal_base;
+	uint32_t address_mask;
+	uint32_t pci_base;
 };
 
 struct vr41xx_pci_address_map {