From 6778948f9de86c3cfaf36725a7c87dcff9ba247f Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 08:20:59 +0000 Subject: [PATCH] kernel_5.10 no rt --- kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c | 99 ++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 80 insertions(+), 19 deletions(-) diff --git a/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c index 9b89741..4e5a225 100644 --- a/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -115,6 +115,10 @@ #define PME_TURN_OFF (BIT(4) | BIT(20)) #define PCIE_CLIENT_GENERAL_DEBUG 0x104 #define PCIE_CLIENT_HOT_RESET_CTRL 0x180 +#define PCIE_LTSSM_APP_DLY1_EN BIT(0) +#define PCIE_LTSSM_APP_DLY2_EN BIT(1) +#define PCIE_LTSSM_APP_DLY1_DONE BIT(2) +#define PCIE_LTSSM_APP_DLY2_DONE BIT(3) #define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) #define PCIE_CLIENT_LTSSM_STATUS 0x300 #define SMLH_LINKUP BIT(16) @@ -137,6 +141,7 @@ #define PCIE_PL_ORDER_RULE_CTRL_OFF 0x8B4 #define RK_PCIE_L2_TMOUT_US 5000 +#define RK_PCIE_HOTRESET_TMOUT_US 10000 enum rk_pcie_ltssm_code { S_L0 = 0x11, @@ -185,6 +190,10 @@ u32 l1ss_ctl1; struct dentry *debugfs; u32 msi_vector_num; + struct workqueue_struct *hot_rst_wq; + struct work_struct hot_rst_work; + u32 comp_prst[2]; + u32 intx; }; struct rk_pcie_of_data { @@ -1119,6 +1128,10 @@ dw_pcie_setup_rc(pp); + /* Disable BAR0 BAR1 */ + dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + BAR_0 * 4, 0); + dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + BAR_1 * 4, 0); + ret = rk_pcie_establish_link(pci); if (pp->msi_irq > 0) @@ -1434,13 +1447,37 @@ table->start.chnl = table->chn; } +static void rk_pcie_hot_rst_work(struct work_struct *work) +{ + struct rk_pcie *rk_pcie = container_of(work, struct rk_pcie, hot_rst_work); + u32 val, status; + int ret; + + /* Setup command register */ + val = dw_pcie_readl_dbi(rk_pcie->pci, PCI_COMMAND); + val &= 0xffff0000; + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + dw_pcie_writel_dbi(rk_pcie->pci, PCI_COMMAND, val); + + if (rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL) & PCIE_LTSSM_APP_DLY2_EN) { + ret = readl_poll_timeout(rk_pcie->apb_base + PCIE_CLIENT_LTSSM_STATUS, + status, ((status & 0x3F) == 0), 100, RK_PCIE_HOTRESET_TMOUT_US); + if (ret) + dev_err(rk_pcie->pci->dev, "wait for detect quiet failed!\n"); + + rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL, + (PCIE_LTSSM_APP_DLY2_DONE) | ((PCIE_LTSSM_APP_DLY2_DONE) << 16)); + } +} + static irqreturn_t rk_pcie_sys_irq_handler(int irq, void *arg) { struct rk_pcie *rk_pcie = arg; u32 chn; union int_status status; union int_clear clears; - u32 reg, val; + u32 reg; status.asdword = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS); @@ -1481,14 +1518,8 @@ } reg = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC); - if (reg & BIT(2)) { - /* Setup command register */ - val = dw_pcie_readl_dbi(rk_pcie->pci, PCI_COMMAND); - val &= 0xffff0000; - val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER | PCI_COMMAND_SERR; - dw_pcie_writel_dbi(rk_pcie->pci, PCI_COMMAND, val); - } + if (reg & BIT(2)) + queue_work(rk_pcie->hot_rst_wq, &rk_pcie->hot_rst_work); rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC, reg); @@ -1612,7 +1643,8 @@ /* LTSSM EN ctrl mode */ val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL); - val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16); + val |= (PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN) + | ((PCIE_LTSSM_APP_DLY2_EN | PCIE_LTSSM_ENABLE_ENHANCE) << 16); rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL, val); } @@ -1650,7 +1682,7 @@ static int rk_pcie_intx_map(struct irq_domain *domain, unsigned int irq, irq_hw_number_t hwirq) { - irq_set_chip_and_handler(irq, &rk_pcie_legacy_irq_chip, handle_simple_irq); + irq_set_chip_and_handler(irq, &rk_pcie_legacy_irq_chip, handle_level_irq); irq_set_chip_data(irq, domain->host_data); return 0; @@ -2051,17 +2083,39 @@ rk_pcie->is_signal_test = true; } - /* Force into compliance mode */ - if (device_property_read_bool(dev, "rockchip,compliance-mode")) { - val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS); - val |= BIT(4); - dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val); + /* + * Force into compliance mode + * comp_prst is a two dimensional array of which the first element + * stands for speed mode, and the second one is preset value encoding: + * [0] 0->SMA tool control the signal switch, 1/2/3 is for manual Gen setting + * [1] transmitter setting for manual Gen setting, valid only if [0] isn't zero. + */ + if (!device_property_read_u32_array(dev, "rockchip,compliance-mode", + rk_pcie->comp_prst, 2)) { + BUG_ON(rk_pcie->comp_prst[0] > 3 || rk_pcie->comp_prst[1] > 10); + if (!rk_pcie->comp_prst[0]) { + dev_info(dev, "Auto compliance mode for SMA tool.\n"); + } else { + dev_info(dev, "compliance mode for soldered board Gen%d, P%d.\n", + rk_pcie->comp_prst[0], rk_pcie->comp_prst[1]); + val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS); + val |= BIT(4) | rk_pcie->comp_prst[0] | (rk_pcie->comp_prst[1] << 12); + dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val); + } rk_pcie->is_signal_test = true; } /* Skip waiting for training to pass in system PM routine */ if (device_property_read_bool(dev, "rockchip,skip-scan-in-resume")) rk_pcie->skip_scan_in_resume = true; + + rk_pcie->hot_rst_wq = create_singlethread_workqueue("rk_pcie_hot_rst_wq"); + if (!rk_pcie->hot_rst_wq) { + dev_err(dev, "failed to create hot_rst workqueue\n"); + ret = -ENOMEM; + goto remove_irq_domain; + } + INIT_WORK(&rk_pcie->hot_rst_work, rk_pcie_hot_rst_work); switch (rk_pcie->mode) { case RK_PCIE_RC_TYPE: @@ -2076,12 +2130,12 @@ return 0; if (ret) - goto remove_irq_domain; + goto remove_rst_wq; ret = rk_pcie_init_dma_trx(rk_pcie); if (ret) { dev_err(dev, "failed to add dma extension\n"); - goto remove_irq_domain; + goto remove_rst_wq; } if (rk_pcie->dma_obj) { @@ -2093,7 +2147,7 @@ /* hold link reset grant after link-up */ ret = rk_pcie_reset_grant_ctrl(rk_pcie, false); if (ret) - goto remove_irq_domain; + goto remove_rst_wq; } dw_pcie_dbi_ro_wr_dis(pci); @@ -2121,6 +2175,8 @@ return 0; +remove_rst_wq: + destroy_workqueue(rk_pcie->hot_rst_wq); remove_irq_domain: if (rk_pcie->irq_domain) irq_domain_remove(rk_pcie->irq_domain); @@ -2304,6 +2360,8 @@ phy_power_off(rk_pcie->phy); phy_exit(rk_pcie->phy); + rk_pcie->intx = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY); + clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks); rk_pcie->in_suspend = true; @@ -2368,6 +2426,9 @@ if (std_rc) dw_pcie_setup_rc(&rk_pcie->pci->pp); + rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY, + rk_pcie->intx | 0xffff0000); + ret = rk_pcie_establish_link(rk_pcie->pci); if (ret) { dev_err(dev, "failed to establish pcie link\n"); -- Gitblit v1.6.2