Skip to content

Commit 679e563

Browse files
P33Mpopcornmix
authored andcommitted
PCI: brcmstb: add support for BCM2712 priority forwarding
The BCM2712 root complexes can interpret priority signalling in two different ways, based on the incoming Traffic Class of a TLP. The TLP TCs are assigned to separate internal request/response queues, and assigned different AXI IDs. These queues can have outgoing AXI transactions tagged based on: - Static QoS values - Dynamic QoS through internal backpressure - Dynamic QoS with elevation based on Vendor Messages received by the RC The VDM mechanism is of limited use due to implementation bugs, but the implicit reordering due to separate ID assignment allows higher-priority traffic from an EP to overtake other traffic in the RC and rest of the system. RP1 assigns TCs based on its internal bus managers, and internally tags read requests to allow out-of-order completions, so these two features operate in concert to provide priority service to e.g. MIPI camera or display traffic. Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
1 parent 4a269b6 commit 679e563

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed

drivers/pci/controller/pcie-brcmstb.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,22 @@
213213
#define PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_PWRDN_SHIFT 0x0
214214

215215
/* BCM7712/2712-specific registers */
216+
217+
#define PCIE_RC_TL_VDM_CTL0 0x0a20
218+
#define PCIE_RC_TL_VDM_CTL0_VDM_ENABLED_MASK 0x10000
219+
#define PCIE_RC_TL_VDM_CTL0_VDM_IGNORETAG_MASK 0x20000
220+
#define PCIE_RC_TL_VDM_CTL0_VDM_IGNOREVNDRID_MASK 0x40000
221+
222+
#define PCIE_RC_TL_VDM_CTL1 0x0a0c
223+
#define PCIE_RC_TL_VDM_CTL1_VDM_VNDRID0_MASK 0x0000ffff
224+
#define PCIE_RC_TL_VDM_CTL1_VDM_VNDRID1_MASK 0xffff0000
225+
226+
#define PCIE_MISC_CTRL_1 0x40A0
227+
#define PCIE_MISC_CTRL_1_OUTBOUND_TC_MASK 0xf
228+
#define PCIE_MISC_CTRL_1_OUTBOUND_NO_SNOOP_MASK BIT(3)
229+
#define PCIE_MISC_CTRL_1_OUTBOUND_RO_MASK BIT(4)
230+
#define PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK BIT(5)
231+
216232
#define PCIE_MISC_UBUS_CTRL 0x40a4
217233
#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK BIT(13)
218234
#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK BIT(19)
@@ -221,6 +237,31 @@
221237

222238
#define PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT 0x405c
223239

240+
/* AXI priority forwarding - automatic level-based */
241+
#define PCIE_MISC_TC_QUEUE_TO_QOS_MAP(x) (0x4160 - (x) * 4)
242+
/* Defined in quarter-fullness */
243+
#define QUEUE_THRESHOLD_34_TO_QOS_MAP_SHIFT 12
244+
#define QUEUE_THRESHOLD_23_TO_QOS_MAP_SHIFT 8
245+
#define QUEUE_THRESHOLD_12_TO_QOS_MAP_SHIFT 4
246+
#define QUEUE_THRESHOLD_01_TO_QOS_MAP_SHIFT 0
247+
#define QUEUE_THRESHOLD_MASK 0xf
248+
249+
/* VDM messages indexing TCs to AXI priorities */
250+
/* Indexes 8-15 */
251+
#define PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_HI 0x4164
252+
/* Indexes 0-7 */
253+
#define PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_LO 0x4168
254+
#define VDM_PRIORITY_TO_QOS_MAP_SHIFT(x) (4 * (x))
255+
#define VDM_PRIORITY_TO_QOS_MAP_MASK 0xf
256+
257+
#define PCIE_MISC_AXI_INTF_CTRL 0x416C
258+
#define AXI_EN_RCLK_QOS_ARRAY_FIX BIT(13)
259+
#define AXI_EN_QOS_UPDATE_TIMING_FIX BIT(12)
260+
#define AXI_DIS_QOS_GATING_IN_MASTER BIT(11)
261+
#define AXI_REQFIFO_EN_QOS_PROPAGATION BIT(7)
262+
#define AXI_BRIDGE_LOW_LATENCY_MODE BIT(6)
263+
#define AXI_MASTER_MAX_OUTSTANDING_REQUESTS_MASK 0x3f
264+
224265
#define PCIE_MISC_AXI_READ_ERROR_DATA 0x4170
225266

226267
/* Forward declarations */
@@ -856,6 +897,7 @@ static int brcm_pcie_post_setup_bcm2712(struct brcm_pcie *pcie)
856897
const u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e };
857898
int ret, i;
858899
u32 tmp;
900+
u8 qos_map[8];
859901

860902
/* Allow a 54MHz (xosc) refclk source */
861903
ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET, 0x1600);
@@ -903,6 +945,84 @@ static int brcm_pcie_post_setup_bcm2712(struct brcm_pcie *pcie)
903945
writel(0xB2D0000, pcie->base + PCIE_MISC_UBUS_TIMEOUT);
904946
writel(0xABA0000, pcie->base + PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT);
905947

948+
/*
949+
* BCM2712 has a configurable QoS mechanism that assigns TLP Traffic Classes
950+
* to separate AXI IDs with a configurable priority scheme.
951+
* Dynamic priority elevation is supported through reception of Type 1
952+
* Vendor Defined Messages, but several bugs make this largely ineffective.
953+
*/
954+
955+
/* Disable broken forwarding search. Set chicken bits for 2712D0 */
956+
tmp = readl(pcie->base + PCIE_MISC_AXI_INTF_CTRL);
957+
tmp &= ~AXI_REQFIFO_EN_QOS_PROPAGATION;
958+
tmp |= AXI_EN_RCLK_QOS_ARRAY_FIX | AXI_EN_QOS_UPDATE_TIMING_FIX |
959+
AXI_DIS_QOS_GATING_IN_MASTER;
960+
writel(tmp, pcie->base + PCIE_MISC_AXI_INTF_CTRL);
961+
962+
/*
963+
* Work around spurious QoS=0 assignments to inbound traffic.
964+
* If the QOS_UPDATE_TIMING_FIX bit is Reserved-0, then this is a
965+
* 2712C1 chip, or a single-lane RC. Use the best-effort alternative
966+
* which is to partially throttle AXI requests in-flight to SDRAM.
967+
*/
968+
tmp = readl(pcie->base + PCIE_MISC_AXI_INTF_CTRL);
969+
if (!(tmp & AXI_EN_QOS_UPDATE_TIMING_FIX)) {
970+
tmp &= ~AXI_MASTER_MAX_OUTSTANDING_REQUESTS_MASK;
971+
tmp |= 15;
972+
writel(tmp, pcie->base + PCIE_MISC_AXI_INTF_CTRL);
973+
}
974+
975+
/* Disable VDM reception by default */
976+
tmp = readl(pcie->base + PCIE_MISC_CTRL_1);
977+
tmp &= ~PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK;
978+
writel(tmp, pcie->base + PCIE_MISC_CTRL_1);
979+
980+
if (!of_property_read_u8_array(pcie->np, "brcm,fifo-qos-map", qos_map, 4)) {
981+
982+
/*
983+
* Backpressure mode - each element is QoS for each
984+
* quartile of FIFO level. Each TC gets the same map, because
985+
* this mode is intended for nonrealtime EPs.
986+
*/
987+
tmp = 0;
988+
for (i = 0; i < 4; i++) {
989+
/* Priorities range from 0-15 */
990+
qos_map[i] &= 0x0f;
991+
tmp |= qos_map[i] << (i * 4);
992+
}
993+
for (i = 0; i < 8; i++)
994+
writel(tmp, pcie->base + PCIE_MISC_TC_QUEUE_TO_QOS_MAP(i));
995+
996+
} else if (!of_property_read_u8_array(pcie->np, "brcm,vdm-qos-map", qos_map, 8)) {
997+
/* Enable VDM reception */
998+
tmp = readl(pcie->base + PCIE_MISC_CTRL_1);
999+
tmp |= PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK;
1000+
writel(tmp, pcie->base + PCIE_MISC_CTRL_1);
1001+
1002+
tmp = 0;
1003+
for (i = 0; i < 8; i++) {
1004+
/* Priorities range from 0-15 */
1005+
qos_map[i] &= 0x0f;
1006+
tmp |= qos_map[i] << (i * 4);
1007+
}
1008+
/* Broken forwarding means no point separating panic priorities from normal */
1009+
writel(tmp, pcie->base + PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_LO);
1010+
writel(tmp, pcie->base + PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_HI);
1011+
1012+
/* Match Vendor ID of 0 */
1013+
writel(0, pcie->base + PCIE_RC_TL_VDM_CTL1);
1014+
1015+
/*
1016+
* Forward VDMs to priority interface anyway -
1017+
* useful for debugging starvation through the received VDM count fields.
1018+
*/
1019+
tmp = readl(pcie->base + PCIE_RC_TL_VDM_CTL0);
1020+
tmp |= PCIE_RC_TL_VDM_CTL0_VDM_ENABLED_MASK |
1021+
PCIE_RC_TL_VDM_CTL0_VDM_IGNORETAG_MASK |
1022+
PCIE_RC_TL_VDM_CTL0_VDM_IGNOREVNDRID_MASK;
1023+
writel(tmp, pcie->base + PCIE_RC_TL_VDM_CTL0);
1024+
}
1025+
9061026
return 0;
9071027
}
9081028

0 commit comments

Comments
 (0)