From: John Jacques <john.jacq...@intel.com>

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

Signed-off-by: John Jacques <john.jacq...@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....@intel.com>");
 MODULE_DESCRIPTION("Axxia PCIe host controller driver");
 MODULE_LICENSE("GPL v2");
-- 
2.7.4

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to