linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] [POWERPC] Add support for Rev. B of PowerPC 440SPe
@ 2006-11-13 17:55 Roland Dreier
  2006-11-13 22:27 ` Wolfgang Denk
  2006-11-13 22:31 ` [PATCH v2 -- fixed changelog] " Roland Dreier
  0 siblings, 2 replies; 11+ messages in thread
From: Roland Dreier @ 2006-11-13 17:55 UTC (permalink / raw)
  To: mporter; +Cc: linuxppc-embedded

This is mostly updating the PCI Express code to work with the new core
in the Rev. B chip, which unfortunately has different undocumented
restrictions on the PLB addresses that can be used from the Rev. A core.

Also, when adding the cputable entry for 440SPe Rev. B, we need to
adjust the entry for 440SP Rev. A so that it looks at more bits of the
PVR.  The 440SPe Rev. B has PVR 53421891, which would have matched the
old 440SP pattern of 53xxx891.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
---
Matt, please queue for a 2.6.20 merge.

 arch/powerpc/kernel/cputable.c           |   21 ++-
 arch/ppc/platforms/4xx/davinci_sc.c      |    5 -
 arch/ppc/syslib/ppc440spe_pcie.c         |  258 ++++++++++++++++++++++--------
 drivers/infiniband/hw/mthca/mthca_main.c |    4 +-
 4 files changed, 206 insertions(+), 82 deletions(-)

diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index bfd499e..04559be 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1073,8 +1073,8 @@ #ifdef CONFIG_44x
 		.platform		= "ppc440",
 	},
 	{ /* 440SP Rev. A */
-		.pvr_mask		= 0xff000fff,
-		.pvr_value		= 0x53000891,
+		.pvr_mask		= 0xfff00fff,
+		.pvr_value		= 0x53200891,
 		.cpu_name		= "440SP Rev. A",
 		.cpu_features		= CPU_FTRS_44X,
 		.cpu_user_features	= COMMON_USER_BOOKE,
@@ -1083,9 +1083,20 @@ #ifdef CONFIG_44x
 		.platform		= "ppc440",
 	},
 	{ /* 440SPe Rev. A */
-		.pvr_mask		= 0xff000fff,
-		.pvr_value		= 0x53000890,
-		.cpu_name		= "440SPe Rev. A",
+		.pvr_mask               = 0xfff00fff,
+		.pvr_value              = 0x53400890,
+		.cpu_name               = "440SPe Rev. A",
+		.cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+			CPU_FTR_USE_TB,
+		.cpu_user_features      = COMMON_USER_BOOKE,
+		.icache_bsize           = 32,
+		.dcache_bsize           = 32,
+		.platform               = "ppc440",
+	},
+	{ /* 440SPe Rev. B */
+		.pvr_mask		= 0xfff00fff,
+		.pvr_value		= 0x53400891,
+		.cpu_name		= "440SPe Rev. B",
 		.cpu_features		= CPU_FTR_SPLIT_ID_CACHE |
 			CPU_FTR_USE_TB,
 		.cpu_user_features	= COMMON_USER_BOOKE,
diff --git a/arch/ppc/platforms/4xx/davinci_sc.c b/arch/ppc/platforms/4xx/davinci_sc.c
index 623988f..3dbedda 100644
--- a/arch/ppc/platforms/4xx/davinci_sc.c
+++ b/arch/ppc/platforms/4xx/davinci_sc.c
@@ -172,11 +172,6 @@ davinci_sc_setup_hoses(void)
 	char name[20];
 	int i;
 
-	if (0 && ppc440spe_init_pcie()) {
-		printk(KERN_WARNING "PPC440SPe PCI Express initialization failed\n");
-		return;
-	}
-
 	for (i = 0; i <= 2; ++i) {
 		if (!davinci_sc_pcie_card_present(i))
 			continue;
diff --git a/arch/ppc/syslib/ppc440spe_pcie.c b/arch/ppc/syslib/ppc440spe_pcie.c
index dd5d4b9..7ae14d2 100644
--- a/arch/ppc/syslib/ppc440spe_pcie.c
+++ b/arch/ppc/syslib/ppc440spe_pcie.c
@@ -19,16 +19,23 @@ #include <asm/ibm44x.h>
 
 #include "ppc440spe_pcie.h"
 
+static enum {
+	REV_A,
+	REV_B
+} core_rev;
+
 static int
 pcie_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
 		     int len, u32 *val)
 {
 	struct pci_controller *hose = bus->sysdata;
 
-	if (PCI_SLOT(devfn) != 1)
+	/* 440SPE implements only one function per port */
+	if (PCI_SLOT(devfn) != 1 || PCI_FUNC(devfn) != 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	offset += devfn << 12;
+	if (core_rev == REV_A)
+		offset += devfn << 12;
 
 	/*
 	 * Note: the caller has already checked that offset is
@@ -57,10 +64,11 @@ pcie_write_config(struct pci_bus *bus, u
 {
 	struct pci_controller *hose = bus->sysdata;
 
-	if (PCI_SLOT(devfn) != 1)
+	if (PCI_SLOT(devfn) != 1 || PCI_FUNC(devfn) != 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	offset += devfn << 12;
+	if (core_rev == REV_A)
+		offset += devfn << 12;
 
 	switch (len) {
 	case 1:
@@ -153,6 +161,20 @@ static void check_error(void)
  */
 int ppc440spe_init_pcie(void)
 {
+	int i;
+
+	switch (PVR_REV(mfspr(SPRN_PVR))) {
+	case 0x1890: core_rev = REV_A; break;
+	case 0x1891: core_rev = REV_B; break;
+	default:
+		printk(KERN_ERR "PCIE: Unknown PVR rev. %lx\n",
+		       PVR_REV(mfspr(SPRN_PVR)));
+		return -1;
+	}
+
+	printk(KERN_INFO "PCIE: core rev %c detected\n",
+	       core_rev == REV_A ? 'A' : 'B');
+
 	/* Set PLL clock receiver to LVPECL */
 	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28);
 
@@ -168,21 +190,78 @@ int ppc440spe_init_pcie(void)
 	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
 	udelay(3);
 
+	for (i = 0; i < 100; ++i) {
+		if (SDR_READ(PESDR0_PLLLCT3) & 0x10000000)
+			goto pll_ok;
+
+		udelay(1);
+	}
+
+	printk(KERN_INFO "PCIE: VCO output not locked: %x\n",
+	       SDR_READ(PESDR0_PLLLCT3));
+	return -1;
+
+pll_ok:
 	return 0;
 }
 
+static void ppc440spe_setup_utl(int port)
+{
+	void __iomem *utl_base;
+
+	/*
+	 * Map UTL registers at 0xc_1000_0n00
+	 */
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
+		break;
+
+	case 1:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
+		break;
+
+	case 2:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+	}
+
+	utl_base = ioremap64(0xc10000000ull + 0x1000 * port, 0x100);
+
+	/*
+	 * Set buffer allocations and then assert VRB and TXE.
+	 */
+	out_be32(utl_base + PEUTL_OUTTR,   0x08000000);
+	out_be32(utl_base + PEUTL_INTR,    0x02000000);
+	out_be32(utl_base + PEUTL_OPDBSZ,  0x10000000);
+	out_be32(utl_base + PEUTL_PBBSZ,   0x53000000);
+	out_be32(utl_base + PEUTL_IPHBSZ,  0x08000000);
+	out_be32(utl_base + PEUTL_IPDBSZ,  0x10000000);
+	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+	out_be32(utl_base + PEUTL_PCTL,    0x80800066);
+
+	iounmap(utl_base);
+}
+
 int ppc440spe_init_pcie_rootport(int port)
 {
 	static int core_init;
-	void __iomem *utl_base;
 	u32 val = 0;
 	int i;
 
 	if (!core_init) {
-		++core_init;
 		i = ppc440spe_init_pcie();
 		if (i)
 			return i;
+		++core_init;
 	}
 
 	/*
@@ -193,13 +272,19 @@ int ppc440spe_init_pcie_rootport(int por
 	 * - Set up UTL configuration.
 	 * - Increase SERDES drive strength to levels suggested by AMCC.
 	 * - De-assert RSTPYN, RSTDL and RSTGU.
+	 *
+	 * For rev. B chips, we don't set PESDRn_UTLSET2, but just
+	 * leave it with default setting 0x11310000. The register has
+	 * new fields, PESDRn_UTLSET2[LKINE] in particular: clearing
+	 * it leads to a PCIe core hang.
 	 */
 	switch (port) {
 	case 0:
 		SDR_WRITE(PESDR0_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X8 << 12);
 
 		SDR_WRITE(PESDR0_UTLSET1, 0x21222222);
-		SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
+		if (core_rev == REV_A)
+			SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
 
 		SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000);
 		SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000);
@@ -218,7 +303,8 @@ int ppc440spe_init_pcie_rootport(int por
 		SDR_WRITE(PESDR1_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
 
 		SDR_WRITE(PESDR1_UTLSET1, 0x21222222);
-		SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
+		if (core_rev == REV_A)
+			SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
 
 		SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000);
 		SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000);
@@ -233,7 +319,8 @@ int ppc440spe_init_pcie_rootport(int por
 		SDR_WRITE(PESDR2_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
 
 		SDR_WRITE(PESDR2_UTLSET1, 0x21222222);
-		SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
+		if (core_rev == REV_A)
+			SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
 
 		SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000);
 		SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
@@ -255,78 +342,81 @@ int ppc440spe_init_pcie_rootport(int por
 
 	if (!(val & (1 << 20)))
 		printk(KERN_INFO "PCIE%d: PGRST inactive\n", port);
-	else
-		printk(KERN_WARNING "PGRST for PCIE%d failed %08x\n", port, val);
-
-	switch (port) {
-	case 0: printk(KERN_INFO "PCIE0: LOOP %08x\n", SDR_READ(PESDR0_LOOP)); break;
-	case 1: printk(KERN_INFO "PCIE1: LOOP %08x\n", SDR_READ(PESDR1_LOOP)); break;
-	case 2: printk(KERN_INFO "PCIE2: LOOP %08x\n", SDR_READ(PESDR2_LOOP)); break;
+	else {
+		printk(KERN_WARNING "PCIE%d: PGRST failed %08x\n", port, val);
+		return -1;
 	}
 
-	/*
-	 * Map UTL registers at 0xc_1000_0n00
-	 */
 	switch (port) {
-	case 0:
-		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
-		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000);
-		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
-		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
-		break;
-
-	case 1:
-		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
-		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000);
-		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
-		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
-		break;
-
-	case 2:
-		mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
-		mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000);
-		mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
-		mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+	case 0: val = SDR_READ(PESDR0_LOOP); break;
+	case 1: val = SDR_READ(PESDR1_LOOP); break;
+	case 2: val = SDR_READ(PESDR2_LOOP); break;
 	}
 
-	utl_base = ioremap64(0xc10000000ull + 0x1000 * port, 0x100);
+	if (val & 0x1000)
+		printk(KERN_INFO "PCIE%d: link up\n", port);
+	else {
+		printk(KERN_WARNING "PCIE%d: link down %08x\n", port, val);
+		return -1;
+	}
 
 	/*
-	 * Set buffer allocations and then assert VRB and TXE.
+	 * Setup UTL registers - but only on rev. A!
+	 * Just leave rev. B with default settings.
 	 */
-	out_be32(utl_base + PEUTL_OUTTR,   0x08000000);
-	out_be32(utl_base + PEUTL_INTR,    0x02000000);
-	out_be32(utl_base + PEUTL_OPDBSZ,  0x10000000);
-	out_be32(utl_base + PEUTL_PBBSZ,   0x53000000);
-	out_be32(utl_base + PEUTL_IPHBSZ,  0x08000000);
-	out_be32(utl_base + PEUTL_IPDBSZ,  0x10000000);
-	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
-	out_be32(utl_base + PEUTL_PCTL,    0x80800066);
-
-	iounmap(utl_base);
+	if (core_rev == REV_A)
+		ppc440spe_setup_utl(port);
 
 	/*
 	 * We map PCI Express configuration access into the 512MB regions
+	 *
+	 * Rev. B is very strict about PLB real addressess and ranges
+	 * to be mapped for config space; it seems to only work with
+	 * 0xd_nnnn_nnnn range (the core hangs on config transaction
+	 * attempts when set otherwise), while rev. A only works with
+	 * 0xc_nnnn_nnnn.  So we use the following ranges:
+	 *
+	 * Rev. A:
 	 *     PCIE0: 0xc_4000_0000
 	 *     PCIE1: 0xc_8000_0000
 	 *     PCIE2: 0xc_c000_0000
+	 *
+	 * Rev. B:
+	 *     PCIE0: 0xd_0000_0000
+	 *     PCIE1: 0xd_2000_0000
+	 *     PCIE2: 0xd_4000_0000
 	 */
 	switch (port) {
 	case 0:
-		mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
-		mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+		if (core_rev == REV_A) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+		} else {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000);
+		}
 		mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
 		break;
 
 	case 1:
-		mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
-		mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+		if (core_rev == REV_A) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+		} else {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000);
+		}
 		mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
 		break;
 
 	case 2:
-		mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
-		mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+		if (core_rev == REV_A) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+		} else {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000);
+		}
 		mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
 		break;
 	}
@@ -336,18 +426,24 @@ int ppc440spe_init_pcie_rootport(int por
 	 */
 	switch (port) {
 	case 0:
-		if (!(SDR_READ(PESDR0_RCSSTS) & (1 << 16)))
+		if (!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) {
 			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+			return -1;
+		}
 		SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20);
 		break;
 	case 1:
-		if (!(SDR_READ(PESDR1_RCSSTS) & (1 << 16)))
-			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+		if (!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) {
+			printk(KERN_WARNING "PCIE1: VC0 not active\n");
+			return -1;
+		}
 		SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20);
 		break;
 	case 2:
-		if (!(SDR_READ(PESDR2_RCSSTS) & (1 << 16)))
-			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+		if (!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) {
+			printk(KERN_WARNING "PCIE2: VC0 not active\n");
+			return -1;
+		}
 		SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20);
 		break;
 	}
@@ -375,19 +471,42 @@ void ppc440spe_setup_pcie(struct pci_con
 {
 	void __iomem *mbase;
 
-	/*
-	 * Map 16MB, which is enough for 4 bits of bus #
-	 */
-	hose->cfg_data = ioremap64(0xc40000000ull + port * 0x40000000,
-				   1 << 24);
+	if (core_rev == REV_A) {
+		/*
+		 * Map 16MB, which is enough for 4 bits of bus #
+		 */
+		hose->cfg_data = ioremap64(0xc40000000ull + port * 0x40000000,
+					   1 << 24);
+
+		mbase = ioremap64(0xc50000000ull + port * 0x40000000, 0x1000);
+	} else {
+		/*
+		 * Rev. B is very strict about PLB real addressess and
+		 * sizes to be mapped for config space; the core hangs
+		 * on config transaction attempt if not set to
+		 * 0xd_0010_0000, 0xd_2010_0000, 0xd_4010_0000
+		 * respectively.
+		 */
+		hose->cfg_data = ioremap64(0xd00100000ull + port * 0x20000000,
+					   0x400);
+
+		/* for accessing Local Config space we need to set A[35] */
+		mbase = ioremap64(0xd10000000ull + port * 0x20000000, 0x400);
+	}
+
 	hose->ops = &pcie_pci_ops;
 
 	/*
 	 * Set bus numbers on our root port
 	 */
-	mbase = ioremap64(0xc50000000ull + port * 0x40000000, 4096);
-	out_8(mbase + PCI_PRIMARY_BUS, 0);
-	out_8(mbase + PCI_SECONDARY_BUS, 0);
+	if (core_rev == REV_A) {
+		out_8(mbase + PCI_PRIMARY_BUS, 0);
+		out_8(mbase + PCI_SECONDARY_BUS, 0);
+	} else {
+		out_8(mbase + PCI_PRIMARY_BUS, 0);
+		out_8(mbase + PCI_SECONDARY_BUS, 1);
+		out_8(mbase + PCI_SUBORDINATE_BUS, 1);
+	}
 
 	/*
 	 * Set up outbound translation to hose->mem_space from PLB
@@ -412,7 +531,6 @@ void ppc440spe_setup_pcie(struct pci_con
 		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
 		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
 		      ~(hose->mem_space.end - hose->mem_space.start) | 3);
-
 		break;
 	case 2:
 		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2),  0x0000000d);
-- 
1.4.3.2

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] [POWERPC] Add support for Rev. B of PowerPC 440SPe
  2006-11-13 17:55 [PATCH] [POWERPC] Add support for Rev. B of PowerPC 440SPe Roland Dreier
@ 2006-11-13 22:27 ` Wolfgang Denk
  2006-11-13 22:29   ` jhon scoot
  2006-11-13 22:31   ` Roland Dreier
  2006-11-13 22:31 ` [PATCH v2 -- fixed changelog] " Roland Dreier
  1 sibling, 2 replies; 11+ messages in thread
From: Wolfgang Denk @ 2006-11-13 22:27 UTC (permalink / raw)
  To: Roland Dreier; +Cc: linuxppc-embedded

In message <adalkmf44eu.fsf@cisco.com> you wrote:
> This is mostly updating the PCI Express code to work with the new core
> in the Rev. B chip, which unfortunately has different undocumented
> restrictions on the PLB addresses that can be used from the Rev. A core.
> 
> Also, when adding the cputable entry for 440SPe Rev. B, we need to
> adjust the entry for 440SP Rev. A so that it looks at more bits of the
> PVR.  The 440SPe Rev. B has PVR 53421891, which would have matched the
> old 440SP pattern of 53xxx891.
> 
> Signed-off-by: Roland Dreier <rolandd@cisco.com>

Just for the record:

This patch is _heavily_ borrowed on code by Rafal Jaworowski; see
http://www.denx.de/cgi-bin/gitweb.cgi?p=linux-2.6-denx.git;a=commit;h=30e3e3be8863902f508af74fdc61ec9b80756bc0

Please add correct attribution.

Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
"In Christianity neither morality nor religion come into contact with
reality at any point."                          - Friedrich Nietzsche

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] [POWERPC] Add support for Rev. B of PowerPC 440SPe
  2006-11-13 22:27 ` Wolfgang Denk
@ 2006-11-13 22:29   ` jhon scoot
  2006-11-13 22:31   ` Roland Dreier
  1 sibling, 0 replies; 11+ messages in thread
From: jhon scoot @ 2006-11-13 22:29 UTC (permalink / raw)
  To: wd, rdreier; +Cc: linuxppc-embedded

Roland did u are working on a settop box?  with PPC440


>From: Wolfgang Denk <wd@denx.de>
>To: Roland Dreier <rdreier@cisco.com>
>CC: linuxppc-embedded@ozlabs.org
>Subject: Re: [PATCH] [POWERPC] Add support for Rev. B of PowerPC 440SPe 
>Date: Mon, 13 Nov 2006 23:27:25 +0100
>
>In message <adalkmf44eu.fsf@cisco.com> you wrote:
> > This is mostly updating the PCI Express code to work with the new core
> > in the Rev. B chip, which unfortunately has different undocumented
> > restrictions on the PLB addresses that can be used from the Rev. A core.
> >
> > Also, when adding the cputable entry for 440SPe Rev. B, we need to
> > adjust the entry for 440SP Rev. A so that it looks at more bits of the
> > PVR.  The 440SPe Rev. B has PVR 53421891, which would have matched the
> > old 440SP pattern of 53xxx891.
> >
> > Signed-off-by: Roland Dreier <rolandd@cisco.com>
>
>Just for the record:
>
>This patch is _heavily_ borrowed on code by Rafal Jaworowski; see
>http://www.denx.de/cgi-bin/gitweb.cgi?p=linux-2.6-denx.git;a=commit;h=30e3e3be8863902f508af74fdc61ec9b80756bc0
>
>Please add correct attribution.
>
>Best regards,
>
>Wolfgang Denk
>
>--
>Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
>Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
>"In Christianity neither morality nor religion come into contact with
>reality at any point."                          - Friedrich Nietzsche
>_______________________________________________
>Linuxppc-embedded mailing list
>Linuxppc-embedded@ozlabs.org
>https://ozlabs.org/mailman/listinfo/linuxppc-embedded

_________________________________________________________________
Try Search Survival Kits: Fix up your home and better handle your cash with 
Live Search! 
http://imagine-windowslive.com/search/kits/default.aspx?kit=improve&locale=en-US&source=hmtagline

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] [POWERPC] Add support for Rev. B of PowerPC 440SPe
  2006-11-13 22:27 ` Wolfgang Denk
  2006-11-13 22:29   ` jhon scoot
@ 2006-11-13 22:31   ` Roland Dreier
  1 sibling, 0 replies; 11+ messages in thread
From: Roland Dreier @ 2006-11-13 22:31 UTC (permalink / raw)
  To: Wolfgang Denk; +Cc: linuxppc-embedded

 > This patch is _heavily_ borrowed on code by Rafal Jaworowski

Indeed -- I meant to add that to the change log and just forgot.
I will resend now.

On the other hand it might have been nice for you to submit this
upstream rather than letting it sit in your tree for months and
months...

 - R.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 -- fixed changelog] [POWERPC] Add support for Rev. B of PowerPC 440SPe
  2006-11-13 17:55 [PATCH] [POWERPC] Add support for Rev. B of PowerPC 440SPe Roland Dreier
  2006-11-13 22:27 ` Wolfgang Denk
@ 2006-11-13 22:31 ` Roland Dreier
  2006-11-14  9:01   ` Eugene Surovegin
  1 sibling, 1 reply; 11+ messages in thread
From: Roland Dreier @ 2006-11-13 22:31 UTC (permalink / raw)
  To: mporter; +Cc: linuxppc-embedded

This is mostly updating the PCI Express code to work with the new core
in the Rev. B chip, which unfortunately has different undocumented
restrictions on the PLB addresses that can be used from the Rev. A core.

Also, when adding the cputable entry for 440SPe Rev. B, we need to
adjust the entry for 440SP Rev. A so that it looks at more bits of the
PVR.  The 440SPe Rev. B has PVR 53421891, which would have matched the
old 440SP pattern of 53xxx891.

This is a cleaned up version of the original work done by Rafal
Jaworowski <raj@semihalf.com>, who actually suffered through figuring
out how to avoid the Rev. B chip locking up when using PCIe.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
---
Matt, please apply this version, which gives proper credit for the patch.

 arch/powerpc/kernel/cputable.c           |   21 ++-
 arch/ppc/platforms/4xx/davinci_sc.c      |    5 -
 arch/ppc/syslib/ppc440spe_pcie.c         |  258 ++++++++++++++++++++++--------
 drivers/infiniband/hw/mthca/mthca_main.c |    4 +-
 4 files changed, 206 insertions(+), 82 deletions(-)

diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index bfd499e..04559be 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1073,8 +1073,8 @@ #ifdef CONFIG_44x
 		.platform		= "ppc440",
 	},
 	{ /* 440SP Rev. A */
-		.pvr_mask		= 0xff000fff,
-		.pvr_value		= 0x53000891,
+		.pvr_mask		= 0xfff00fff,
+		.pvr_value		= 0x53200891,
 		.cpu_name		= "440SP Rev. A",
 		.cpu_features		= CPU_FTRS_44X,
 		.cpu_user_features	= COMMON_USER_BOOKE,
@@ -1083,9 +1083,20 @@ #ifdef CONFIG_44x
 		.platform		= "ppc440",
 	},
 	{ /* 440SPe Rev. A */
-		.pvr_mask		= 0xff000fff,
-		.pvr_value		= 0x53000890,
-		.cpu_name		= "440SPe Rev. A",
+		.pvr_mask               = 0xfff00fff,
+		.pvr_value              = 0x53400890,
+		.cpu_name               = "440SPe Rev. A",
+		.cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+			CPU_FTR_USE_TB,
+		.cpu_user_features      = COMMON_USER_BOOKE,
+		.icache_bsize           = 32,
+		.dcache_bsize           = 32,
+		.platform               = "ppc440",
+	},
+	{ /* 440SPe Rev. B */
+		.pvr_mask		= 0xfff00fff,
+		.pvr_value		= 0x53400891,
+		.cpu_name		= "440SPe Rev. B",
 		.cpu_features		= CPU_FTR_SPLIT_ID_CACHE |
 			CPU_FTR_USE_TB,
 		.cpu_user_features	= COMMON_USER_BOOKE,
diff --git a/arch/ppc/platforms/4xx/davinci_sc.c b/arch/ppc/platforms/4xx/davinci_sc.c
index 623988f..3dbedda 100644
--- a/arch/ppc/platforms/4xx/davinci_sc.c
+++ b/arch/ppc/platforms/4xx/davinci_sc.c
@@ -172,11 +172,6 @@ davinci_sc_setup_hoses(void)
 	char name[20];
 	int i;
 
-	if (0 && ppc440spe_init_pcie()) {
-		printk(KERN_WARNING "PPC440SPe PCI Express initialization failed\n");
-		return;
-	}
-
 	for (i = 0; i <= 2; ++i) {
 		if (!davinci_sc_pcie_card_present(i))
 			continue;
diff --git a/arch/ppc/syslib/ppc440spe_pcie.c b/arch/ppc/syslib/ppc440spe_pcie.c
index dd5d4b9..7ae14d2 100644
--- a/arch/ppc/syslib/ppc440spe_pcie.c
+++ b/arch/ppc/syslib/ppc440spe_pcie.c
@@ -19,16 +19,23 @@ #include <asm/ibm44x.h>
 
 #include "ppc440spe_pcie.h"
 
+static enum {
+	REV_A,
+	REV_B
+} core_rev;
+
 static int
 pcie_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
 		     int len, u32 *val)
 {
 	struct pci_controller *hose = bus->sysdata;
 
-	if (PCI_SLOT(devfn) != 1)
+	/* 440SPE implements only one function per port */
+	if (PCI_SLOT(devfn) != 1 || PCI_FUNC(devfn) != 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	offset += devfn << 12;
+	if (core_rev == REV_A)
+		offset += devfn << 12;
 
 	/*
 	 * Note: the caller has already checked that offset is
@@ -57,10 +64,11 @@ pcie_write_config(struct pci_bus *bus, u
 {
 	struct pci_controller *hose = bus->sysdata;
 
-	if (PCI_SLOT(devfn) != 1)
+	if (PCI_SLOT(devfn) != 1 || PCI_FUNC(devfn) != 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	offset += devfn << 12;
+	if (core_rev == REV_A)
+		offset += devfn << 12;
 
 	switch (len) {
 	case 1:
@@ -153,6 +161,20 @@ static void check_error(void)
  */
 int ppc440spe_init_pcie(void)
 {
+	int i;
+
+	switch (PVR_REV(mfspr(SPRN_PVR))) {
+	case 0x1890: core_rev = REV_A; break;
+	case 0x1891: core_rev = REV_B; break;
+	default:
+		printk(KERN_ERR "PCIE: Unknown PVR rev. %lx\n",
+		       PVR_REV(mfspr(SPRN_PVR)));
+		return -1;
+	}
+
+	printk(KERN_INFO "PCIE: core rev %c detected\n",
+	       core_rev == REV_A ? 'A' : 'B');
+
 	/* Set PLL clock receiver to LVPECL */
 	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28);
 
@@ -168,21 +190,78 @@ int ppc440spe_init_pcie(void)
 	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
 	udelay(3);
 
+	for (i = 0; i < 100; ++i) {
+		if (SDR_READ(PESDR0_PLLLCT3) & 0x10000000)
+			goto pll_ok;
+
+		udelay(1);
+	}
+
+	printk(KERN_INFO "PCIE: VCO output not locked: %x\n",
+	       SDR_READ(PESDR0_PLLLCT3));
+	return -1;
+
+pll_ok:
 	return 0;
 }
 
+static void ppc440spe_setup_utl(int port)
+{
+	void __iomem *utl_base;
+
+	/*
+	 * Map UTL registers at 0xc_1000_0n00
+	 */
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
+		break;
+
+	case 1:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
+		break;
+
+	case 2:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+	}
+
+	utl_base = ioremap64(0xc10000000ull + 0x1000 * port, 0x100);
+
+	/*
+	 * Set buffer allocations and then assert VRB and TXE.
+	 */
+	out_be32(utl_base + PEUTL_OUTTR,   0x08000000);
+	out_be32(utl_base + PEUTL_INTR,    0x02000000);
+	out_be32(utl_base + PEUTL_OPDBSZ,  0x10000000);
+	out_be32(utl_base + PEUTL_PBBSZ,   0x53000000);
+	out_be32(utl_base + PEUTL_IPHBSZ,  0x08000000);
+	out_be32(utl_base + PEUTL_IPDBSZ,  0x10000000);
+	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+	out_be32(utl_base + PEUTL_PCTL,    0x80800066);
+
+	iounmap(utl_base);
+}
+
 int ppc440spe_init_pcie_rootport(int port)
 {
 	static int core_init;
-	void __iomem *utl_base;
 	u32 val = 0;
 	int i;
 
 	if (!core_init) {
-		++core_init;
 		i = ppc440spe_init_pcie();
 		if (i)
 			return i;
+		++core_init;
 	}
 
 	/*
@@ -193,13 +272,19 @@ int ppc440spe_init_pcie_rootport(int por
 	 * - Set up UTL configuration.
 	 * - Increase SERDES drive strength to levels suggested by AMCC.
 	 * - De-assert RSTPYN, RSTDL and RSTGU.
+	 *
+	 * For rev. B chips, we don't set PESDRn_UTLSET2, but just
+	 * leave it with default setting 0x11310000. The register has
+	 * new fields, PESDRn_UTLSET2[LKINE] in particular: clearing
+	 * it leads to a PCIe core hang.
 	 */
 	switch (port) {
 	case 0:
 		SDR_WRITE(PESDR0_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X8 << 12);
 
 		SDR_WRITE(PESDR0_UTLSET1, 0x21222222);
-		SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
+		if (core_rev == REV_A)
+			SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
 
 		SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000);
 		SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000);
@@ -218,7 +303,8 @@ int ppc440spe_init_pcie_rootport(int por
 		SDR_WRITE(PESDR1_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
 
 		SDR_WRITE(PESDR1_UTLSET1, 0x21222222);
-		SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
+		if (core_rev == REV_A)
+			SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
 
 		SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000);
 		SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000);
@@ -233,7 +319,8 @@ int ppc440spe_init_pcie_rootport(int por
 		SDR_WRITE(PESDR2_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
 
 		SDR_WRITE(PESDR2_UTLSET1, 0x21222222);
-		SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
+		if (core_rev == REV_A)
+			SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
 
 		SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000);
 		SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
@@ -255,78 +342,81 @@ int ppc440spe_init_pcie_rootport(int por
 
 	if (!(val & (1 << 20)))
 		printk(KERN_INFO "PCIE%d: PGRST inactive\n", port);
-	else
-		printk(KERN_WARNING "PGRST for PCIE%d failed %08x\n", port, val);
-
-	switch (port) {
-	case 0: printk(KERN_INFO "PCIE0: LOOP %08x\n", SDR_READ(PESDR0_LOOP)); break;
-	case 1: printk(KERN_INFO "PCIE1: LOOP %08x\n", SDR_READ(PESDR1_LOOP)); break;
-	case 2: printk(KERN_INFO "PCIE2: LOOP %08x\n", SDR_READ(PESDR2_LOOP)); break;
+	else {
+		printk(KERN_WARNING "PCIE%d: PGRST failed %08x\n", port, val);
+		return -1;
 	}
 
-	/*
-	 * Map UTL registers at 0xc_1000_0n00
-	 */
 	switch (port) {
-	case 0:
-		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
-		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000);
-		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
-		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
-		break;
-
-	case 1:
-		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
-		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000);
-		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
-		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
-		break;
-
-	case 2:
-		mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
-		mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000);
-		mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
-		mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+	case 0: val = SDR_READ(PESDR0_LOOP); break;
+	case 1: val = SDR_READ(PESDR1_LOOP); break;
+	case 2: val = SDR_READ(PESDR2_LOOP); break;
 	}
 
-	utl_base = ioremap64(0xc10000000ull + 0x1000 * port, 0x100);
+	if (val & 0x1000)
+		printk(KERN_INFO "PCIE%d: link up\n", port);
+	else {
+		printk(KERN_WARNING "PCIE%d: link down %08x\n", port, val);
+		return -1;
+	}
 
 	/*
-	 * Set buffer allocations and then assert VRB and TXE.
+	 * Setup UTL registers - but only on rev. A!
+	 * Just leave rev. B with default settings.
 	 */
-	out_be32(utl_base + PEUTL_OUTTR,   0x08000000);
-	out_be32(utl_base + PEUTL_INTR,    0x02000000);
-	out_be32(utl_base + PEUTL_OPDBSZ,  0x10000000);
-	out_be32(utl_base + PEUTL_PBBSZ,   0x53000000);
-	out_be32(utl_base + PEUTL_IPHBSZ,  0x08000000);
-	out_be32(utl_base + PEUTL_IPDBSZ,  0x10000000);
-	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
-	out_be32(utl_base + PEUTL_PCTL,    0x80800066);
-
-	iounmap(utl_base);
+	if (core_rev == REV_A)
+		ppc440spe_setup_utl(port);
 
 	/*
 	 * We map PCI Express configuration access into the 512MB regions
+	 *
+	 * Rev. B is very strict about PLB real addressess and ranges
+	 * to be mapped for config space; it seems to only work with
+	 * 0xd_nnnn_nnnn range (the core hangs on config transaction
+	 * attempts when set otherwise), while rev. A only works with
+	 * 0xc_nnnn_nnnn.  So we use the following ranges:
+	 *
+	 * Rev. A:
 	 *     PCIE0: 0xc_4000_0000
 	 *     PCIE1: 0xc_8000_0000
 	 *     PCIE2: 0xc_c000_0000
+	 *
+	 * Rev. B:
+	 *     PCIE0: 0xd_0000_0000
+	 *     PCIE1: 0xd_2000_0000
+	 *     PCIE2: 0xd_4000_0000
 	 */
 	switch (port) {
 	case 0:
-		mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
-		mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+		if (core_rev == REV_A) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+		} else {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000);
+		}
 		mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
 		break;
 
 	case 1:
-		mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
-		mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+		if (core_rev == REV_A) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+		} else {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000);
+		}
 		mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
 		break;
 
 	case 2:
-		mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
-		mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+		if (core_rev == REV_A) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+		} else {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000);
+		}
 		mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
 		break;
 	}
@@ -336,18 +426,24 @@ int ppc440spe_init_pcie_rootport(int por
 	 */
 	switch (port) {
 	case 0:
-		if (!(SDR_READ(PESDR0_RCSSTS) & (1 << 16)))
+		if (!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) {
 			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+			return -1;
+		}
 		SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20);
 		break;
 	case 1:
-		if (!(SDR_READ(PESDR1_RCSSTS) & (1 << 16)))
-			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+		if (!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) {
+			printk(KERN_WARNING "PCIE1: VC0 not active\n");
+			return -1;
+		}
 		SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20);
 		break;
 	case 2:
-		if (!(SDR_READ(PESDR2_RCSSTS) & (1 << 16)))
-			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+		if (!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) {
+			printk(KERN_WARNING "PCIE2: VC0 not active\n");
+			return -1;
+		}
 		SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20);
 		break;
 	}
@@ -375,19 +471,42 @@ void ppc440spe_setup_pcie(struct pci_con
 {
 	void __iomem *mbase;
 
-	/*
-	 * Map 16MB, which is enough for 4 bits of bus #
-	 */
-	hose->cfg_data = ioremap64(0xc40000000ull + port * 0x40000000,
-				   1 << 24);
+	if (core_rev == REV_A) {
+		/*
+		 * Map 16MB, which is enough for 4 bits of bus #
+		 */
+		hose->cfg_data = ioremap64(0xc40000000ull + port * 0x40000000,
+					   1 << 24);
+
+		mbase = ioremap64(0xc50000000ull + port * 0x40000000, 0x1000);
+	} else {
+		/*
+		 * Rev. B is very strict about PLB real addressess and
+		 * sizes to be mapped for config space; the core hangs
+		 * on config transaction attempt if not set to
+		 * 0xd_0010_0000, 0xd_2010_0000, 0xd_4010_0000
+		 * respectively.
+		 */
+		hose->cfg_data = ioremap64(0xd00100000ull + port * 0x20000000,
+					   0x400);
+
+		/* for accessing Local Config space we need to set A[35] */
+		mbase = ioremap64(0xd10000000ull + port * 0x20000000, 0x400);
+	}
+
 	hose->ops = &pcie_pci_ops;
 
 	/*
 	 * Set bus numbers on our root port
 	 */
-	mbase = ioremap64(0xc50000000ull + port * 0x40000000, 4096);
-	out_8(mbase + PCI_PRIMARY_BUS, 0);
-	out_8(mbase + PCI_SECONDARY_BUS, 0);
+	if (core_rev == REV_A) {
+		out_8(mbase + PCI_PRIMARY_BUS, 0);
+		out_8(mbase + PCI_SECONDARY_BUS, 0);
+	} else {
+		out_8(mbase + PCI_PRIMARY_BUS, 0);
+		out_8(mbase + PCI_SECONDARY_BUS, 1);
+		out_8(mbase + PCI_SUBORDINATE_BUS, 1);
+	}
 
 	/*
 	 * Set up outbound translation to hose->mem_space from PLB
@@ -412,7 +531,6 @@ void ppc440spe_setup_pcie(struct pci_con
 		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
 		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
 		      ~(hose->mem_space.end - hose->mem_space.start) | 3);
-
 		break;
 	case 2:
 		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2),  0x0000000d);
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 47ea021..c499b90 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -87,9 +87,9 @@ static const char mthca_version[] __devi
 	DRV_VERSION " (" DRV_RELDATE ")\n";
 
 static struct mthca_profile default_profile = {
-	.num_qp		   = 1 << 16,
+	.num_qp		   = 1 << 11,
 	.rdb_per_qp	   = 4,
-	.num_cq		   = 1 << 16,
+	.num_cq		   = 1 << 11,
 	.num_mcg	   = 1 << 13,
 	.num_mpt	   = 1 << 17,
 	.num_mtt	   = 1 << 20,
-- 
1.4.3.2

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 -- fixed changelog] [POWERPC] Add support for Rev. B of PowerPC 440SPe
  2006-11-13 22:31 ` [PATCH v2 -- fixed changelog] " Roland Dreier
@ 2006-11-14  9:01   ` Eugene Surovegin
  2006-11-15 22:29     ` Roland Dreier
  0 siblings, 1 reply; 11+ messages in thread
From: Eugene Surovegin @ 2006-11-14  9:01 UTC (permalink / raw)
  To: Roland Dreier; +Cc: linuxppc-embedded

On Mon, Nov 13, 2006 at 02:31:51PM -0800, Roland Dreier wrote:
> This is mostly updating the PCI Express code to work with the new core
> in the Rev. B chip, which unfortunately has different undocumented
> restrictions on the PLB addresses that can be used from the Rev. A core.
> 
> Also, when adding the cputable entry for 440SPe Rev. B, we need to
> adjust the entry for 440SP Rev. A so that it looks at more bits of the
> PVR.  The 440SPe Rev. B has PVR 53421891, which would have matched the
> old 440SP pattern of 53xxx891.
> 
> This is a cleaned up version of the original work done by Rafal
> Jaworowski <raj@semihalf.com>, who actually suffered through figuring
> out how to avoid the Rev. B chip locking up when using PCIe.
> 
> Signed-off-by: Roland Dreier <rolandd@cisco.com>

[snip]

> +static void ppc440spe_setup_utl(int port)
> +{
> +	void __iomem *utl_base;
> +
> +	/*
> +	 * Map UTL registers at 0xc_1000_0n00
> +	 */
> +	switch (port) {
> +	case 0:
> +		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
> +		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000);
> +		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
> +		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
> +		break;
> +
> +	case 1:
> +		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
> +		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000);
> +		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
> +		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
> +		break;
> +
> +	case 2:
> +		mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
> +		mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000);
> +		mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
> +		mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
> +	}

Can this be collapsed into 4 writes instead of 12? DCR accessors 
have supported run-time specified parameters for quite some time.

[snip]

> +	case 0: val = SDR_READ(PESDR0_LOOP); break;
> +	case 1: val = SDR_READ(PESDR1_LOOP); break;
> +	case 2: val = SDR_READ(PESDR2_LOOP); break;

I'm curious, why do we need a switch here? 
SDR_READ() also supports run-time parameters.


[snip]

>  	switch (port) {
>  	case 0:
> -		mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
> -		mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
> +		if (core_rev == REV_A) {
> +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
> +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
> +		} else {
> +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d);
> +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000);
> +		}
>  		mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
>  		break;
>  
>  	case 1:
> -		mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
> -		mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
> +		if (core_rev == REV_A) {
> +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
> +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
> +		} else {
> +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d);
> +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000);
> +		}
>  		mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
>  		break;
>  
>  	case 2:
> -		mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
> -		mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
> +		if (core_rev == REV_A) {
> +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
> +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
> +		} else {
> +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d);
> +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000);
> +		}
>  		mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
>  		break;
>  	}


Can we get rid of this switch as well?

There are other places like this in the patch but I think you got my 
idea :).

-- 
Eugene

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 -- fixed changelog] [POWERPC] Add support for Rev. B of PowerPC 440SPe
  2006-11-14  9:01   ` Eugene Surovegin
@ 2006-11-15 22:29     ` Roland Dreier
  2006-11-16  1:14       ` Eugene Surovegin
  0 siblings, 1 reply; 11+ messages in thread
From: Roland Dreier @ 2006-11-15 22:29 UTC (permalink / raw)
  To: mporter; +Cc: linuxppc-embedded

 > Can we get rid of this switch as well?
 > 
 > There are other places like this in the patch but I think you got my 
 > idea :).

Makes sense -- I'll rework the patch to cut down on the code
duplication (which is already there in my code that went upstream).  I
think there have to be switches (or equivalently, look-up tables)
since there's no regularity in where the DCRs/SDRs for the different
PCIe ports are.

 - R.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 -- fixed changelog] [POWERPC] Add support for Rev. B of PowerPC 440SPe
  2006-11-15 22:29     ` Roland Dreier
@ 2006-11-16  1:14       ` Eugene Surovegin
  2006-11-16  1:20         ` Roland Dreier
  0 siblings, 1 reply; 11+ messages in thread
From: Eugene Surovegin @ 2006-11-16  1:14 UTC (permalink / raw)
  To: Roland Dreier; +Cc: linuxppc-embedded

On Wed, Nov 15, 2006 at 02:29:51PM -0800, Roland Dreier wrote:

[snip]

> I think there have to be switches (or equivalently, look-up tables)
> since there's no regularity in where the DCRs/SDRs for the different
> PCIe ports are.

Uhh, I was afraid you were gonna say this. HW guys don't make our life 
easier :).

I think look-up tables are fine. It's not a fast path, is it?

-- 
Eugene

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 -- fixed changelog] [POWERPC] Add support for Rev. B of PowerPC 440SPe
  2006-11-16  1:14       ` Eugene Surovegin
@ 2006-11-16  1:20         ` Roland Dreier
  2006-11-16  1:26           ` Eugene Surovegin
  0 siblings, 1 reply; 11+ messages in thread
From: Roland Dreier @ 2006-11-16  1:20 UTC (permalink / raw)
  To: mporter; +Cc: linuxppc-embedded

 > I think look-up tables are fine. It's not a fast path, is it?

Nope, that would be fine.  I'll definitely cut down on the code
duplication -- I'm just not sure what will end up being cleanest.  I
don't see that much difference between a switch and a look-up table
for finding the base DCR index for a particular port.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 -- fixed changelog] [POWERPC] Add support for Rev. B of PowerPC 440SPe
  2006-11-16  1:20         ` Roland Dreier
@ 2006-11-16  1:26           ` Eugene Surovegin
  2006-11-16  1:36             ` Roland Dreier
  0 siblings, 1 reply; 11+ messages in thread
From: Eugene Surovegin @ 2006-11-16  1:26 UTC (permalink / raw)
  To: Roland Dreier; +Cc: linuxppc-embedded

On Wed, Nov 15, 2006 at 05:20:28PM -0800, Roland Dreier wrote:
>  > I think look-up tables are fine. It's not a fast path, is it?
> 
> Nope, that would be fine.  I'll definitely cut down on the code
> duplication -- I'm just not sure what will end up being cleanest.  I
> don't see that much difference between a switch and a look-up table
> for finding the base DCR index for a particular port.

OK, I was just wanted to make sure you were aware that mfdcr/mtdcr 
supported run-time specified DCR number (from that code it wasn't 
clear).

-- 
Eugene

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 -- fixed changelog] [POWERPC] Add support for Rev. B of PowerPC 440SPe
  2006-11-16  1:26           ` Eugene Surovegin
@ 2006-11-16  1:36             ` Roland Dreier
  0 siblings, 0 replies; 11+ messages in thread
From: Roland Dreier @ 2006-11-16  1:36 UTC (permalink / raw)
  To: mporter; +Cc: linuxppc-embedded

 > OK, I was just wanted to make sure you were aware that mfdcr/mtdcr 
 > supported run-time specified DCR number (from that code it wasn't 
 > clear).

I actually didn't until you pointed it out -- mfdcr looks enough like
assembly to confuse my small brain, and I guess I'm way behind the
times (since the support for run-time numbers predates the beginning
of git history, so it's been a _long_ time).

 - R.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2006-11-16  1:36 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-13 17:55 [PATCH] [POWERPC] Add support for Rev. B of PowerPC 440SPe Roland Dreier
2006-11-13 22:27 ` Wolfgang Denk
2006-11-13 22:29   ` jhon scoot
2006-11-13 22:31   ` Roland Dreier
2006-11-13 22:31 ` [PATCH v2 -- fixed changelog] " Roland Dreier
2006-11-14  9:01   ` Eugene Surovegin
2006-11-15 22:29     ` Roland Dreier
2006-11-16  1:14       ` Eugene Surovegin
2006-11-16  1:20         ` Roland Dreier
2006-11-16  1:26           ` Eugene Surovegin
2006-11-16  1:36             ` Roland Dreier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).