Skip to content

Commit 6f77f0a

Browse files
committed
Merge branch 'pci/controller/broadcom'
- Add DT property "brcm,clkreq-mode" and driver support for different CLKREQ# modes (Jim Quinlan) * pci/controller/broadcom: PCI: brcmstb: Configure HW CLKREQ# mode appropriate for downstream device dt-bindings: PCI: brcmstb: Add property "brcm,clkreq-mode"
2 parents c94df62 + e2596dc commit 6f77f0a

File tree

2 files changed

+104
-10
lines changed

2 files changed

+104
-10
lines changed

Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,24 @@ properties:
6464

6565
aspm-no-l0s: true
6666

67+
brcm,clkreq-mode:
68+
description: A string that determines the operating
69+
clkreq mode of the PCIe RC HW with respect to controlling the refclk
70+
signal. There are three different modes -- "safe", which drives the
71+
refclk signal unconditionally and will work for all devices but does
72+
not provide any power savings; "no-l1ss" -- which provides Clock
73+
Power Management, L0s, and L1, but cannot provide L1 substate (L1SS)
74+
power savings. If the downstream device connected to the RC is L1SS
75+
capable AND the OS enables L1SS, all PCIe traffic may abruptly halt,
76+
potentially hanging the system; "default" -- which provides L0s, L1,
77+
and L1SS, but not compliant to provide Clock Power Management;
78+
specifically, may not be able to meet the T_CLRon max timing of 400ns
79+
as specified in "Dynamic Clock Control", section 3.2.5.2.2 PCI
80+
Express Mini CEM 2.1 specification. This situation is atypical and
81+
should happen only with older devices.
82+
$ref: /schemas/types.yaml#/definitions/string
83+
enum: [ safe, no-l1ss, default ]
84+
6785
brcm,scb-sizes:
6886
description: u64 giving the 64bit PCIe memory
6987
viewport size of a memory controller. There may be up to

drivers/pci/controller/pcie-brcmstb.c

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc
4949
#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00
5050

51+
#define PCIE_RC_CFG_PRIV1_ROOT_CAP 0x4f8
52+
#define PCIE_RC_CFG_PRIV1_ROOT_CAP_L1SS_MODE_MASK 0xf8
53+
5154
#define PCIE_RC_DL_MDIO_ADDR 0x1100
5255
#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
5356
#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
@@ -121,9 +124,12 @@
121124

122125
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
123126
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
127+
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK 0x200000
124128
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
125129
#define PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x00800000
126-
130+
#define PCIE_CLKREQ_MASK \
131+
(PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK | \
132+
PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK)
127133

128134
#define PCIE_INTR2_CPU_BASE 0x4300
129135
#define PCIE_MSI_INTR2_BASE 0x4500
@@ -1028,13 +1034,89 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
10281034
return 0;
10291035
}
10301036

1037+
/*
1038+
* This extends the timeout period for an access to an internal bus. This
1039+
* access timeout may occur during L1SS sleep periods, even without the
1040+
* presence of a PCIe access.
1041+
*/
1042+
static void brcm_extend_rbus_timeout(struct brcm_pcie *pcie)
1043+
{
1044+
/* TIMEOUT register is two registers before RGR1_SW_INIT_1 */
1045+
const unsigned int REG_OFFSET = PCIE_RGR1_SW_INIT_1(pcie) - 8;
1046+
u32 timeout_us = 4000000; /* 4 seconds, our setting for L1SS */
1047+
1048+
/* Each unit in timeout register is 1/216,000,000 seconds */
1049+
writel(216 * timeout_us, pcie->base + REG_OFFSET);
1050+
}
1051+
1052+
static void brcm_config_clkreq(struct brcm_pcie *pcie)
1053+
{
1054+
static const char err_msg[] = "invalid 'brcm,clkreq-mode' DT string\n";
1055+
const char *mode = "default";
1056+
u32 clkreq_cntl;
1057+
int ret, tmp;
1058+
1059+
ret = of_property_read_string(pcie->np, "brcm,clkreq-mode", &mode);
1060+
if (ret && ret != -EINVAL) {
1061+
dev_err(pcie->dev, err_msg);
1062+
mode = "safe";
1063+
}
1064+
1065+
/* Start out assuming safe mode (both mode bits cleared) */
1066+
clkreq_cntl = readl(pcie->base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
1067+
clkreq_cntl &= ~PCIE_CLKREQ_MASK;
1068+
1069+
if (strcmp(mode, "no-l1ss") == 0) {
1070+
/*
1071+
* "no-l1ss" -- Provides Clock Power Management, L0s, and
1072+
* L1, but cannot provide L1 substate (L1SS) power
1073+
* savings. If the downstream device connected to the RC is
1074+
* L1SS capable AND the OS enables L1SS, all PCIe traffic
1075+
* may abruptly halt, potentially hanging the system.
1076+
*/
1077+
clkreq_cntl |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK;
1078+
/*
1079+
* We want to un-advertise L1 substates because if the OS
1080+
* tries to configure the controller into using L1 substate
1081+
* power savings it may fail or hang when the RC HW is in
1082+
* "no-l1ss" mode.
1083+
*/
1084+
tmp = readl(pcie->base + PCIE_RC_CFG_PRIV1_ROOT_CAP);
1085+
u32p_replace_bits(&tmp, 2, PCIE_RC_CFG_PRIV1_ROOT_CAP_L1SS_MODE_MASK);
1086+
writel(tmp, pcie->base + PCIE_RC_CFG_PRIV1_ROOT_CAP);
1087+
1088+
} else if (strcmp(mode, "default") == 0) {
1089+
/*
1090+
* "default" -- Provides L0s, L1, and L1SS, but not
1091+
* compliant to provide Clock Power Management;
1092+
* specifically, may not be able to meet the Tclron max
1093+
* timing of 400ns as specified in "Dynamic Clock Control",
1094+
* section 3.2.5.2.2 of the PCIe spec. This situation is
1095+
* atypical and should happen only with older devices.
1096+
*/
1097+
clkreq_cntl |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK;
1098+
brcm_extend_rbus_timeout(pcie);
1099+
1100+
} else {
1101+
/*
1102+
* "safe" -- No power savings; refclk is driven by RC
1103+
* unconditionally.
1104+
*/
1105+
if (strcmp(mode, "safe") != 0)
1106+
dev_err(pcie->dev, err_msg);
1107+
mode = "safe";
1108+
}
1109+
writel(clkreq_cntl, pcie->base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
1110+
1111+
dev_info(pcie->dev, "clkreq-mode set to %s\n", mode);
1112+
}
1113+
10311114
static int brcm_pcie_start_link(struct brcm_pcie *pcie)
10321115
{
10331116
struct device *dev = pcie->dev;
10341117
void __iomem *base = pcie->base;
10351118
u16 nlw, cls, lnksta;
10361119
bool ssc_good = false;
1037-
u32 tmp;
10381120
int ret, i;
10391121

10401122
/* Unassert the fundamental reset */
@@ -1059,6 +1141,8 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie)
10591141
return -ENODEV;
10601142
}
10611143

1144+
brcm_config_clkreq(pcie);
1145+
10621146
if (pcie->gen)
10631147
brcm_pcie_set_gen(pcie, pcie->gen);
10641148

@@ -1077,14 +1161,6 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie)
10771161
pci_speed_string(pcie_link_speed[cls]), nlw,
10781162
ssc_good ? "(SSC)" : "(!SSC)");
10791163

1080-
/*
1081-
* Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
1082-
* is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1.
1083-
*/
1084-
tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
1085-
tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK;
1086-
writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
1087-
10881164
return 0;
10891165
}
10901166

0 commit comments

Comments
 (0)