[PATCH net-next 06/11] net: ethernet: qualcomm: ppe: Add IPQ5424 BM buffer configuration

From: Luo Jie

Date: Thu Oct 08 2026 - 10:59:19 EST


IPQ5424 has fewer PPE ports than IPQ9574, so it requires a different buffer
configuration per port, and more buffers are left for the shared buffer
pool. IPQ5424 also has more BM ports than IPQ9574, 19 versus 15, so some BM
register tables have more entries on IPQ5424, and some of them are located
at different addresses.

Signed-off-by: Luo Jie <jie.luo@xxxxxxxxxxxxxxxx>
---
drivers/net/ethernet/qualcomm/ppe/ppe.c | 5 ++
drivers/net/ethernet/qualcomm/ppe/ppe.h | 15 ++++
drivers/net/ethernet/qualcomm/ppe/ppe_config.c | 96 ++++++++++++++++++++++----
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 35 +++++++---
4 files changed, 131 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet/qualcomm/ppe/ppe.c
index f71b673b6f97..b144fd818998 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
@@ -28,6 +28,7 @@

/**
* struct ppe_of_data - PPE private data of IPQ SoC
+ * @type: PPE type value
* @ppe_rate: PPE clock rate
* @num_ports: Number of PPE ports
* @regmap_config: Regmap configuration
@@ -35,6 +36,7 @@
* @num_icc_paths: Number of ICC paths
*/
struct ppe_of_data {
+ enum ppe_type type;
unsigned long ppe_rate;
int num_ports;
const struct regmap_config *regmap_config;
@@ -275,6 +277,7 @@ static int qcom_ppe_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(ppe_dev->regmap),
"PPE initialize regmap failed\n");
ppe_dev->dev = dev;
+ ppe_dev->type = data->type;
ppe_dev->clk_rate = data->ppe_rate;
ppe_dev->num_ports = data->num_ports;
ppe_dev->num_icc_paths = data->num_icc_paths;
@@ -302,6 +305,7 @@ static void qcom_ppe_remove(struct platform_device *pdev)
}

static const struct ppe_of_data ipq9574_data = {
+ .type = IPQ9574_PPE,
.ppe_rate = IPQ9574_PPE_CLK_RATE,
.num_ports = IPQ9574_PPE_PORT_MAX,
.regmap_config = &regmap_config_ipq9574,
@@ -310,6 +314,7 @@ static const struct ppe_of_data ipq9574_data = {
};

static const struct ppe_of_data ipq5424_data = {
+ .type = IPQ5424_PPE,
.ppe_rate = IPQ5424_PPE_CLK_RATE,
.num_ports = IPQ5424_PPE_PORT_MAX,
.regmap_config = &regmap_config_ipq5424,
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.h b/drivers/net/ethernet/qualcomm/ppe/ppe.h
index 27458f0bc206..33b876d2e079 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h
@@ -13,10 +13,24 @@ struct device;
struct regmap;
struct dentry;

+/**
+ * enum ppe_type - PPE device type.
+ * @IPQ9574_PPE: PPE device of IPQ9574.
+ * @IPQ5424_PPE: PPE device of IPQ5424.
+ *
+ * PPE type is used to identify the PPE device of the different
+ * IPQ platform.
+ */
+enum ppe_type {
+ IPQ9574_PPE,
+ IPQ5424_PPE,
+};
+
/**
* struct ppe_device - PPE device private data.
* @dev: PPE device structure.
* @regmap: PPE register map.
+ * @type: Different PPE type on various IPQ SoC.
* @clk_rate: PPE clock rate.
* @num_ports: Number of PPE ports.
* @debugfs_root: Debugfs root entry.
@@ -30,6 +44,7 @@ struct dentry;
struct ppe_device {
struct device *dev;
struct regmap *regmap;
+ enum ppe_type type;
unsigned long clk_rate;
unsigned int num_ports;
struct dentry *debugfs_root;
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
index 8a553902ffad..3afa57119323 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
@@ -230,6 +230,56 @@ static const struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = {
},
};

+/* IPQ5424 has fewer PPE physical ports (3) than IPQ9574 (6), so fewer
+ * buffers need to be reserved for per-port purposes. Out of the same
+ * 2048 total, the rest assigned to the general 'group0' pool is
+ * correspondingly larger here, 1650 versus IPQ9574's 1550.
+ */
+static const int ipq5424_ppe_bm_group_config = 1650;
+
+/* The buffer configurations per PPE port on IPQ5424. There are 19 BM
+ * ports supported by PPE. BM port (0-15) is for EDMA port 0, and BM
+ * port (16-18) is for the 3 PPE physical ports.
+ */
+static const struct ppe_bm_port_config ipq5424_ppe_bm_port_config[] = {
+ {
+ /* Buffer configuration for the BM port ID 0 of EDMA. */
+ .port_id_start = 0,
+ .port_id_end = 0,
+ .pre_alloc = 0,
+ .in_fly_buf = 100,
+ .ceil = 1146,
+ .weight = 7,
+ .resume_offset = 8,
+ .resume_ceil = 0,
+ .dynamic = true,
+ },
+ {
+ /* Buffer configuration for the BM port ID 1-15 of EDMA. */
+ .port_id_start = 1,
+ .port_id_end = 15,
+ .pre_alloc = 0,
+ .in_fly_buf = 100,
+ .ceil = 250,
+ .weight = 4,
+ .resume_offset = 36,
+ .resume_ceil = 0,
+ .dynamic = true,
+ },
+ {
+ /* Buffer configuration for the BM port ID 16-18 of PPE ports. */
+ .port_id_start = 16,
+ .port_id_end = 18,
+ .pre_alloc = 0,
+ .in_fly_buf = 128,
+ .ceil = 250,
+ .weight = 4,
+ .resume_offset = 36,
+ .resume_ceil = 0,
+ .dynamic = true,
+ },
+};
+
/* QM fetches the packet from PPE buffer management for transmitting the
* packet out. The QM group configuration limits the total number of buffers
* enqueued by all PPE hardware queues.
@@ -1413,7 +1463,7 @@ static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,

/* Assign the default group ID 0 to the BM port. */
val = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0);
- reg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id;
+ reg = PPE_BM_PORT_GROUP_ID_ADDR(ppe_dev) + PPE_BM_PORT_GROUP_ID_INC * bm_port_id;
ret = regmap_update_bits(ppe_dev->regmap, reg,
PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID,
val);
@@ -1431,25 +1481,38 @@ static int ppe_config_bm(struct ppe_device *ppe_dev)
{
const struct ppe_bm_port_config *port_cfg;
unsigned int i, bm_port_id, port_cfg_cnt;
- u32 reg, val;
+ u32 reg, val, group_cfg;
int ret;

+ switch (ppe_dev->type) {
+ case IPQ9574_PPE:
+ port_cfg = ipq9574_ppe_bm_port_config;
+ port_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config);
+ group_cfg = ipq9574_ppe_bm_group_config;
+ break;
+ case IPQ5424_PPE:
+ port_cfg = ipq5424_ppe_bm_port_config;
+ port_cfg_cnt = ARRAY_SIZE(ipq5424_ppe_bm_port_config);
+ group_cfg = ipq5424_ppe_bm_group_config;
+ break;
+ default:
+ dev_err(ppe_dev->dev, "Invalid PPE type %d\n", ppe_dev->type);
+ return -EINVAL;
+ }
+
+ reg = PPE_BM_SHARED_GROUP_CFG_ADDR(ppe_dev);
+
/* Configure the allocated buffer number only for group 0.
* The buffer number of group 1-3 is already cleared to 0
* after PPE reset during the probe of PPE driver.
*/
- reg = PPE_BM_SHARED_GROUP_CFG_ADDR;
- val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,
- ipq9574_ppe_bm_group_config);
+ val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, group_cfg);
ret = regmap_update_bits(ppe_dev->regmap, reg,
PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,
val);
if (ret)
goto bm_config_fail;

- /* Configure buffer thresholds for the BM ports. */
- port_cfg = ipq9574_ppe_bm_port_config;
- port_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config);
for (i = 0; i < port_cfg_cnt; i++) {
for (bm_port_id = port_cfg[i].port_id_start;
bm_port_id <= port_cfg[i].port_id_end; bm_port_id++) {
@@ -1472,12 +1535,23 @@ static int ppe_config_bm(struct ppe_device *ppe_dev)
*/
static int ppe_config_qm(struct ppe_device *ppe_dev)
{
+ int ret, i, group_buffer_cfg, queue_id, queue_cfg_count;
const struct ppe_qm_queue_config *queue_cfg;
- int ret, i, queue_id, queue_cfg_count;
u32 reg, multicast_queue_cfg[5];
u32 unicast_queue_cfg[4];
u32 group_cfg[3];

+ switch (ppe_dev->type) {
+ case IPQ9574_PPE:
+ group_buffer_cfg = ipq9574_ppe_qm_group_config;
+ queue_cfg = ipq9574_ppe_qm_queue_config;
+ queue_cfg_count = ARRAY_SIZE(ipq9574_ppe_qm_queue_config);
+ break;
+ default:
+ dev_err(ppe_dev->dev, "Invalid PPE type %d\n", ppe_dev->type);
+ return -EINVAL;
+ }
+
/* Assign the buffer number to the group 0 by default. */
reg = PPE_AC_GRP_CFG_TBL_ADDR;
ret = regmap_bulk_read(ppe_dev->regmap, reg,
@@ -1485,15 +1559,13 @@ static int ppe_config_qm(struct ppe_device *ppe_dev)
if (ret)
goto qm_config_fail;

- PPE_AC_GRP_SET_BUF_LIMIT(group_cfg, ipq9574_ppe_qm_group_config);
+ PPE_AC_GRP_SET_BUF_LIMIT(group_cfg, group_buffer_cfg);

ret = regmap_bulk_write(ppe_dev->regmap, reg,
group_cfg, ARRAY_SIZE(group_cfg));
if (ret)
goto qm_config_fail;

- queue_cfg = ipq9574_ppe_qm_queue_config;
- queue_cfg_count = ARRAY_SIZE(ipq9574_ppe_qm_queue_config);
for (i = 0; i < queue_cfg_count; i++) {
queue_id = queue_cfg[i].queue_start;

diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
index 746dfbb5a682..441e8e04a80b 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
@@ -386,17 +386,32 @@
#define PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT_EN BIT(16)
#define PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT GENMASK(20, 17)

-/* There are 15 BM ports and 4 BM groups supported by PPE.
- * BM port (0-7) is for EDMA port 0, BM port (8-13) is for
- * PPE physical port 1-6 and BM port 14 is for EIP port.
+/* There are 15 BM ports on IPQ9574 and 19 BM ports on IPQ5424, and
+ * 4 BM groups supported by PPE. On IPQ9574, BM port (0-7) is for EDMA
+ * port 0, BM port (8-13) is for PPE physical port 1-6 and BM port 14
+ * is for EIP port. On IPQ5424, BM port (0-15) is for EDMA port 0 and
+ * BM port (16-18) is for PPE physical port 1-3.
+ *
+ * The per-BM-port tables PPE_BM_PORT_FC_MODE and PPE_BM_PORT_FC_CFG_TBL
+ * are at the same address on both SoCs, IPQ5424 only has more entries.
*/
+#define PPE_BM_PORT_IPQ9574_ENTRIES 15
+#define PPE_BM_PORT_IPQ5424_ENTRIES 19
+#define PPE_BM_PORT_ENTRIES(ppe_dev) \
+ ((ppe_dev)->type == IPQ5424_PPE ? PPE_BM_PORT_IPQ5424_ENTRIES : \
+ PPE_BM_PORT_IPQ9574_ENTRIES)
+
#define PPE_BM_PORT_FC_MODE_ADDR 0x600100
-#define PPE_BM_PORT_FC_MODE_ENTRIES 15
+#define PPE_BM_PORT_FC_MODE_ENTRIES(ppe_dev) PPE_BM_PORT_ENTRIES(ppe_dev)
#define PPE_BM_PORT_FC_MODE_INC 0x4
#define PPE_BM_PORT_FC_MODE_EN BIT(0)

-#define PPE_BM_PORT_GROUP_ID_ADDR 0x600180
-#define PPE_BM_PORT_GROUP_ID_ENTRIES 15
+#define PPE_BM_PORT_GROUP_ID_IPQ9574_ADDR 0x600180
+#define PPE_BM_PORT_GROUP_ID_IPQ5424_ADDR 0x6001c0
+#define PPE_BM_PORT_GROUP_ID_ADDR(ppe_dev) \
+ ((ppe_dev)->type == IPQ5424_PPE ? PPE_BM_PORT_GROUP_ID_IPQ5424_ADDR : \
+ PPE_BM_PORT_GROUP_ID_IPQ9574_ADDR)
+#define PPE_BM_PORT_GROUP_ID_ENTRIES(ppe_dev) PPE_BM_PORT_ENTRIES(ppe_dev)
#define PPE_BM_PORT_GROUP_ID_INC 0x4
#define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID GENMASK(1, 0)

@@ -412,13 +427,17 @@
#define PPE_BM_REACT_CNT_TBL_INC 0x4
#define PPE_BM_REACT_CNT_VAL GENMASK(8, 0)

-#define PPE_BM_SHARED_GROUP_CFG_ADDR 0x600290
+#define PPE_BM_SHARED_GROUP_CFG_IPQ9574_ADDR 0x600290
+#define PPE_BM_SHARED_GROUP_CFG_IPQ5424_ADDR 0x6002f0
+#define PPE_BM_SHARED_GROUP_CFG_ADDR(ppe_dev) \
+ ((ppe_dev)->type == IPQ5424_PPE ? PPE_BM_SHARED_GROUP_CFG_IPQ5424_ADDR : \
+ PPE_BM_SHARED_GROUP_CFG_IPQ9574_ADDR)
#define PPE_BM_SHARED_GROUP_CFG_ENTRIES 4
#define PPE_BM_SHARED_GROUP_CFG_INC 0x4
#define PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT GENMASK(10, 0)

#define PPE_BM_PORT_FC_CFG_TBL_ADDR 0x601000
-#define PPE_BM_PORT_FC_CFG_TBL_ENTRIES 15
+#define PPE_BM_PORT_FC_CFG_TBL_ENTRIES(ppe_dev) PPE_BM_PORT_ENTRIES(ppe_dev)
#define PPE_BM_PORT_FC_CFG_TBL_INC 0x10
#define PPE_BM_PORT_FC_W0_REACT_LIMIT GENMASK(8, 0)
#define PPE_BM_PORT_FC_W0_RESUME_THRESHOLD GENMASK(17, 9)

--
2.43.0