From c3733c007cae4bab1d65f6d20e23a74ed3fd259f Mon Sep 17 00:00:00 2001 From: Dom Cobley Date: Fri, 2 Feb 2024 13:04:00 +0000 Subject: [PATCH] Revert "PCI: brcmstb: Configure HW CLKREQ# mode appropriate for downstream device" This reverts commit e2596dcf1e9dfd5904d50f796c19b03c94a3b8b4. --- drivers/pci/controller/pcie-brcmstb.c | 96 +++------------------------ 1 file changed, 10 insertions(+), 86 deletions(-) diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c index c08683febdd4..e47a77f943b1 100644 --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c @@ -48,9 +48,6 @@ #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00 -#define PCIE_RC_CFG_PRIV1_ROOT_CAP 0x4f8 -#define PCIE_RC_CFG_PRIV1_ROOT_CAP_L1SS_MODE_MASK 0xf8 - #define PCIE_RC_DL_MDIO_ADDR 0x1100 #define PCIE_RC_DL_MDIO_WR_DATA 0x1104 #define PCIE_RC_DL_MDIO_RD_DATA 0x1108 @@ -124,12 +121,9 @@ #define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204 #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2 -#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK 0x200000 #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000 #define PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x00800000 -#define PCIE_CLKREQ_MASK \ - (PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK | \ - PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK) + #define PCIE_INTR2_CPU_BASE 0x4300 #define PCIE_MSI_INTR2_BASE 0x4500 @@ -1034,89 +1028,13 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie) return 0; } -/* - * This extends the timeout period for an access to an internal bus. This - * access timeout may occur during L1SS sleep periods, even without the - * presence of a PCIe access. - */ -static void brcm_extend_rbus_timeout(struct brcm_pcie *pcie) -{ - /* TIMEOUT register is two registers before RGR1_SW_INIT_1 */ - const unsigned int REG_OFFSET = PCIE_RGR1_SW_INIT_1(pcie) - 8; - u32 timeout_us = 4000000; /* 4 seconds, our setting for L1SS */ - - /* Each unit in timeout register is 1/216,000,000 seconds */ - writel(216 * timeout_us, pcie->base + REG_OFFSET); -} - -static void brcm_config_clkreq(struct brcm_pcie *pcie) -{ - static const char err_msg[] = "invalid 'brcm,clkreq-mode' DT string\n"; - const char *mode = "default"; - u32 clkreq_cntl; - int ret, tmp; - - ret = of_property_read_string(pcie->np, "brcm,clkreq-mode", &mode); - if (ret && ret != -EINVAL) { - dev_err(pcie->dev, err_msg); - mode = "safe"; - } - - /* Start out assuming safe mode (both mode bits cleared) */ - clkreq_cntl = readl(pcie->base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); - clkreq_cntl &= ~PCIE_CLKREQ_MASK; - - if (strcmp(mode, "no-l1ss") == 0) { - /* - * "no-l1ss" -- Provides Clock Power Management, L0s, and - * L1, but cannot provide L1 substate (L1SS) power - * savings. If the downstream device connected to the RC is - * L1SS capable AND the OS enables L1SS, all PCIe traffic - * may abruptly halt, potentially hanging the system. - */ - clkreq_cntl |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK; - /* - * We want to un-advertise L1 substates because if the OS - * tries to configure the controller into using L1 substate - * power savings it may fail or hang when the RC HW is in - * "no-l1ss" mode. - */ - tmp = readl(pcie->base + PCIE_RC_CFG_PRIV1_ROOT_CAP); - u32p_replace_bits(&tmp, 2, PCIE_RC_CFG_PRIV1_ROOT_CAP_L1SS_MODE_MASK); - writel(tmp, pcie->base + PCIE_RC_CFG_PRIV1_ROOT_CAP); - - } else if (strcmp(mode, "default") == 0) { - /* - * "default" -- Provides L0s, L1, and L1SS, but not - * compliant to provide Clock Power Management; - * specifically, may not be able to meet the Tclron max - * timing of 400ns as specified in "Dynamic Clock Control", - * section 3.2.5.2.2 of the PCIe spec. This situation is - * atypical and should happen only with older devices. - */ - clkreq_cntl |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK; - brcm_extend_rbus_timeout(pcie); - - } else { - /* - * "safe" -- No power savings; refclk is driven by RC - * unconditionally. - */ - if (strcmp(mode, "safe") != 0) - dev_err(pcie->dev, err_msg); - mode = "safe"; - } - writel(clkreq_cntl, pcie->base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); - - dev_info(pcie->dev, "clkreq-mode set to %s\n", mode); -} - static int brcm_pcie_start_link(struct brcm_pcie *pcie) { struct device *dev = pcie->dev; void __iomem *base = pcie->base; u16 nlw, cls, lnksta; bool ssc_good = false; + u32 tmp; int ret, i; /* Unassert the fundamental reset */ @@ -1141,8 +1059,6 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie) return -ENODEV; } - brcm_config_clkreq(pcie); - if (pcie->gen) brcm_pcie_set_gen(pcie, pcie->gen); @@ -1161,6 +1077,14 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie) pci_speed_string(pcie_link_speed[cls]), nlw, ssc_good ? "(SSC)" : "(!SSC)"); + /* + * Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1 + * is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1. + */ + tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); + tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK; + writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); + return 0; }