[PATCH 1/2] Adding PCI-E support for PowerPC 460SX based SOC.

Josh Boyer jwboyer at linux.vnet.ibm.com
Tue Dec 22 22:49:40 EST 2009


On Tue, Dec 22, 2009 at 12:49:41AM -0800, tmarri at amcc.com wrote:
>From: Tirumala Marri <tmarri at amcc.com>
>
>
>Signed-off-by: Tirumala Marri <tmarri at amcc.com>

Acked-by: Josh Boyer <jwboyer at linux.vnet.ibm.com

Ben, do you want to take this through your tree or mine?

josh

>---
>Kerenl:2.6.33-rc1
>Testing: This patch has been tested on 460SX based redwood board . One board configured as  
>root complex and other as Endpoint. Checked for link up . From root complex lspci command
>shows the end point. Also programmed IO tested using loop back as well as board to board.
>---
> arch/powerpc/boot/dts/redwood.dts |  122 +++++++++++++++++++++++++++++++++++++
> arch/powerpc/sysdev/ppc4xx_pci.c  |  119 ++++++++++++++++++++++++++++++++++++
> arch/powerpc/sysdev/ppc4xx_pci.h  |   58 +++++++++++++++++
> 3 files changed, 299 insertions(+), 0 deletions(-)
>
>diff --git a/arch/powerpc/boot/dts/redwood.dts b/arch/powerpc/boot/dts/redwood.dts
>index d2af32e..81636c0 100644
>--- a/arch/powerpc/boot/dts/redwood.dts
>+++ b/arch/powerpc/boot/dts/redwood.dts
>@@ -234,10 +234,132 @@
> 				has-inverted-stacr-oc;
> 				has-new-stacr-staopc;
> 			};
>+		};
>+		PCIE0: pciex at d00000000 {
>+			device_type = "pci";
>+			#interrupt-cells = <1>;
>+			#size-cells = <2>;
>+			#address-cells = <3>;
>+			compatible = "ibm,plb-pciex-460sx", "ibm,plb-pciex";
>+			primary;
>+			port = <0x0>; /* port number */
>+			reg = <0x0000000d 0x00000000 0x20000000	/* Config space access */
>+			       0x0000000c 0x10000000 0x00001000>;	/* Registers */
>+			dcr-reg = <0x100 0x020>;
>+			sdr-base = <0x300>;
>+
>+			/* Outbound ranges, one memory and one IO,
>+			 * later cannot be changed
>+			 */
>+			ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000
>+				  0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>;
>+
>+			/* Inbound 2GB range starting at 0 */
>+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
> 
>+			/* This drives busses 10 to 0x1f */
>+			bus-range = <0x10 0x1f>;
>+
>+			/* Legacy interrupts (note the weird polarity, the bridge seems
>+			 * to invert PCIe legacy interrupts).
>+			 * We are de-swizzling here because the numbers are actually for
>+			 * port of the root complex virtual P2P bridge. But I want
>+			 * to avoid putting a node for it in the tree, so the numbers
>+			 * below are basically de-swizzled numbers.
>+			 * The real slot is on idsel 0, so the swizzling is 1:1
>+			 */
>+			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
>+			interrupt-map = <
>+				0x0 0x0 0x0 0x1 &UIC3 0x0 0x4 /* swizzled int A */
>+				0x0 0x0 0x0 0x2 &UIC3 0x1 0x4 /* swizzled int B */
>+				0x0 0x0 0x0 0x3 &UIC3 0x2 0x4 /* swizzled int C */
>+				0x0 0x0 0x0 0x4 &UIC3 0x3 0x4 /* swizzled int D */>;
>+		};
>+
>+		PCIE1: pciex at d20000000 {
>+			device_type = "pci";
>+			#interrupt-cells = <1>;
>+			#size-cells = <2>;
>+			#address-cells = <3>;
>+			compatible = "ibm,plb-pciex-460sx", "ibm,plb-pciex";
>+			primary;
>+			port = <0x1>; /* port number */
>+			reg = <0x0000000d 0x20000000 0x20000000	/* Config space access */
>+			       0x0000000c 0x10001000 0x00001000>;	/* Registers */
>+			dcr-reg = <0x120 0x020>;
>+			sdr-base = <0x340>;
>+
>+			/* Outbound ranges, one memory and one IO,
>+			 * later cannot be changed
>+			 */
>+			ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000
>+				  0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>;
>+
>+			/* Inbound 2GB range starting at 0 */
>+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
>+
>+			/* This drives busses 10 to 0x1f */
>+			bus-range = <0x20 0x2f>;
>+
>+			/* Legacy interrupts (note the weird polarity, the bridge seems
>+			 * to invert PCIe legacy interrupts).
>+			 * We are de-swizzling here because the numbers are actually for
>+			 * port of the root complex virtual P2P bridge. But I want
>+			 * to avoid putting a node for it in the tree, so the numbers
>+			 * below are basically de-swizzled numbers.
>+			 * The real slot is on idsel 0, so the swizzling is 1:1
>+			 */
>+			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
>+			interrupt-map = <
>+				0x0 0x0 0x0 0x1 &UIC3 0x4 0x4 /* swizzled int A */
>+				0x0 0x0 0x0 0x2 &UIC3 0x5 0x4 /* swizzled int B */
>+				0x0 0x0 0x0 0x3 &UIC3 0x6 0x4 /* swizzled int C */
>+				0x0 0x0 0x0 0x4 &UIC3 0x7 0x4 /* swizzled int D */>;
>+		};
>+
>+		PCIE2: pciex at d40000000 {
>+			device_type = "pci";
>+			#interrupt-cells = <1>;
>+			#size-cells = <2>;
>+			#address-cells = <3>;
>+			compatible = "ibm,plb-pciex-460sx", "ibm,plb-pciex";
>+			primary;
>+			port = <0x2>; /* port number */
>+			reg = <0x0000000d 0x40000000 0x20000000	/* Config space access */
>+			       0x0000000c 0x10002000 0x00001000>;	/* Registers */
>+			dcr-reg = <0x140 0x020>;
>+			sdr-base = <0x370>;
>+
>+			/* Outbound ranges, one memory and one IO,
>+			 * later cannot be changed
>+			 */
>+			ranges = <0x02000000 0x00000000 0x80000000 0x0000000f 0x00000000 0x00000000 0x80000000
>+				  0x01000000 0x00000000 0x00000000 0x0000000f 0x80020000 0x00000000 0x00010000>;
>+
>+			/* Inbound 2GB range starting at 0 */
>+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
>+
>+			/* This drives busses 10 to 0x1f */
>+			bus-range = <0x30 0x3f>;
>+
>+			/* Legacy interrupts (note the weird polarity, the bridge seems
>+			 * to invert PCIe legacy interrupts).
>+			 * We are de-swizzling here because the numbers are actually for
>+			 * port of the root complex virtual P2P bridge. But I want
>+			 * to avoid putting a node for it in the tree, so the numbers
>+			 * below are basically de-swizzled numbers.
>+			 * The real slot is on idsel 0, so the swizzling is 1:1
>+			 */
>+			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
>+			interrupt-map = <
>+				0x0 0x0 0x0 0x1 &UIC3 0x8 0x4 /* swizzled int A */
>+				0x0 0x0 0x0 0x2 &UIC3 0x9 0x4 /* swizzled int B */
>+				0x0 0x0 0x0 0x3 &UIC3 0xa 0x4 /* swizzled int C */
>+				0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>;
> 		};
> 
> 	};
>+
> 	chosen {
> 		linux,stdout-path = "/plb/opb/serial at ef600200";
> 	};
>diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
>index 6ff9d71..64cd020 100644
>--- a/arch/powerpc/sysdev/ppc4xx_pci.c
>+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
>@@ -972,6 +972,123 @@ static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
> 	.setup_utl	= ppc460ex_pciex_init_utl,
> };
> 
>+static int __init ppc460sx_pciex_core_init(struct device_node *np)
>+{
>+	/* HSS drive amplitude */
>+	mtdcri(SDR0, PESDR0_460SX_HSSL0DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL1DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL2DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL3DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL4DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL5DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL6DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL7DAMP, 0xB9843211);
>+
>+	mtdcri(SDR0, PESDR1_460SX_HSSL0DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR1_460SX_HSSL1DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR1_460SX_HSSL2DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR1_460SX_HSSL3DAMP, 0xB9843211);
>+
>+	mtdcri(SDR0, PESDR2_460SX_HSSL0DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR2_460SX_HSSL1DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR2_460SX_HSSL2DAMP, 0xB9843211);
>+	mtdcri(SDR0, PESDR2_460SX_HSSL3DAMP, 0xB9843211);
>+
>+	/* HSS TX pre-emphasis */
>+	mtdcri(SDR0, PESDR0_460SX_HSSL0COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL1COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL2COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL3COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL4COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL5COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL6COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR0_460SX_HSSL7COEFA, 0xDCB98987);
>+
>+	mtdcri(SDR0, PESDR1_460SX_HSSL0COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR1_460SX_HSSL1COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR1_460SX_HSSL2COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR1_460SX_HSSL3COEFA, 0xDCB98987);
>+
>+	mtdcri(SDR0, PESDR2_460SX_HSSL0COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR2_460SX_HSSL1COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR2_460SX_HSSL2COEFA, 0xDCB98987);
>+	mtdcri(SDR0, PESDR2_460SX_HSSL3COEFA, 0xDCB98987);
>+
>+	/* HSS TX calibration control */
>+	mtdcri(SDR0, PESDR0_460SX_HSSL1CALDRV, 0x22222222);
>+	mtdcri(SDR0, PESDR1_460SX_HSSL1CALDRV, 0x22220000);
>+	mtdcri(SDR0, PESDR2_460SX_HSSL1CALDRV, 0x22220000);
>+
>+	/* HSS TX slew control */
>+	mtdcri(SDR0, PESDR0_460SX_HSSSLEW, 0xFFFFFFFF);
>+	mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);
>+	mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000);
>+
>+	udelay(100);
>+
>+	/* De-assert PLLRESET */
>+	dcri_clrset(SDR0, PESDR0_PLLLCT2, 0x00000100, 0);
>+
>+	/* Reset DL, UTL, GPL before configuration */
>+	mtdcri(SDR0, PESDR0_460SX_RCSSET,
>+			PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
>+	mtdcri(SDR0, PESDR1_460SX_RCSSET,
>+			PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
>+	mtdcri(SDR0, PESDR2_460SX_RCSSET,
>+			PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
>+
>+	udelay(100);
>+
>+	/*
>+	 * If bifurcation is not enabled, u-boot would have disabled the
>+	 * third PCIe port
>+	 */
>+	if (((mfdcri(SDR0, PESDR1_460SX_HSSCTLSET) & 0x00000001) ==
>+				0x00000001)) {
>+		printk(KERN_INFO "PCI: PCIE bifurcation setup successfully.\n");
>+		printk(KERN_INFO "PCI: Total 3 PCIE ports are present\n");
>+		return 3;
>+	}
>+
>+	printk(KERN_INFO "PCI: Total 2 PCIE ports are present\n");
>+	return 2;
>+}
>+
>+static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
>+{
>+
>+	if (port->endpoint)
>+		dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
>+				0x01000000, 0);
>+	else
>+		dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
>+				0, 0x01000000);
>+
>+	/*Gen-1*/
>+	mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000);
>+
>+	dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
>+			(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),
>+			PESDRx_RCSSET_RSTPYN);
>+
>+	port->has_ibpre = 1;
>+
>+	return 0;
>+}
>+
>+static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
>+{
>+	/* Max 128 Bytes */
>+	out_be32 (port->utl_base + PEUTL_PBBSZ,   0x00000000);
>+	return 0;
>+}
>+
>+static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
>+	.core_init	= ppc460sx_pciex_core_init,
>+	.port_init_hw	= ppc460sx_pciex_init_port_hw,
>+	.setup_utl	= ppc460sx_pciex_init_utl,
>+};
>+
> #endif /* CONFIG_44x */
> 
> #ifdef CONFIG_40x
>@@ -1087,6 +1204,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
> 	}
> 	if (of_device_is_compatible(np, "ibm,plb-pciex-460ex"))
> 		ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops;
>+	if (of_device_is_compatible(np, "ibm,plb-pciex-460sx"))
>+		ppc4xx_pciex_hwops = &ppc460sx_pcie_hwops;
> #endif /* CONFIG_44x    */
> #ifdef CONFIG_40x
> 	if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
>diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h
>index d04e40b..56d9e5d 100644
>--- a/arch/powerpc/sysdev/ppc4xx_pci.h
>+++ b/arch/powerpc/sysdev/ppc4xx_pci.h
>@@ -324,6 +324,64 @@
> #define PESDR0_460EX_IHS2		0x036D
> 
> /*
>+ * 460SX addtional DCRs
>+ */
>+#define PESDRn_460SX_RCEI		0x02
>+
>+#define PESDR0_460SX_HSSL0DAMP		0x320
>+#define PESDR0_460SX_HSSL1DAMP		0x321
>+#define PESDR0_460SX_HSSL2DAMP		0x322
>+#define PESDR0_460SX_HSSL3DAMP		0x323
>+#define PESDR0_460SX_HSSL4DAMP		0x324
>+#define PESDR0_460SX_HSSL5DAMP		0x325
>+#define PESDR0_460SX_HSSL6DAMP		0x326
>+#define PESDR0_460SX_HSSL7DAMP		0x327
>+
>+#define PESDR1_460SX_HSSL0DAMP		0x354
>+#define PESDR1_460SX_HSSL1DAMP		0x355
>+#define PESDR1_460SX_HSSL2DAMP		0x356
>+#define PESDR1_460SX_HSSL3DAMP		0x357
>+
>+#define PESDR2_460SX_HSSL0DAMP		0x384
>+#define PESDR2_460SX_HSSL1DAMP		0x385
>+#define PESDR2_460SX_HSSL2DAMP		0x386
>+#define PESDR2_460SX_HSSL3DAMP		0x387
>+
>+#define PESDR0_460SX_HSSL0COEFA		0x328
>+#define PESDR0_460SX_HSSL1COEFA		0x329
>+#define PESDR0_460SX_HSSL2COEFA		0x32A
>+#define PESDR0_460SX_HSSL3COEFA		0x32B
>+#define PESDR0_460SX_HSSL4COEFA		0x32C
>+#define PESDR0_460SX_HSSL5COEFA		0x32D
>+#define PESDR0_460SX_HSSL6COEFA		0x32E
>+#define PESDR0_460SX_HSSL7COEFA		0x32F
>+
>+#define PESDR1_460SX_HSSL0COEFA		0x358
>+#define PESDR1_460SX_HSSL1COEFA		0x359
>+#define PESDR1_460SX_HSSL2COEFA		0x35A
>+#define PESDR1_460SX_HSSL3COEFA		0x35B
>+
>+#define PESDR2_460SX_HSSL0COEFA		0x388
>+#define PESDR2_460SX_HSSL1COEFA		0x389
>+#define PESDR2_460SX_HSSL2COEFA		0x38A
>+#define PESDR2_460SX_HSSL3COEFA		0x38B
>+
>+#define PESDR0_460SX_HSSL1CALDRV	0x339
>+#define PESDR1_460SX_HSSL1CALDRV	0x361
>+#define PESDR2_460SX_HSSL1CALDRV	0x391
>+
>+#define PESDR0_460SX_HSSSLEW		0x338
>+#define PESDR1_460SX_HSSSLEW		0x360
>+#define PESDR2_460SX_HSSSLEW		0x390
>+
>+#define PESDR0_460SX_HSSCTLSET		0x31E
>+#define PESDR1_460SX_HSSCTLSET		0x352
>+#define PESDR2_460SX_HSSCTLSET		0x382
>+
>+#define PESDR0_460SX_RCSSET		0x304
>+#define PESDR1_460SX_RCSSET		0x344
>+#define PESDR2_460SX_RCSSET		0x374
>+/*
>  * Of the above, some are common offsets from the base
>  */
> #define PESDRn_UTLSET1			0x00
>-- 
>1.6.1.rc3
>
>_______________________________________________
>Linuxppc-dev mailing list
>Linuxppc-dev at lists.ozlabs.org
>https://lists.ozlabs.org/listinfo/linuxppc-dev


More information about the Linuxppc-dev mailing list