[PATCH] powerpc: p1022: add two functions for reset pci slot

Dongsheng Wang dongsheng.wang at nxp.com
Fri Jan 22 19:19:07 AEDT 2016


From: Wang Dongsheng <dongsheng.wang at nxp.com>

When the DIU enable, only through the way of indirect access
to read/write pixis register. So add direct and indirect for
pci slot reset.

Signed-off-by: Wang Dongsheng <dongsheng.wang at nxp.com>

diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 371df82..5c8894c 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -53,23 +53,6 @@
 #define CLKDVDR_PXCKDLY		0x06000000
 #define CLKDVDR_PXCLK_MASK	0x00FF0000
 
-/* Some ngPIXIS register definitions */
-#define PX_CTL		3
-#define PX_BRDCFG0	8
-#define PX_BRDCFG1	9
-
-#define PX_BRDCFG0_ELBC_SPI_MASK	0xc0
-#define PX_BRDCFG0_ELBC_SPI_ELBC	0x00
-#define PX_BRDCFG0_ELBC_SPI_NULL	0xc0
-#define PX_BRDCFG0_ELBC_DIU		0x02
-
-#define PX_BRDCFG1_DVIEN	0x80
-#define PX_BRDCFG1_DFPEN	0x40
-#define PX_BRDCFG1_BACKLIGHT	0x20
-#define PX_BRDCFG1_DDCEN	0x10
-
-#define PX_CTL_ALTACC		0x80
-
 /*
  * DIU Area Descriptor
  *
@@ -106,6 +89,28 @@
 	(c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
 	(c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
 
+#endif
+
+/* Some ngPIXIS register definitions */
+#define PX_CTL		3
+#define PX_BRDCFG0	8
+#define PX_BRDCFG1	9
+
+#define PX_RST		0x4
+#define PX_RST_PCIE	0x8
+
+#define PX_BRDCFG0_ELBC_SPI_MASK	0xc0
+#define PX_BRDCFG0_ELBC_SPI_ELBC	0x00
+#define PX_BRDCFG0_ELBC_SPI_NULL	0xc0
+#define PX_BRDCFG0_ELBC_DIU		0x02
+
+#define PX_BRDCFG1_DVIEN	0x80
+#define PX_BRDCFG1_DFPEN	0x40
+#define PX_BRDCFG1_BACKLIGHT	0x20
+#define PX_BRDCFG1_DDCEN	0x10
+
+#define PX_CTL_ALTACC		0x80
+
 struct fsl_law {
 	u32	lawbar;
 	u32	reserved1;
@@ -125,6 +130,8 @@ struct fsl_law {
 
 #define BR_BA		0xFFFF8000
 
+static int px_ctl_altacc_flag;
+
 /*
  * Map a BRx value to a physical address
  *
@@ -157,48 +164,40 @@ static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br)
 #endif
 }
 
-/**
- * p1022ds_set_monitor_port: switch the output to a different monitor port
- */
-static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
+static u8 __iomem *lbc_lcs0_ba;
+static u8 __iomem *lbc_lcs1_ba;
+
+static inline bool verify_pixis_indirect_access_address(void)
 {
-	struct device_node *guts_node;
-	struct device_node *lbc_node = NULL;
-	struct device_node *law_node = NULL;
-	struct ccsr_guts __iomem *guts;
-	struct fsl_lbc_regs *lbc = NULL;
+	if (lbc_lcs0_ba && lbc_lcs1_ba)
+		return true;
+
+	return false;
+}
+
+static void indirect_access_pixis_probe(void)
+{
+	struct device_node *lbc_node;
+	struct device_node *law_node;
+	struct fsl_lbc_regs *lbc;
 	void *ecm = NULL;
-	u8 __iomem *lbc_lcs0_ba = NULL;
-	u8 __iomem *lbc_lcs1_ba = NULL;
+
 	phys_addr_t cs0_addr, cs1_addr;
 	u32 br0, or0, br1, or1;
 	const __be32 *iprop;
 	unsigned int num_laws;
-	u8 b;
-
-	/* Map the global utilities registers. */
-	guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
-	if (!guts_node) {
-		pr_err("p1022ds: missing global utilities device node\n");
-		return;
-	}
-
-	guts = of_iomap(guts_node, 0);
-	if (!guts) {
-		pr_err("p1022ds: could not map global utilities device\n");
-		goto exit;
-	}
 
 	lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
 	if (!lbc_node) {
 		pr_err("p1022ds: missing localbus node\n");
-		goto exit;
+		return;
 	}
 
 	lbc = of_iomap(lbc_node, 0);
+	of_node_put(lbc_node);
 	if (!lbc) {
 		pr_err("p1022ds: could not map localbus node\n");
-		goto exit;
+		return;
 	}
 
 	law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law");
@@ -282,7 +281,103 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 	if (!lbc_lcs1_ba) {
 		pr_err("p1022ds: could not ioremap CS1 address %llx\n",
 		       (unsigned long long)cs1_addr);
-		goto exit;
+
+		iounmap(lbc_lcs0_ba);
+	}
+
+exit:
+	if (ecm)
+		iounmap(ecm);
+	if (lbc)
+		iounmap(lbc);
+
+	if (law_node)
+		of_node_put(law_node);
+}
+
+static void indirect_access_pixis_reset_pcie_slot(void)
+{
+	if (!verify_pixis_indirect_access_address()) {
+		WARN_ON(1);
+		return;
+	}
+
+	/* Set FPGA access address */
+	out_8(lbc_lcs0_ba, PX_RST);
+
+	/* power down pcie slot */
+	clrbits8(lbc_lcs1_ba, PX_RST_PCIE);
+
+	/* power up pcie slot */
+	setbits8(lbc_lcs1_ba, PX_RST_PCIE);
+}
+
+static void direct_access_pixis_reset_pcie_slot(void)
+{
+	struct device_node *pixis_node;
+	void __iomem *pixis;
+
+	/* Map the pixis registers. */
+	pixis_node =
+		of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
+	if (!pixis_node) {
+		pr_err("p1022ds: missing pixis node\n");
+		return;
+	}
+
+	pixis = of_iomap(pixis_node, 0);
+	of_node_put(pixis_node);
+	if (!pixis) {
+		pr_err("p1022ds: could not map pixis registers\n");
+		return;
+	}
+
+	/* Rset PCIE slot */
+	/* power down pcie slot */
+	clrbits8(pixis + PX_RST, PX_RST_PCIE);
+
+	/* power up pcie slot */
+	setbits8(pixis + PX_RST, PX_RST_PCIE);
+
+	iounmap(pixis);
+}
+
+void p1022ds_reset_pcie_slot(void)
+{
+	if (px_ctl_altacc_flag)
+		indirect_access_pixis_reset_pcie_slot();
+	else
+		direct_access_pixis_reset_pcie_slot();
+}
+
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
+/**
+ * p1022ds_set_monitor_port: switch the output to a different monitor port
+ */
+static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
+{
+	struct device_node *guts_node;
+	struct ccsr_guts __iomem *guts;
+	u8 b;
+
+	if (!verify_pixis_indirect_access_address()) {
+		WARN_ON(1);
+		return;
+	}
+
+	/* Map the global utilities registers. */
+	guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
+	if (!guts_node) {
+		pr_err("p1022ds: missing global utilities device node\n");
+		return;
+	}
+
+	guts = of_iomap(guts_node, 0);
+	of_node_put(guts_node);
+	if (!guts) {
+		pr_err("p1022ds: could not map global utilities device\n");
+		return;
 	}
 
 	/* Make sure we're in indirect mode first. */
@@ -307,6 +402,7 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 
 		/* Enable indirect PIXIS mode.  */
 		setbits8(pixis + PX_CTL, PX_CTL_ALTACC);
+		px_ctl_altacc_flag = 1;
 		iounmap(pixis);
 
 		/* Switch the board mux to the DIU */
@@ -348,20 +444,7 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 	}
 
 exit:
-	if (lbc_lcs1_ba)
-		iounmap(lbc_lcs1_ba);
-	if (lbc_lcs0_ba)
-		iounmap(lbc_lcs0_ba);
-	if (lbc)
-		iounmap(lbc);
-	if (ecm)
-		iounmap(ecm);
-	if (guts)
-		iounmap(guts);
-
-	of_node_put(law_node);
-	of_node_put(lbc_node);
-	of_node_put(guts_node);
+	iounmap(guts);
 }
 
 /**
@@ -543,6 +626,8 @@ static void __init p1022_ds_setup_arch(void)
 
 	swiotlb_detect_4g();
 
+	indirect_access_pixis_probe();
+
 	pr_info("Freescale P1022 DS reference board\n");
 }
 
-- 
2.1.0.27.g96db324



More information about the Linuxppc-dev mailing list