public inbox for linuxppc-dev@ozlabs.org 
 help / color / mirror / Atom feed
From: Olof Johansson <olof@lixom•net>
To: paulus@samba•org
Cc: linuxppc-dev@ozlabs•org
Subject: [POWERPC] pasemi: Add workaround for erratum 5945
Date: Tue, 4 Sep 2007 21:08:50 -0500	[thread overview]
Message-ID: <20070905020850.GC25900@lixom.net> (raw)
In-Reply-To: <20070905020733.GA25900@lixom.net>

commit 3f7a4e905341e46e7b442a9326c3b31229e25209
Author: Olof Johansson <olof@lixom•net>
Date:   Mon Sep 3 00:11:49 2007 -0500

    [POWERPC] pasemi: Add workaround for erratum 5945
    
    Erratum 5945 causes some of the registers on the PCIe root ports to
    not read correctly.  Do a small dance to avoid this: Write an unused
    register, read the value and write it back. Thankfully this is not in
    a hot code path.
    
    Signed-off-by: Olof Johansson <olof@lixom•net>

diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c
index fcfb3df..b6a0ec4 100644
--- a/arch/powerpc/platforms/pasemi/pci.c
+++ b/arch/powerpc/platforms/pasemi/pci.c
@@ -51,6 +51,61 @@ static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose,
 	return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset);
 }
 
+static inline int is_root_port(int busno, int devfn)
+{
+	return ((busno == 0) && (PCI_FUNC(devfn) < 4) &&
+		 ((PCI_SLOT(devfn) == 16) || (PCI_SLOT(devfn) == 17)));
+}
+
+static inline int is_5945_reg(int reg)
+{
+	return (((reg >= 0x18) && (reg < 0x34)) ||
+		((reg >= 0x158) && (reg < 0x178)));
+}
+
+static int workaround_5945(struct pci_bus *bus, unsigned int devfn,
+			   int offset, int len, u32 *val)
+{
+	struct pci_controller *hose;
+	void volatile __iomem *addr, *dummy;
+	int byte;
+	u32 tmp;
+
+	if (!is_root_port(bus->number, devfn) || !is_5945_reg(offset))
+		return 0;
+
+	hose = pci_bus_to_host(bus);
+
+	addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset & ~0x3);
+	byte = offset & 0x3;
+
+	/* Workaround bug 5945: write 0 to a dummy register before reading,
+	 * and write back what we read. We must read/write the full 32-bit
+	 * contents so we need to shift and mask by hand.
+	 */
+	dummy = pa_pxp_cfg_addr(hose, bus->number, devfn, 0x10);
+	out_le32(dummy, 0);
+	tmp = in_le32(addr);
+	out_le32(addr, tmp);
+
+	switch (len) {
+	case 1:
+		*val = (tmp >> (8*byte)) & 0xff;
+		break;
+	case 2:
+		if (byte == 0)
+			*val = tmp & 0xffff;
+		else
+			*val = (tmp >> 16) & 0xffff;
+		break;
+	default:
+		*val = tmp;
+		break;
+	}
+
+	return 1;
+}
+
 static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
 			      int offset, int len, u32 *val)
 {
@@ -64,6 +119,9 @@ static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
 	if (!pa_pxp_offset_valid(bus->number, devfn, offset))
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
+	if (workaround_5945(bus, devfn, offset, len, val))
+		return PCIBIOS_SUCCESSFUL;
+
 	addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
 
 	/*
@@ -180,7 +238,7 @@ void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset)
 {
 	struct pci_controller *hose;
 
-	hose = pci_bus_to_host(bus);
+	hose = pci_bus_to_host(dev->bus);
 
-	return pa_pxp_cfg_addr(hose, hose->number, dev->devfn, int offset)
+	return (void __iomem *)pa_pxp_cfg_addr(hose, dev->bus->number, dev->devfn, offset);
 }

  parent reply	other threads:[~2007-09-05  3:01 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-05  2:07 Please pull from 'for-2.6.24' branch Olof Johansson
2007-09-05  2:08 ` [POWERPC] pasemi: add pasemi_pci_getcfgaddr() Olof Johansson
2007-09-05  2:08 ` Olof Johansson [this message]
2007-09-05  2:09 ` [POWERPC] pasemi: Export more SPRs to sysfs when CONFIG_DEBUG_KERNEL=y Olof Johansson
2007-09-05  2:09 ` [POWERPC] pasemi: Print more information at machine check Olof Johansson
2007-09-05  2:09 ` [POWERPC] pasemi: Move pasemi_idle_init() to late_initcall() Olof Johansson
2007-09-10 15:44   ` Nathan Lynch
2007-09-10 16:00     ` Olof Johansson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070905020850.GC25900@lixom.net \
    --to=olof@lixom$(echo .)net \
    --cc=linuxppc-dev@ozlabs$(echo .)org \
    --cc=paulus@samba$(echo .)org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox