cc470b46b5b6f8c692042fa440fd180c88d5186d
[openwrt/staging/stintel.git] /
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
5 configuration
6
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.
12
13 Change-Id: Ifb1b69c89966cf5cab19f8e2661c64a4dc6230fe
14 Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
15 ---
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
25
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
30 @@ -4,4 +4,4 @@
31 #
32
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
40 @@ -15,6 +15,7 @@
41 #include <linux/reset.h>
42
43 #include "ppe.h"
44 +#include "ppe_config.h"
45
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)
49 if (ret)
50 return dev_err_probe(dev, ret, "PPE clock config failed\n");
51
52 + ret = ppe_hw_config(ppe_dev);
53 + if (ret)
54 + return dev_err_probe(dev, ret, "PPE HW config failed\n");
55 +
56 platform_set_drvdata(pdev, ppe_dev);
57
58 return 0;
59 diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
60 new file mode 100644
61 index 000000000000..0ba4efdfd509
62 --- /dev/null
63 +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
64 @@ -0,0 +1,181 @@
65 +// SPDX-License-Identifier: GPL-2.0-only
66 +/*
67 + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
68 + */
69 +
70 +/* PPE HW initialization configs such as BM(buffer management),
71 + * QM(queue management) and scheduler configs.
72 + */
73 +
74 +#include <linux/bitfield.h>
75 +#include <linux/bits.h>
76 +#include <linux/device.h>
77 +#include <linux/regmap.h>
78 +
79 +#include "ppe.h"
80 +#include "ppe_config.h"
81 +#include "ppe_regs.h"
82 +
83 +/**
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.
94 + *
95 + * The is for configuring the threshold that impacts the port
96 + * flow control.
97 + */
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;
103 + unsigned int ceil;
104 + unsigned int weight;
105 + unsigned int resume_offset;
106 + unsigned int resume_ceil;
107 + bool dynamic;
108 +};
109 +
110 +static int ipq9574_ppe_bm_group_config = 1550;
111 +static struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = {
112 + {
113 + .port_id_start = 0,
114 + .port_id_end = 0,
115 + .pre_alloc = 0,
116 + .in_fly_buf = 100,
117 + .ceil = 1146,
118 + .weight = 7,
119 + .resume_offset = 8,
120 + .resume_ceil = 0,
121 + .dynamic = true,
122 + },
123 + {
124 + .port_id_start = 1,
125 + .port_id_end = 7,
126 + .pre_alloc = 0,
127 + .in_fly_buf = 100,
128 + .ceil = 250,
129 + .weight = 4,
130 + .resume_offset = 36,
131 + .resume_ceil = 0,
132 + .dynamic = true,
133 + },
134 + {
135 + .port_id_start = 8,
136 + .port_id_end = 13,
137 + .pre_alloc = 0,
138 + .in_fly_buf = 128,
139 + .ceil = 250,
140 + .weight = 4,
141 + .resume_offset = 36,
142 + .resume_ceil = 0,
143 + .dynamic = true,
144 + },
145 + {
146 + .port_id_start = 14,
147 + .port_id_end = 14,
148 + .pre_alloc = 0,
149 + .in_fly_buf = 40,
150 + .ceil = 250,
151 + .weight = 4,
152 + .resume_offset = 36,
153 + .resume_ceil = 0,
154 + .dynamic = true,
155 + },
156 +};
157 +
158 +static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
159 + struct ppe_bm_port_config port_cfg)
160 +{
161 + u32 reg, val, bm_fc_val[2];
162 + int ret;
163 +
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);
171 +
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);
177 +
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));
181 + if (ret)
182 + return ret;
183 +
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,
189 + val);
190 + if (ret)
191 + return ret;
192 +
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;
196 +
197 + return regmap_update_bits(ppe_dev->regmap, reg,
198 + PPE_BM_PORT_FC_MODE_EN,
199 + val);
200 +}
201 +
202 +/* Configure the buffer threshold for the port flow control function. */
203 +static int ppe_config_bm(struct ppe_device *ppe_dev)
204 +{
205 + unsigned int i, bm_port_id, port_cfg_cnt;
206 + struct ppe_bm_port_config *port_cfg;
207 + u32 reg, val;
208 + int ret;
209 +
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
212 + * of PPE driver.
213 + */
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,
219 + val);
220 + if (ret)
221 + goto bm_config_fail;
222 +
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,
229 + port_cfg[i]);
230 + if (ret)
231 + goto bm_config_fail;
232 + }
233 + }
234 +
235 + return 0;
236 +
237 +bm_config_fail:
238 + dev_err(ppe_dev->dev, "PPE BM config error %d\n", ret);
239 + return ret;
240 +}
241 +
242 +int ppe_hw_config(struct ppe_device *ppe_dev)
243 +{
244 + return ppe_config_bm(ppe_dev);
245 +}
246 diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
247 new file mode 100644
248 index 000000000000..7e66019de799
249 --- /dev/null
250 +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
251 @@ -0,0 +1,10 @@
252 +/* SPDX-License-Identifier: GPL-2.0-only
253 + *
254 + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
255 + */
256 +
257 +#ifndef __PPE_CONFIG_H__
258 +#define __PPE_CONFIG_H__
259 +
260 +int ppe_hw_config(struct ppe_device *ppe_dev);
261 +#endif
262 diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
263 new file mode 100644
264 index 000000000000..bf25e0acc0f6
265 --- /dev/null
266 +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
267 @@ -0,0 +1,54 @@
268 +/* SPDX-License-Identifier: GPL-2.0-only
269 + *
270 + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
271 + */
272 +
273 +/* PPE hardware register and table declarations. */
274 +#ifndef __PPE_REGS_H__
275 +#define __PPE_REGS_H__
276 +
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.
280 + */
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)
284 +
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)
288 +
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)
292 +
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)
303 +
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)
320 +
321 +#endif
322 --
323 2.45.2
324