mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Til Kaiser <mail@tk154.de>
To: netdev@vger.kernel.org
Cc: Luo Jie <jie.luo@oss.qualcomm.com>,
	Andrew Lunn <andrew+netdev@lunn.ch>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@kernel.org>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	Simon Horman <horms@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
	Shuah Khan <skhan@linuxfoundation.org>,
	Randy Dunlap <rdunlap@infradead.org>,
	Lei Wei <quic_leiwei@quicinc.com>,
	Suruchi Agarwal <quic_suruchia@quicinc.com>,
	Pavithra R <quic_pavir@quicinc.com>,
	linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
	Til Kaiser <mail@tk154.de>
Subject: [PATCH net-next 1/4] net: ethernet: qualcomm: ppe: Select hardware configuration by SoC
Date: Mon,  5 Oct 2026 17:29:12 +0200	[thread overview]
Message-ID: <20261005152915.101780-2-mail@tk154.de> (raw)
In-Reply-To: <20261005152915.101780-1-mail@tk154.de>

The PPE driver hardcodes IPQ9574 parameters: the PPE clock rate,
interconnect paths, port count, buffer limits and scheduler arbitration
tables. Other SoCs with the same PPE architecture need different values.

Move these into per-SoC platform match data, and collect the buffer
manager (BM), queue manager (QM) and scheduler tables in a new struct
ppe_soc_config that is passed to the hardware initialization code. The
IPQ9574 values are unchanged; no functional change intended.

The IPQ9574 scheduler resource table has nine entries, with the reserved
pool at index 8. Select that final entry for port ID num_ports, preserving
the IPQ9574 lookup while allowing a smaller port count on other SoCs.

Rename regmap_config_ipq9574 to ppe_reg_config for the shared PPE
register layout.

Signed-off-by: Til Kaiser <mail@tk154.de>
---
 drivers/net/ethernet/qualcomm/ppe/ppe.c       | 48 ++++++++++-----
 .../net/ethernet/qualcomm/ppe/ppe_config.c    | 58 +++++++++++++------
 .../net/ethernet/qualcomm/ppe/ppe_config.h    | 34 ++++++++++-
 3 files changed, 106 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet/qualcomm/ppe/ppe.c
index 3c301e609d3e..0ef72c20364b 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
@@ -18,13 +19,15 @@
 #include "ppe_config.h"
 #include "ppe_debugfs.h"
 
-#define PPE_PORT_MAX		8
-#define PPE_CLK_RATE		353000000
+struct ppe_plat_data {
+	const struct ppe_soc_config *soc_cfg;
+	const struct icc_bulk_data *icc_data;
+	unsigned long ppe_clk_rate;
+	unsigned int num_icc, num_ports;
+};
 
-/* ICC clocks for enabling PPE device. The avg_bw and peak_bw with value 0
- * will be updated by the clock rate of PPE.
- */
-static const struct icc_bulk_data ppe_icc_data[] = {
+/* IPQ9574 interconnect paths. Zero bandwidths use the PPE clock rate. */
+static const struct icc_bulk_data ipq9574_icc_data[] = {
 	{
 		.name = "ppe",
 		.avg_bw = 0,
@@ -62,6 +65,15 @@ static const struct icc_bulk_data ppe_icc_data[] = {
 	},
 };
 
+static const struct ppe_plat_data ipq9574_ppe_data = {
+	.soc_cfg = &ipq9574_soc_config,
+	.icc_data = ipq9574_icc_data,
+	.ppe_clk_rate = 353000000,
+	.num_icc = ARRAY_SIZE(ipq9574_icc_data),
+	.num_ports = 8,
+};
+
+/* PPE register access ranges. */
 static const struct regmap_range ppe_readable_ranges[] = {
 	regmap_reg_range(0x0, 0x1ff),		/* Global */
 	regmap_reg_range(0x400, 0x5ff),		/* LPI CSR */
@@ -99,7 +111,7 @@ static const struct regmap_access_table ppe_reg_table = {
 	.n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges),
 };
 
-static const struct regmap_config regmap_config_ipq9574 = {
+static const struct regmap_config ppe_reg_config = {
 	.reg_bits = 32,
 	.reg_stride = 4,
 	.val_bits = 32,
@@ -108,7 +120,8 @@ static const struct regmap_config regmap_config_ipq9574 = {
 	.max_register = 0xbef800,
 };
 
-static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
+static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev,
+				    const struct icc_bulk_data *ppe_icc_data)
 {
 	unsigned long ppe_rate = ppe_dev->clk_rate;
 	struct device *dev = ppe_dev->dev;
@@ -172,12 +185,17 @@ static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
 
 static int qcom_ppe_probe(struct platform_device *pdev)
 {
+	const struct ppe_plat_data *plat_data;
 	struct device *dev = &pdev->dev;
 	struct ppe_device *ppe_dev;
 	void __iomem *base;
 	int ret, num_icc;
 
-	num_icc = ARRAY_SIZE(ppe_icc_data);
+	plat_data = device_get_match_data(dev);
+	if (!plat_data)
+		return -EINVAL;
+
+	num_icc = plat_data->num_icc;
 	ppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc),
 			       GFP_KERNEL);
 	if (!ppe_dev)
@@ -187,20 +205,20 @@ static int qcom_ppe_probe(struct platform_device *pdev)
 	if (IS_ERR(base))
 		return dev_err_probe(dev, PTR_ERR(base), "PPE ioremap failed\n");
 
-	ppe_dev->regmap = devm_regmap_init_mmio(dev, base, &regmap_config_ipq9574);
+	ppe_dev->regmap = devm_regmap_init_mmio(dev, base, &ppe_reg_config);
 	if (IS_ERR(ppe_dev->regmap))
 		return dev_err_probe(dev, PTR_ERR(ppe_dev->regmap),
 				     "PPE initialize regmap failed\n");
 	ppe_dev->dev = dev;
-	ppe_dev->clk_rate = PPE_CLK_RATE;
-	ppe_dev->num_ports = PPE_PORT_MAX;
+	ppe_dev->clk_rate = plat_data->ppe_clk_rate;
+	ppe_dev->num_ports = plat_data->num_ports;
 	ppe_dev->num_icc_paths = num_icc;
 
-	ret = ppe_clock_init_and_reset(ppe_dev);
+	ret = ppe_clock_init_and_reset(ppe_dev, plat_data->icc_data);
 	if (ret)
 		return dev_err_probe(dev, ret, "PPE clock config failed\n");
 
-	ret = ppe_hw_config(ppe_dev);
+	ret = ppe_hw_config(ppe_dev, plat_data->soc_cfg);
 	if (ret)
 		return dev_err_probe(dev, ret, "PPE HW config failed\n");
 
@@ -219,7 +237,7 @@ static void qcom_ppe_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id qcom_ppe_of_match[] = {
-	{ .compatible = "qcom,ipq9574-ppe" },
+	{ .compatible = "qcom,ipq9574-ppe", .data = &ipq9574_ppe_data },
 	{}
 };
 MODULE_DEVICE_TABLE(of, qcom_ppe_of_match);
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
index 125b73be92b1..65ac6c0841d5 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
@@ -835,6 +835,19 @@ static const struct ppe_port_schedule_resource ppe_scheduler_res[] = {
 	},
 };
 
+const struct ppe_soc_config ipq9574_soc_config = {
+	.bm_group_config = ipq9574_ppe_bm_group_config,
+	.bm_port_config = ipq9574_ppe_bm_port_config,
+	.bm_port_config_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config),
+	.qm_group_config = ipq9574_ppe_qm_group_config,
+	.qm_queue_config = ipq9574_ppe_qm_queue_config,
+	.qm_queue_config_cnt = ARRAY_SIZE(ipq9574_ppe_qm_queue_config),
+	.sch_bm_config = ipq9574_ppe_sch_bm_config,
+	.sch_bm_config_cnt = ARRAY_SIZE(ipq9574_ppe_sch_bm_config),
+	.sch_qm_config = ipq9574_ppe_sch_qm_config,
+	.sch_qm_config_cnt = ARRAY_SIZE(ipq9574_ppe_sch_qm_config),
+};
+
 /* Set the PPE queue level scheduler configuration. */
 static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev,
 					  int node_id, int port,
@@ -1080,7 +1093,12 @@ int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,
 	if (port > ppe_dev->num_ports)
 		return -EINVAL;
 
-	res = ppe_scheduler_res[port];
+	/* Port ID num_ports selects the reserved pool in the final entry. */
+	if (port == ppe_dev->num_ports)
+		res = ppe_scheduler_res[ARRAY_SIZE(ppe_scheduler_res) - 1];
+	else
+		res = ppe_scheduler_res[port];
+
 	switch (type) {
 	case PPE_RES_UCAST:
 		*res_start = res.ucastq_start;
@@ -1427,7 +1445,8 @@ static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
 }
 
 /* Configure the buffer threshold for the port flow control function. */
-static int ppe_config_bm(struct ppe_device *ppe_dev)
+static int ppe_config_bm(struct ppe_device *ppe_dev,
+			 const struct ppe_soc_config *soc_cfg)
 {
 	const struct ppe_bm_port_config *port_cfg;
 	unsigned int i, bm_port_id, port_cfg_cnt;
@@ -1440,7 +1459,7 @@ static int ppe_config_bm(struct ppe_device *ppe_dev)
 	 */
 	reg = PPE_BM_SHARED_GROUP_CFG_ADDR;
 	val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,
-			 ipq9574_ppe_bm_group_config);
+			 soc_cfg->bm_group_config);
 	ret = regmap_update_bits(ppe_dev->regmap, reg,
 				 PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,
 				 val);
@@ -1448,8 +1467,8 @@ static int ppe_config_bm(struct ppe_device *ppe_dev)
 		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);
+	port_cfg = soc_cfg->bm_port_config;
+	port_cfg_cnt = soc_cfg->bm_port_config_cnt;
 	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++) {
@@ -1470,7 +1489,8 @@ static int ppe_config_bm(struct ppe_device *ppe_dev)
 /* Configure PPE hardware queue depth, which is decided by the threshold
  * of queue.
  */
-static int ppe_config_qm(struct ppe_device *ppe_dev)
+static int ppe_config_qm(struct ppe_device *ppe_dev,
+			 const struct ppe_soc_config *soc_cfg)
 {
 	const struct ppe_qm_queue_config *queue_cfg;
 	int ret, i, queue_id, queue_cfg_count;
@@ -1485,15 +1505,15 @@ 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, soc_cfg->qm_group_config);
 
 	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);
+	queue_cfg = soc_cfg->qm_queue_config;
+	queue_cfg_count = soc_cfg->qm_queue_config_cnt;
 	for (i = 0; i < queue_cfg_count; i++) {
 		queue_id = queue_cfg[i].queue_start;
 
@@ -1625,7 +1645,8 @@ static int ppe_node_scheduler_config(struct ppe_device *ppe_dev,
 /* Initialize scheduler settings for PPE buffer utilization and dispatching
  * packet on PPE queue.
  */
-static int ppe_config_scheduler(struct ppe_device *ppe_dev)
+static int ppe_config_scheduler(struct ppe_device *ppe_dev,
+				const struct ppe_soc_config *soc_cfg)
 {
 	const struct ppe_scheduler_port_config *port_cfg;
 	const struct ppe_scheduler_qm_config *qm_cfg;
@@ -1633,8 +1654,8 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev)
 	int ret, i, count;
 	u32 val, reg;
 
-	count = ARRAY_SIZE(ipq9574_ppe_sch_bm_config);
-	bm_cfg = ipq9574_ppe_sch_bm_config;
+	count = soc_cfg->sch_bm_config_cnt;
+	bm_cfg = soc_cfg->sch_bm_config;
 
 	/* Configure the depth of BM scheduler entries. */
 	val = FIELD_PREP(PPE_BM_SCH_CTRL_SCH_DEPTH, count);
@@ -1664,8 +1685,8 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev)
 			goto sch_config_fail;
 	}
 
-	count = ARRAY_SIZE(ipq9574_ppe_sch_qm_config);
-	qm_cfg = ipq9574_ppe_sch_qm_config;
+	count = soc_cfg->sch_qm_config_cnt;
+	qm_cfg = soc_cfg->sch_qm_config;
 
 	/* Configure the depth of QM scheduler entries. */
 	val = FIELD_PREP(PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH, count);
@@ -1995,19 +2016,20 @@ static int ppe_bridge_init(struct ppe_device *ppe_dev)
 	return 0;
 }
 
-int ppe_hw_config(struct ppe_device *ppe_dev)
+int ppe_hw_config(struct ppe_device *ppe_dev,
+		  const struct ppe_soc_config *soc_cfg)
 {
 	int ret;
 
-	ret = ppe_config_bm(ppe_dev);
+	ret = ppe_config_bm(ppe_dev, soc_cfg);
 	if (ret)
 		return ret;
 
-	ret = ppe_config_qm(ppe_dev);
+	ret = ppe_config_qm(ppe_dev, soc_cfg);
 	if (ret)
 		return ret;
 
-	ret = ppe_config_scheduler(ppe_dev);
+	ret = ppe_config_scheduler(ppe_dev, soc_cfg);
 	if (ret)
 		return ret;
 
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
index 60493e51e0a4..0dafab264743 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
@@ -287,7 +287,39 @@ struct ppe_rss_hash_cfg {
 	u8 hash_fin_outer[PPE_RSS_HASH_TUPLES];
 };
 
-int ppe_hw_config(struct ppe_device *ppe_dev);
+/**
+ * struct ppe_soc_config - SoC-specific PPE hardware configuration.
+ * @bm_group_config: Buffer Management (BM) group configuration.
+ * @bm_port_config: Pointer to the BM port configuration array.
+ * @bm_port_config_cnt: Number of entries in the BM port configuration array.
+ * @qm_group_config: Queue Management (QM) group configuration.
+ * @qm_queue_config: Pointer to the QM queue configuration array.
+ * @qm_queue_config_cnt: Number of entries in the QM queue configuration array.
+ * @sch_bm_config: Pointer to the BM scheduler arbitration array.
+ * @sch_bm_config_cnt: Number of entries in the BM scheduler arbitration array.
+ * @sch_qm_config: Pointer to the QM scheduler arbitration array.
+ * @sch_qm_config_cnt: Number of entries in the QM scheduler arbitration array.
+ */
+struct ppe_soc_config {
+	int bm_group_config;
+	const struct ppe_bm_port_config *bm_port_config;
+	unsigned int bm_port_config_cnt;
+
+	int qm_group_config;
+	const struct ppe_qm_queue_config *qm_queue_config;
+	unsigned int qm_queue_config_cnt;
+
+	const struct ppe_scheduler_bm_config *sch_bm_config;
+	unsigned int sch_bm_config_cnt;
+
+	const struct ppe_scheduler_qm_config *sch_qm_config;
+	unsigned int sch_qm_config_cnt;
+};
+
+extern const struct ppe_soc_config ipq9574_soc_config;
+
+int ppe_hw_config(struct ppe_device *ppe_dev,
+		  const struct ppe_soc_config *soc_cfg);
 int ppe_queue_scheduler_set(struct ppe_device *ppe_dev,
 			    int node_id, bool flow_level, int port,
 			    struct ppe_scheduler_cfg scheduler_cfg);
-- 
2.56.0


  reply	other threads:[~2026-10-05 15:36 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-05 15:29 [PATCH net-next 0/4] net: ethernet: qualcomm: ppe: Add IPQ5332 support Til Kaiser
2026-10-05 15:29 ` Til Kaiser [this message]
2026-10-05 15:29 ` [PATCH net-next 2/4] dt-bindings: net: qcom,ipq9574-ppe: Tighten ethernet port node constraints Til Kaiser
2026-10-05 15:29 ` [PATCH net-next 3/4] dt-bindings: net: qcom,ipq9574-ppe: Add IPQ5332 support Til Kaiser
2026-10-05 15:29 ` [PATCH net-next 4/4] net: ethernet: qualcomm: ppe: " Til Kaiser

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261005152915.101780-2-mail@tk154.de \
    --to=mail@tk154.de \
    --cc=andrew+netdev@lunn.ch \
    --cc=conor+dt@kernel.org \
    --cc=corbet@lwn.net \
    --cc=davem@davemloft.net \
    --cc=devicetree@vger.kernel.org \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=jie.luo@oss.qualcomm.com \
    --cc=krzk+dt@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=quic_leiwei@quicinc.com \
    --cc=quic_pavir@quicinc.com \
    --cc=quic_suruchia@quicinc.com \
    --cc=rdunlap@infradead.org \
    --cc=robh@kernel.org \
    --cc=skhan@linuxfoundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®