mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
Revert "PCI: brcmstb: Configure HW CLKREQ# mode appropriate for downstream device"
This reverts commit e2596dcf1e.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user