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
- * yyuasa@mvista.com or source@mvista.com
+ * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
*
- * 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 <lethal@chaoticdreams.org>
- * - Fix deadlock-causing PCIU access race for VR4131.
- *
* MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
* - 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
- * yyuasa@mvista.com or source@mvista.com
+ * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
*
- * 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 {
|