1 From 049820d8a0c918cedd4524eda9abf750819ac901 Mon Sep 17 00:00:00 2001
2 From: Luo Jie <quic_luoj@quicinc.com>
3 Date: Tue, 26 Dec 2023 18:19:30 +0800
4 Subject: [PATCH 19/50] net: ethernet: qualcomm: Add PPE buffer manager
7 The BM (Buffer Management) config controls the pause frame generated
8 on the PPE port. There are maximum 15 BM ports and 4 groups supported,
9 all BM ports are assigned to group 0 by default. The number of hardware
10 buffers configured for the port influence the threshold of the flow
11 control for that port.
13 Change-Id: Ifb1b69c89966cf5cab19f8e2661c64a4dc6230fe
14 Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
16 drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +-
17 drivers/net/ethernet/qualcomm/ppe/ppe.c | 5 +
18 .../net/ethernet/qualcomm/ppe/ppe_config.c | 181 ++++++++++++++++++
19 .../net/ethernet/qualcomm/ppe/ppe_config.h | 10 +
20 drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 54 ++++++
21 5 files changed, 251 insertions(+), 1 deletion(-)
22 create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_config.c
23 create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_config.h
24 create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
26 diff --git a/drivers/net/ethernet/qualcomm/ppe/Makefile b/drivers/net/ethernet/qualcomm/ppe/Makefile
27 index 63d50d3b4f2e..410a7bb54cfe 100644
28 --- a/drivers/net/ethernet/qualcomm/ppe/Makefile
29 +++ b/drivers/net/ethernet/qualcomm/ppe/Makefile
33 obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
34 -qcom-ppe-objs := ppe.o
35 +qcom-ppe-objs := ppe.o ppe_config.o
36 diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet/qualcomm/ppe/ppe.c
37 index 14998ac771c7..443706291ce0 100644
38 --- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
39 +++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
41 #include <linux/reset.h>
44 +#include "ppe_config.h"
46 #define PPE_PORT_MAX 8
47 #define PPE_CLK_RATE 353000000
48 @@ -201,6 +202,10 @@ static int qcom_ppe_probe(struct platform_device *pdev)
50 return dev_err_probe(dev, ret, "PPE clock config failed\n");
52 + ret = ppe_hw_config(ppe_dev);
54 + return dev_err_probe(dev, ret, "PPE HW config failed\n");
56 platform_set_drvdata(pdev, ppe_dev);
59 diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
61 index 000000000000..0ba4efdfd509
63 +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
65 +// SPDX-License-Identifier: GPL-2.0-only
67 + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
70 +/* PPE HW initialization configs such as BM(buffer management),
71 + * QM(queue management) and scheduler configs.
74 +#include <linux/bitfield.h>
75 +#include <linux/bits.h>
76 +#include <linux/device.h>
77 +#include <linux/regmap.h>
80 +#include "ppe_config.h"
81 +#include "ppe_regs.h"
84 + * struct ppe_bm_port_config - PPE BM port configuration.
85 + * @port_id_start: The fist BM port ID to configure.
86 + * @port_id_end: The last BM port ID to configure.
87 + * @pre_alloc: BM port dedicated buffer number.
88 + * @in_fly_buf: Buffer number for receiving the packet after pause frame sent.
89 + * @ceil: Ceil to generate the back pressure.
90 + * @weight: Weight value.
91 + * @resume_offset: Resume offset from the threshold value.
92 + * @resume_ceil: Ceil to resume from the back pressure state.
93 + * @dynamic: Dynamic threshold used or not.
95 + * The is for configuring the threshold that impacts the port
98 +struct ppe_bm_port_config {
99 + unsigned int port_id_start;
100 + unsigned int port_id_end;
101 + unsigned int pre_alloc;
102 + unsigned int in_fly_buf;
104 + unsigned int weight;
105 + unsigned int resume_offset;
106 + unsigned int resume_ceil;
110 +static int ipq9574_ppe_bm_group_config = 1550;
111 +static struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = {
113 + .port_id_start = 0,
119 + .resume_offset = 8,
124 + .port_id_start = 1,
130 + .resume_offset = 36,
135 + .port_id_start = 8,
141 + .resume_offset = 36,
146 + .port_id_start = 14,
152 + .resume_offset = 36,
158 +static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
159 + struct ppe_bm_port_config port_cfg)
161 + u32 reg, val, bm_fc_val[2];
164 + /* Configure BM flow control related threshold */
165 + PPE_BM_PORT_FC_SET_WEIGHT(bm_fc_val, port_cfg.weight);
166 + PPE_BM_PORT_FC_SET_RESUME_OFFSET(bm_fc_val, port_cfg.resume_offset);
167 + PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(bm_fc_val, port_cfg.resume_ceil);
168 + PPE_BM_PORT_FC_SET_DYNAMIC(bm_fc_val, port_cfg.dynamic);
169 + PPE_BM_PORT_FC_SET_REACT_LIMIT(bm_fc_val, port_cfg.in_fly_buf);
170 + PPE_BM_PORT_FC_SET_PRE_ALLOC(bm_fc_val, port_cfg.pre_alloc);
172 + /* Ceiling is divided into the different register word. */
173 + val = FIELD_GET(GENMASK(2, 0), port_cfg.ceil);
174 + PPE_BM_PORT_FC_SET_CEILING_LOW(bm_fc_val, val);
175 + val = FIELD_GET(GENMASK(10, 3), port_cfg.ceil);
176 + PPE_BM_PORT_FC_SET_CEILING_HIGH(bm_fc_val, val);
178 + reg = PPE_BM_PORT_FC_CFG_ADDR + PPE_BM_PORT_FC_CFG_INC * bm_port_id;
179 + ret = regmap_bulk_write(ppe_dev->regmap, reg,
180 + bm_fc_val, ARRAY_SIZE(bm_fc_val));
184 + /* Assign the default group ID 0 to the BM port */
185 + val = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0);
186 + reg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id;
187 + ret = regmap_update_bits(ppe_dev->regmap, reg,
188 + PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID,
193 + /* Enable BM port flow control */
194 + val = FIELD_PREP(PPE_BM_PORT_FC_MODE_EN, true);
195 + reg = PPE_BM_PORT_FC_MODE_ADDR + PPE_BM_PORT_FC_MODE_INC * bm_port_id;
197 + return regmap_update_bits(ppe_dev->regmap, reg,
198 + PPE_BM_PORT_FC_MODE_EN,
202 +/* Configure the buffer threshold for the port flow control function. */
203 +static int ppe_config_bm(struct ppe_device *ppe_dev)
205 + unsigned int i, bm_port_id, port_cfg_cnt;
206 + struct ppe_bm_port_config *port_cfg;
210 + /* Configure the buffer number of group 0 by default. The buffer
211 + * number of group 1-3 is cleared to 0 after PPE reset on the probe
214 + reg = PPE_BM_SHARED_GROUP_CFG_ADDR;
215 + val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,
216 + ipq9574_ppe_bm_group_config);
217 + ret = regmap_update_bits(ppe_dev->regmap, reg,
218 + PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,
221 + goto bm_config_fail;
223 + port_cfg = ipq9574_ppe_bm_port_config;
224 + port_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config);
225 + for (i = 0; i < port_cfg_cnt; i++) {
226 + for (bm_port_id = port_cfg[i].port_id_start;
227 + bm_port_id <= port_cfg[i].port_id_end; bm_port_id++) {
228 + ret = ppe_config_bm_threshold(ppe_dev, bm_port_id,
231 + goto bm_config_fail;
238 + dev_err(ppe_dev->dev, "PPE BM config error %d\n", ret);
242 +int ppe_hw_config(struct ppe_device *ppe_dev)
244 + return ppe_config_bm(ppe_dev);
246 diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
248 index 000000000000..7e66019de799
250 +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
252 +/* SPDX-License-Identifier: GPL-2.0-only
254 + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
257 +#ifndef __PPE_CONFIG_H__
258 +#define __PPE_CONFIG_H__
260 +int ppe_hw_config(struct ppe_device *ppe_dev);
262 diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
264 index 000000000000..bf25e0acc0f6
266 +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
268 +/* SPDX-License-Identifier: GPL-2.0-only
270 + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
273 +/* PPE hardware register and table declarations. */
274 +#ifndef __PPE_REGS_H__
275 +#define __PPE_REGS_H__
277 +/* There are 15 BM ports and 4 BM groups supported by PPE,
278 + * BM port (0-7) is matched to EDMA port 0, BM port (8-13) is matched
279 + * to PPE physical port 1-6, BM port 14 is matched to EIP.
281 +#define PPE_BM_PORT_FC_MODE_ADDR 0x600100
282 +#define PPE_BM_PORT_FC_MODE_INC 0x4
283 +#define PPE_BM_PORT_FC_MODE_EN BIT(0)
285 +#define PPE_BM_PORT_GROUP_ID_ADDR 0x600180
286 +#define PPE_BM_PORT_GROUP_ID_INC 0x4
287 +#define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID GENMASK(1, 0)
289 +#define PPE_BM_SHARED_GROUP_CFG_ADDR 0x600290
290 +#define PPE_BM_SHARED_GROUP_CFG_INC 0x4
291 +#define PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT GENMASK(10, 0)
293 +#define PPE_BM_PORT_FC_CFG_ADDR 0x601000
294 +#define PPE_BM_PORT_FC_CFG_INC 0x10
295 +#define PPE_BM_PORT_FC_W0_REACT_LIMIT GENMASK(8, 0)
296 +#define PPE_BM_PORT_FC_W0_RESUME_THRESHOLD GENMASK(17, 9)
297 +#define PPE_BM_PORT_FC_W0_RESUME_OFFSET GENMASK(28, 18)
298 +#define PPE_BM_PORT_FC_W0_CEILING_LOW GENMASK(31, 29)
299 +#define PPE_BM_PORT_FC_W1_CEILING_HIGH GENMASK(7, 0)
300 +#define PPE_BM_PORT_FC_W1_WEIGHT GENMASK(10, 8)
301 +#define PPE_BM_PORT_FC_W1_DYNAMIC BIT(11)
302 +#define PPE_BM_PORT_FC_W1_PRE_ALLOC GENMASK(22, 12)
304 +#define PPE_BM_PORT_FC_SET_REACT_LIMIT(tbl_cfg, value) \
305 + u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_REACT_LIMIT)
306 +#define PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(tbl_cfg, value) \
307 + u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_RESUME_THRESHOLD)
308 +#define PPE_BM_PORT_FC_SET_RESUME_OFFSET(tbl_cfg, value) \
309 + u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_RESUME_OFFSET)
310 +#define PPE_BM_PORT_FC_SET_CEILING_LOW(tbl_cfg, value) \
311 + u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_CEILING_LOW)
312 +#define PPE_BM_PORT_FC_SET_CEILING_HIGH(tbl_cfg, value) \
313 + u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_CEILING_HIGH)
314 +#define PPE_BM_PORT_FC_SET_WEIGHT(tbl_cfg, value) \
315 + u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_WEIGHT)
316 +#define PPE_BM_PORT_FC_SET_DYNAMIC(tbl_cfg, value) \
317 + u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_DYNAMIC)
318 +#define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \
319 + u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC)