.. | .. |
---|
115 | 115 | #define PME_TURN_OFF (BIT(4) | BIT(20)) |
---|
116 | 116 | #define PCIE_CLIENT_GENERAL_DEBUG 0x104 |
---|
117 | 117 | #define PCIE_CLIENT_HOT_RESET_CTRL 0x180 |
---|
| 118 | +#define PCIE_LTSSM_APP_DLY1_EN BIT(0) |
---|
| 119 | +#define PCIE_LTSSM_APP_DLY2_EN BIT(1) |
---|
| 120 | +#define PCIE_LTSSM_APP_DLY1_DONE BIT(2) |
---|
| 121 | +#define PCIE_LTSSM_APP_DLY2_DONE BIT(3) |
---|
118 | 122 | #define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) |
---|
119 | 123 | #define PCIE_CLIENT_LTSSM_STATUS 0x300 |
---|
120 | 124 | #define SMLH_LINKUP BIT(16) |
---|
.. | .. |
---|
137 | 141 | |
---|
138 | 142 | #define PCIE_PL_ORDER_RULE_CTRL_OFF 0x8B4 |
---|
139 | 143 | #define RK_PCIE_L2_TMOUT_US 5000 |
---|
| 144 | +#define RK_PCIE_HOTRESET_TMOUT_US 10000 |
---|
140 | 145 | |
---|
141 | 146 | enum rk_pcie_ltssm_code { |
---|
142 | 147 | S_L0 = 0x11, |
---|
.. | .. |
---|
185 | 190 | u32 l1ss_ctl1; |
---|
186 | 191 | struct dentry *debugfs; |
---|
187 | 192 | u32 msi_vector_num; |
---|
| 193 | + struct workqueue_struct *hot_rst_wq; |
---|
| 194 | + struct work_struct hot_rst_work; |
---|
| 195 | + u32 comp_prst[2]; |
---|
| 196 | + u32 intx; |
---|
188 | 197 | }; |
---|
189 | 198 | |
---|
190 | 199 | struct rk_pcie_of_data { |
---|
.. | .. |
---|
1119 | 1128 | |
---|
1120 | 1129 | dw_pcie_setup_rc(pp); |
---|
1121 | 1130 | |
---|
| 1131 | + /* Disable BAR0 BAR1 */ |
---|
| 1132 | + dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + BAR_0 * 4, 0); |
---|
| 1133 | + dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + BAR_1 * 4, 0); |
---|
| 1134 | + |
---|
1122 | 1135 | ret = rk_pcie_establish_link(pci); |
---|
1123 | 1136 | |
---|
1124 | 1137 | if (pp->msi_irq > 0) |
---|
.. | .. |
---|
1434 | 1447 | table->start.chnl = table->chn; |
---|
1435 | 1448 | } |
---|
1436 | 1449 | |
---|
| 1450 | +static void rk_pcie_hot_rst_work(struct work_struct *work) |
---|
| 1451 | +{ |
---|
| 1452 | + struct rk_pcie *rk_pcie = container_of(work, struct rk_pcie, hot_rst_work); |
---|
| 1453 | + u32 val, status; |
---|
| 1454 | + int ret; |
---|
| 1455 | + |
---|
| 1456 | + /* Setup command register */ |
---|
| 1457 | + val = dw_pcie_readl_dbi(rk_pcie->pci, PCI_COMMAND); |
---|
| 1458 | + val &= 0xffff0000; |
---|
| 1459 | + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | |
---|
| 1460 | + PCI_COMMAND_MASTER | PCI_COMMAND_SERR; |
---|
| 1461 | + dw_pcie_writel_dbi(rk_pcie->pci, PCI_COMMAND, val); |
---|
| 1462 | + |
---|
| 1463 | + if (rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL) & PCIE_LTSSM_APP_DLY2_EN) { |
---|
| 1464 | + ret = readl_poll_timeout(rk_pcie->apb_base + PCIE_CLIENT_LTSSM_STATUS, |
---|
| 1465 | + status, ((status & 0x3F) == 0), 100, RK_PCIE_HOTRESET_TMOUT_US); |
---|
| 1466 | + if (ret) |
---|
| 1467 | + dev_err(rk_pcie->pci->dev, "wait for detect quiet failed!\n"); |
---|
| 1468 | + |
---|
| 1469 | + rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL, |
---|
| 1470 | + (PCIE_LTSSM_APP_DLY2_DONE) | ((PCIE_LTSSM_APP_DLY2_DONE) << 16)); |
---|
| 1471 | + } |
---|
| 1472 | +} |
---|
| 1473 | + |
---|
1437 | 1474 | static irqreturn_t rk_pcie_sys_irq_handler(int irq, void *arg) |
---|
1438 | 1475 | { |
---|
1439 | 1476 | struct rk_pcie *rk_pcie = arg; |
---|
1440 | 1477 | u32 chn; |
---|
1441 | 1478 | union int_status status; |
---|
1442 | 1479 | union int_clear clears; |
---|
1443 | | - u32 reg, val; |
---|
| 1480 | + u32 reg; |
---|
1444 | 1481 | |
---|
1445 | 1482 | status.asdword = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + |
---|
1446 | 1483 | PCIE_DMA_WR_INT_STATUS); |
---|
.. | .. |
---|
1481 | 1518 | } |
---|
1482 | 1519 | |
---|
1483 | 1520 | reg = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC); |
---|
1484 | | - if (reg & BIT(2)) { |
---|
1485 | | - /* Setup command register */ |
---|
1486 | | - val = dw_pcie_readl_dbi(rk_pcie->pci, PCI_COMMAND); |
---|
1487 | | - val &= 0xffff0000; |
---|
1488 | | - val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | |
---|
1489 | | - PCI_COMMAND_MASTER | PCI_COMMAND_SERR; |
---|
1490 | | - dw_pcie_writel_dbi(rk_pcie->pci, PCI_COMMAND, val); |
---|
1491 | | - } |
---|
| 1521 | + if (reg & BIT(2)) |
---|
| 1522 | + queue_work(rk_pcie->hot_rst_wq, &rk_pcie->hot_rst_work); |
---|
1492 | 1523 | |
---|
1493 | 1524 | rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC, reg); |
---|
1494 | 1525 | |
---|
.. | .. |
---|
1612 | 1643 | |
---|
1613 | 1644 | /* LTSSM EN ctrl mode */ |
---|
1614 | 1645 | val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL); |
---|
1615 | | - val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16); |
---|
| 1646 | + val |= (PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN) |
---|
| 1647 | + | ((PCIE_LTSSM_APP_DLY2_EN | PCIE_LTSSM_ENABLE_ENHANCE) << 16); |
---|
1616 | 1648 | rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL, val); |
---|
1617 | 1649 | } |
---|
1618 | 1650 | |
---|
.. | .. |
---|
1650 | 1682 | static int rk_pcie_intx_map(struct irq_domain *domain, unsigned int irq, |
---|
1651 | 1683 | irq_hw_number_t hwirq) |
---|
1652 | 1684 | { |
---|
1653 | | - irq_set_chip_and_handler(irq, &rk_pcie_legacy_irq_chip, handle_simple_irq); |
---|
| 1685 | + irq_set_chip_and_handler(irq, &rk_pcie_legacy_irq_chip, handle_level_irq); |
---|
1654 | 1686 | irq_set_chip_data(irq, domain->host_data); |
---|
1655 | 1687 | |
---|
1656 | 1688 | return 0; |
---|
.. | .. |
---|
2051 | 2083 | rk_pcie->is_signal_test = true; |
---|
2052 | 2084 | } |
---|
2053 | 2085 | |
---|
2054 | | - /* Force into compliance mode */ |
---|
2055 | | - if (device_property_read_bool(dev, "rockchip,compliance-mode")) { |
---|
2056 | | - val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS); |
---|
2057 | | - val |= BIT(4); |
---|
2058 | | - dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val); |
---|
| 2086 | + /* |
---|
| 2087 | + * Force into compliance mode |
---|
| 2088 | + * comp_prst is a two dimensional array of which the first element |
---|
| 2089 | + * stands for speed mode, and the second one is preset value encoding: |
---|
| 2090 | + * [0] 0->SMA tool control the signal switch, 1/2/3 is for manual Gen setting |
---|
| 2091 | + * [1] transmitter setting for manual Gen setting, valid only if [0] isn't zero. |
---|
| 2092 | + */ |
---|
| 2093 | + if (!device_property_read_u32_array(dev, "rockchip,compliance-mode", |
---|
| 2094 | + rk_pcie->comp_prst, 2)) { |
---|
| 2095 | + BUG_ON(rk_pcie->comp_prst[0] > 3 || rk_pcie->comp_prst[1] > 10); |
---|
| 2096 | + if (!rk_pcie->comp_prst[0]) { |
---|
| 2097 | + dev_info(dev, "Auto compliance mode for SMA tool.\n"); |
---|
| 2098 | + } else { |
---|
| 2099 | + dev_info(dev, "compliance mode for soldered board Gen%d, P%d.\n", |
---|
| 2100 | + rk_pcie->comp_prst[0], rk_pcie->comp_prst[1]); |
---|
| 2101 | + val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS); |
---|
| 2102 | + val |= BIT(4) | rk_pcie->comp_prst[0] | (rk_pcie->comp_prst[1] << 12); |
---|
| 2103 | + dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val); |
---|
| 2104 | + } |
---|
2059 | 2105 | rk_pcie->is_signal_test = true; |
---|
2060 | 2106 | } |
---|
2061 | 2107 | |
---|
2062 | 2108 | /* Skip waiting for training to pass in system PM routine */ |
---|
2063 | 2109 | if (device_property_read_bool(dev, "rockchip,skip-scan-in-resume")) |
---|
2064 | 2110 | rk_pcie->skip_scan_in_resume = true; |
---|
| 2111 | + |
---|
| 2112 | + rk_pcie->hot_rst_wq = create_singlethread_workqueue("rk_pcie_hot_rst_wq"); |
---|
| 2113 | + if (!rk_pcie->hot_rst_wq) { |
---|
| 2114 | + dev_err(dev, "failed to create hot_rst workqueue\n"); |
---|
| 2115 | + ret = -ENOMEM; |
---|
| 2116 | + goto remove_irq_domain; |
---|
| 2117 | + } |
---|
| 2118 | + INIT_WORK(&rk_pcie->hot_rst_work, rk_pcie_hot_rst_work); |
---|
2065 | 2119 | |
---|
2066 | 2120 | switch (rk_pcie->mode) { |
---|
2067 | 2121 | case RK_PCIE_RC_TYPE: |
---|
.. | .. |
---|
2076 | 2130 | return 0; |
---|
2077 | 2131 | |
---|
2078 | 2132 | if (ret) |
---|
2079 | | - goto remove_irq_domain; |
---|
| 2133 | + goto remove_rst_wq; |
---|
2080 | 2134 | |
---|
2081 | 2135 | ret = rk_pcie_init_dma_trx(rk_pcie); |
---|
2082 | 2136 | if (ret) { |
---|
2083 | 2137 | dev_err(dev, "failed to add dma extension\n"); |
---|
2084 | | - goto remove_irq_domain; |
---|
| 2138 | + goto remove_rst_wq; |
---|
2085 | 2139 | } |
---|
2086 | 2140 | |
---|
2087 | 2141 | if (rk_pcie->dma_obj) { |
---|
.. | .. |
---|
2093 | 2147 | /* hold link reset grant after link-up */ |
---|
2094 | 2148 | ret = rk_pcie_reset_grant_ctrl(rk_pcie, false); |
---|
2095 | 2149 | if (ret) |
---|
2096 | | - goto remove_irq_domain; |
---|
| 2150 | + goto remove_rst_wq; |
---|
2097 | 2151 | } |
---|
2098 | 2152 | |
---|
2099 | 2153 | dw_pcie_dbi_ro_wr_dis(pci); |
---|
.. | .. |
---|
2121 | 2175 | |
---|
2122 | 2176 | return 0; |
---|
2123 | 2177 | |
---|
| 2178 | +remove_rst_wq: |
---|
| 2179 | + destroy_workqueue(rk_pcie->hot_rst_wq); |
---|
2124 | 2180 | remove_irq_domain: |
---|
2125 | 2181 | if (rk_pcie->irq_domain) |
---|
2126 | 2182 | irq_domain_remove(rk_pcie->irq_domain); |
---|
.. | .. |
---|
2304 | 2360 | phy_power_off(rk_pcie->phy); |
---|
2305 | 2361 | phy_exit(rk_pcie->phy); |
---|
2306 | 2362 | |
---|
| 2363 | + rk_pcie->intx = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY); |
---|
| 2364 | + |
---|
2307 | 2365 | clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks); |
---|
2308 | 2366 | |
---|
2309 | 2367 | rk_pcie->in_suspend = true; |
---|
.. | .. |
---|
2368 | 2426 | if (std_rc) |
---|
2369 | 2427 | dw_pcie_setup_rc(&rk_pcie->pci->pp); |
---|
2370 | 2428 | |
---|
| 2429 | + rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY, |
---|
| 2430 | + rk_pcie->intx | 0xffff0000); |
---|
| 2431 | + |
---|
2371 | 2432 | ret = rk_pcie_establish_link(rk_pcie->pci); |
---|
2372 | 2433 | if (ret) { |
---|
2373 | 2434 | dev_err(dev, "failed to establish pcie link\n"); |
---|