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, - ®Val); - regVal |= (1 << 5); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, - regVal); - } else if (phy == 1) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0x0, - ®Val); - regVal |= (1 << 14); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, - regVal); - } else if (phy == 2) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, - ®Val); - 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, - ®Val); - 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, - ®Val); - regVal &= (~(1 << 5)); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, - regVal); - } else if (phy == 1) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0x0, - ®Val); - regVal &= (~(1 << 14)); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, - regVal); - } else if (phy == 2) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, - ®Val); - 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, - ®Val); - 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