From 072de836f53be56a70cecf70b43ae43b7ce17376 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 10:08:36 +0000
Subject: [PATCH] mk-rootfs.sh
---
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