[linux-yocto] [PATCH 3/3] axxia: Add Link Reset to the 5600 Axxia PCIe Driver

Daniel Dragomir daniel.dragomir at windriver.com
Mon Aug 22 02:21:27 PDT 2016


From: John Jacques <john.jacques at intel.com>

Add the ability to re-establish a link to the Axxia
5600 PCIe driver.

Signed-off-by: John Jacques <john.jacques at intel.com>
---
 drivers/misc/axxia-pei.c      | 133 ++++++++++--------------------------------
 drivers/pci/host/pcie-axxia.c | 103 ++++++++++++++++----------------
 2 files changed, 84 insertions(+), 152 deletions(-)

diff --git a/drivers/misc/axxia-pei.c b/drivers/misc/axxia-pei.c
index c750fc9..e78cf60 100644
--- a/drivers/misc/axxia-pei.c
+++ b/drivers/misc/axxia-pei.c
@@ -39,6 +39,7 @@ static int is_5600;
 static int is_6700;
 
 static void __iomem *pcie_gpreg0;
+static void __iomem *pcie_rc;
 
 enum SataMode {
 	SATA0,
@@ -507,68 +508,6 @@ void setup_srio_mode(enum SrioMode mode, enum SrioSpeed speed)
 	}
 }
 
-void enable_reset(u32 phy)
-{
-	u32 regVal;
-
-	if (phy == 0) {
-		ncr_read32(NCP_REGION_ID(0x115, 0), 0x0,
-			   &regVal);
-		regVal |= (1 << 5);
-		ncr_write32(NCP_REGION_ID(0x115, 0), 0x0,
-			    regVal);
-	} else if (phy == 1) {
-		ncr_read32(NCP_REGION_ID(0x115, 0), 0x0,
-			   &regVal);
-		regVal |= (1 << 14);
-		ncr_write32(NCP_REGION_ID(0x115, 0), 0x0,
-			    regVal);
-	} else if (phy == 2) {
-		ncr_read32(NCP_REGION_ID(0x115, 0), 0x4,
-			   &regVal);
-		regVal |= (1 << 19);
-		ncr_write32(NCP_REGION_ID(0x115, 0), 0x4,
-			    regVal);  /* jl */
-	} else if (phy == 3) {
-		ncr_read32(NCP_REGION_ID(0x115, 0), 0x4,
-			   &regVal);
-		regVal |= (1 << 29);
-		ncr_write32(NCP_REGION_ID(0x115, 0), 0x4,
-			    regVal);  /* jl */
-	}
-}
-
-void release_reset(u32 phy)
-{
-	u32 regVal;
-
-	if (phy == 0) {
-		ncr_read32(NCP_REGION_ID(0x115, 0), 0x0,
-			   &regVal);
-		regVal &= (~(1 << 5));
-		ncr_write32(NCP_REGION_ID(0x115, 0), 0x0,
-			    regVal);
-	} else if (phy == 1) {
-		ncr_read32(NCP_REGION_ID(0x115, 0), 0x0,
-			   &regVal);
-		regVal &= (~(1 << 14));
-		ncr_write32(NCP_REGION_ID(0x115, 0), 0x0,
-			    regVal);
-	} else if (phy == 2) {
-		ncr_read32(NCP_REGION_ID(0x115, 0), 0x4,
-			   &regVal);
-		regVal &= (~(1 << 19));
-		ncr_write32(NCP_REGION_ID(0x115, 0), 0x4,
-			    regVal);   /* jl */
-	} else if (phy == 3) {
-		ncr_read32(NCP_REGION_ID(0x115, 0), 0x4,
-			   &regVal);
-		regVal &= (~(1 << 29));
-		ncr_write32(NCP_REGION_ID(0x115, 0), 0x4,
-			    regVal);   /* jl */
-	}
-}
-
 int check_pll_lock(enum PLLMode mode, u32 phy)
 {
 	u32 regVal;
@@ -732,13 +671,14 @@ pei_setup(unsigned int control)
 	val = readl(pcie_gpreg0 + 0x8038);
 	val &= (~(0x1));
 	writel(val, pcie_gpreg0 + 0x8038);
+	msleep(100);
 
-	for (phy = 0; phy < 4; phy++)
-		enable_reset(phy);
-
+	ncr_read32(NCP_REGION_ID(0x115, 0), 0x0, &phyVal0);
+	phyVal0 &= ~1;
+	ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, phyVal0);
 	mdelay(100);		/* TODO: Why is this needed? */
 
-	switch ((control & 0x03c00000) >> 22) {
+	switch ((control & 0x03c00000) >> 22) { /* bits 25:22 */
 	case 0:
 		/* PEI0x8 */
 		rc_mode = (control & 0x80)<<15; /* jl */
@@ -747,30 +687,18 @@ pei_setup(unsigned int control)
 		ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, phyVal0);
 		/* PIPE port select -- Enable PIPE0 interface */
 		ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, (0x1<<24));
-		for (phy = 0; phy < 4; phy++)
-			release_reset(phy);
 		break;
 	case 1:
-		/* PEI0x4_PEI1x4 */
-		rc_mode = (control & 0x80)<<15;  /* jl */
-		/* Enable PEI0/PEI1, PEI0 RC mode */
-		phyVal0 = (control & 0x3) | rc_mode; /* jl */
-		/* PEI0x4 */
-		phyVal0 |= (0x1 << 26);
-		ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, phyVal0);
-		/* PEI1x4 */
-		phyVal1 = (0x1 << 22);
-		/* PIPE port select -- Enable PIPE0/PIPE1 interface */
-		phyVal1 |= (0x2 << 24);
-		ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, phyVal1);
-
-		for (phy = 0; phy < 4; phy++)
-			release_reset(phy);
+		/*
+		  PEI0x4, PEI1x4
+		*/
 
-		/* //jl read back phy registers to check values */
-		ncr_read32(NCP_REGION_ID(0x115, 0), 0x0,  &phyVal0);
-		ncr_read32(NCP_REGION_ID(0x115, 0), 0x4,  &phyVal1);
+		printk("%s:%d -\n", __FILE__, __LINE__);
+		phyVal1 = 0x0e7001ac;
+		ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, phyVal1);
 
+		phyVal0 = 0x84400040;
+		ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, phyVal0);
 		break;
 	case 2:
 		/* PEI0x4_PEI1x2_SATA0x1_SATA1x1 */
@@ -789,8 +717,6 @@ pei_setup(unsigned int control)
 			setup_sata_mode(SATA0, ((control & 0xc0000) >> 18));
 		if (((control & 0x40) >> 6))
 			setup_sata_mode(SATA1, ((control & 0x30000) >> 20));
-		for (phy = 0; phy < 4; phy++)
-			release_reset(phy);
 		if (!check_pll_lock(PLLA, 1)) {
 			printk("PLLA didn't lock\n");
 			return 1;
@@ -842,8 +768,6 @@ pei_setup(unsigned int control)
 			setup_sata_mode(SATA0, ((control & 0xc0000) >> 18));
 		if (((control & 0x40) >> 6))
 			setup_sata_mode(SATA1, ((control & 0x30000) >> 20));
-		for (phy = 0; phy < 4; phy++)
-			release_reset(phy);
 
 		if (!check_pll_lock(PLLA, 1)) {
 			printk("PLLA didn't lock\n");
@@ -898,8 +822,6 @@ pei_setup(unsigned int control)
 			    phyVal1 | srio0_speed);
 		if (srio0_mode)
 			setup_srio_mode(SRIO0, srio0_speed);
-		for (phy = 0; phy < 4; phy++)
-			release_reset(phy);
 		if (!check_pll_lock(PLLA, 1)) {
 			printk("PLLA didn't lock\n");
 			return 1;
@@ -976,8 +898,6 @@ pei_setup(unsigned int control)
 			setup_sata_mode(SATA1, ((control & 0x30000) >> 20));
 		if (srio0_mode)
 			setup_srio_mode(SRIO0, srio0_speed);
-		for (phy = 0; phy < 4; phy++)
-			release_reset(phy);
 		if (!check_pll_lock(PLLA, 1)) {
 			printk("PLLA didn't lock\n");
 			return 1;
@@ -1073,8 +993,6 @@ pei_setup(unsigned int control)
 			    phyVal1 | srio0_speed);
 		if (srio0_mode)
 			setup_srio_mode(SRIO0, srio0_speed);
-		for (phy = 0; phy < 4; phy++)
-			release_reset(phy);
 		if (!check_pll_lock(PLLA, 1)) {
 			printk("PLLA didn't lock\n");
 			return 1;
@@ -1152,8 +1070,6 @@ pei_setup(unsigned int control)
 			setup_srio_mode(SRIO0, srio0_speed);
 		if (srio1_mode)
 			setup_srio_mode(SRIO1, srio1_speed);
-		for (phy = 0; phy < 4; phy++)
-			release_reset(phy);
 		if (!check_pll_lock(PLLA, 1)) {
 			printk("PLLA didn't lock\n");
 			return 1;
@@ -1240,8 +1156,6 @@ pei_setup(unsigned int control)
 			setup_srio_mode(SRIO0, srio0_speed);
 		if (srio1_mode)
 			setup_srio_mode(SRIO1, srio1_speed);
-		for (phy = 0; phy < 4; phy++)
-			release_reset(phy);
 		if (!check_pll_lock(PLLA, 1)) {
 			printk("PLLA didn't lock\n");
 			return 1;
@@ -1350,8 +1264,6 @@ pei_setup(unsigned int control)
 			setup_srio_mode(SRIO0, srio0_speed);
 		if (srio1_mode)
 			setup_srio_mode(SRIO1, srio1_speed);
-		for (phy = 0; phy < 4; phy++)
-			release_reset(phy);
 		if (!check_pll_lock(PLLA, 1)) {
 			printk("PLLA didn't lock\n");
 			return 1;
@@ -1410,6 +1322,21 @@ pei_setup(unsigned int control)
 		break;
 	}
 
+	ncr_read32(NCP_REGION_ID(0x115, 0), 0x0, &phyVal0);
+	phyVal0 |= 1;
+	ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, phyVal0);
+	msleep(100);
+
+	switch ((control & 0x03c00000) >> 22) { /* bits 25:22 */
+	case 1:
+		writel(0x70120, pcie_rc + 0x710);
+		writel(0x104be, pcie_rc + 0x80c);
+		writel(0x1017201, pcie_rc + 0x8a8);
+		break;
+	default:
+		break;
+	}
+
 	return 0;
 }
 
@@ -1424,13 +1351,13 @@ static int
 pei_init(void)
 {
 	/* Use the device tree to determine the Axxia type. */
-
 	if (of_find_compatible_node(NULL, NULL, "lsi,axm5500") ||
 	    of_find_compatible_node(NULL, NULL, "lsi,axm5516")) {
 		is_5500 = 1;
 	} else if (of_find_compatible_node(NULL, NULL, "lsi,axm5616")) {
 		is_5600 = 1;
 		pcie_gpreg0 = ioremap(0xa003000000, 0x10000);
+		pcie_rc = ioremap(0xa002000000, 0x1000);
 	} else if (of_find_compatible_node(NULL, NULL, "lsi,axc6732")) {
 		is_6700 = 1;
 	} else {
diff --git a/drivers/pci/host/pcie-axxia.c b/drivers/pci/host/pcie-axxia.c
index de383e0..9c7ef5f 100644
--- a/drivers/pci/host/pcie-axxia.c
+++ b/drivers/pci/host/pcie-axxia.c
@@ -24,6 +24,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/proc_fs.h>
 #include <linux/axxia-pei.h>
 
 #include "pcie-axxia.h"
@@ -103,6 +104,10 @@
 /* SYSCON */
 #define AXXIA_SYSCON_BASE             0x8002C00000
 
+static int control_set;
+static unsigned int control_value;
+static struct pcie_port *_ppL;
+
 static inline uint32_t axxia_mmio_read_32(uintptr_t addr)
 {
 	return *(uint32_t *)addr;
@@ -516,39 +521,6 @@ void axxia_pcie_setup_rc(struct pcie_port *pp)
 	u32 membase;
 	u32 memlimit;
 
-	/* set the number of lanes */
-	axxia_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val);
-	val &= ~PORT_LINK_MODE_MASK;
-	switch (pp->lanes) {
-	case 1:
-		val |= PORT_LINK_MODE_1_LANES;
-	break;
-	case 2:
-		val |= PORT_LINK_MODE_2_LANES;
-	break;
-	case 4:
-		val |= PORT_LINK_MODE_4_LANES;
-	break;
-	}
-	axxia_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
-
-	/* set link width speed control register */
-	axxia_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, &val);
-	val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
-	switch (pp->lanes) {
-	case 1:
-		val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
-	break;
-	case 2:
-		val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
-	break;
-	case 4:
-		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
-	break;
-	}
-
-	axxia_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);
-
 	/* setup bus numbers */
 	axxia_pcie_readl_rc(pp, PCI_PRIMARY_BUS, &val);
 	val &= 0xff000000;
@@ -567,7 +539,6 @@ void axxia_pcie_setup_rc(struct pcie_port *pp)
 	val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
 		PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
 	axxia_pcie_writel_rc(pp, val, PCI_COMMAND);
-	axxia_pcie_writel_rc(pp, 0x1017201, 0x8a8);
 
 	/* LTSSM enable */
 	axxia_cc_gpreg_readl(pp, PEI_GENERAL_CORE_CTL_REG, &val);
@@ -579,7 +550,6 @@ void axxia_pcie_setup_rc(struct pcie_port *pp)
 
 static int axxia_pcie_establish_link(struct pcie_port *pp)
 {
-
 	/* setup root complex */
 	axxia_pcie_setup_rc(pp);
 
@@ -743,7 +713,7 @@ static struct msi_controller axxia_dw_pcie_msi_chip = {
 	.teardown_irq = axxia_dw_msi_teardown_irq,
 };
 
-int __init axxia_pcie_host_init(struct pcie_port *pp)
+int axxia_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
@@ -849,10 +819,8 @@ int __init axxia_pcie_host_init(struct pcie_port *pp)
 	}
 
 
-	if (axxia_pcie_establish_link(pp)) {
-		dev_err(pp->dev, "axxia_pcie_establish_link failed\n");
-		return -EINVAL;
-	}
+	if (axxia_pcie_establish_link(pp))
+		dev_warn(pp->dev, "axxia_pcie_establish_link failed\n");
 
 	/* Legacy interrupts */
 	pp->irq[0] = platform_get_irq(pdev, 0);
@@ -885,10 +853,6 @@ int __init axxia_pcie_host_init(struct pcie_port *pp)
 	/* program correct class for RC */
 	axxia_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
 
-	axxia_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
-	val |= PORT_LOGIC_SPEED_CHANGE;
-	axxia_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
-
 	bus = pci_create_root_bus(&pdev->dev, pp->root_bus_nr,
 		&axxia_pciex_pci_ops, pp, &res);
 	if (!bus)
@@ -908,7 +872,7 @@ int __init axxia_pcie_host_init(struct pcie_port *pp)
 }
 
 
-static int __init axxia_pcie_probe(struct platform_device *pdev)
+static int axxia_pcie_probe(struct platform_device *pdev)
 {
 	struct axxia_pcie *axxia_pcie;
 	struct pcie_port *pp;
@@ -942,7 +906,7 @@ static int __init axxia_pcie_probe(struct platform_device *pdev)
 		return PTR_ERR(pp->cc_gpreg_base);
 
 	pp->root_bus_nr = 0;
-
+	_pp = pp;
 	pei_control = of_find_node_by_name(NULL, "pei_control");
 
 	if (pei_control) {
@@ -955,6 +919,8 @@ static int __init axxia_pcie_probe(struct platform_device *pdev)
 		}
 
 		axxia_pcie->control = be32_to_cpu(*control);
+		control_set = 1;
+		control_value = axxia_pcie->control;
 
 		if (0 != pei_setup(axxia_pcie->control)) {
 			pr_err("pcie-axxia: PEI setup failed!\n");
@@ -984,7 +950,8 @@ static const struct of_device_id axxia_pcie_of_match[] = {
 MODULE_DEVICE_TABLE(of, axxia_pcie_of_match);
 
 static struct platform_driver axxia_pcie_driver = {
-	.remove		= __exit_p(axxia_pcie_remove),
+	.probe          = axxia_pcie_probe,
+	.remove		= axxia_pcie_remove,
 	.driver = {
 		.name	= "axxia-pcie",
 		.owner	= THIS_MODULE,
@@ -994,12 +961,50 @@ static struct platform_driver axxia_pcie_driver = {
 
 /* Axxia PCIe driver does not allow module unload */
 
-static int __init pcie_init(void)
+static ssize_t
+axxia_pcie_reset_trigger(struct file *file, const char __user *buf,
+			 size_t count, loff_t *ppos)
 {
-	return platform_driver_probe(&axxia_pcie_driver, axxia_pcie_probe);
+	unsigned int val;
+
+	if (0 == control_set)
+		return count;
+
+	pei_setup(control_value);
+
+	axxia_cc_gpreg_readl(_pp, PEI_GENERAL_CORE_CTL_REG, &val);
+	msleep(100);
+	val |= 0x1;
+	axxia_cc_gpreg_writel(_pp, 0x1, PEI_GENERAL_CORE_CTL_REG);
+	msleep(100);
+
+	return count;
+}
+
+static int pcie_init(void)
+{
+	return platform_driver_register(&axxia_pcie_driver);
 }
 subsys_initcall(pcie_init);
 
+static const struct file_operations axxia_pcie_reset_proc_ops = {
+	.write      = axxia_pcie_reset_trigger,
+	.llseek     = noop_llseek,
+};
+
+static int pcie2_init(void)
+{
+	if (0 != proc_create("driver/axxia_pcie_reset", S_IWUSR, NULL,
+			    &axxia_pcie_reset_proc_ops)) {
+		pr_err("Could not create /proc/driver/axxia_pcie_reset!\n");
+
+		return -1;
+	}
+
+	return 0;
+}
+device_initcall(pcie2_init);
+
 MODULE_AUTHOR("Sangeetha Rao <sangeetha.rao at intel.com>");
 MODULE_DESCRIPTION("Axxia PCIe host controller driver");
 MODULE_LICENSE("GPL v2");
-- 
2.7.4



More information about the linux-yocto mailing list