Thread (37 messages) 37 messages, 9 authors, 2024-01-22
STALE918d

[PATCH net-next 06/20] net: ethernet: qualcomm: Add PPE TDM config

From: Luo Jie <hidden>
Date: 2024-01-10 11:43:09
Also in: linux-arm-msm, linux-devicetree, linux-doc, lkml, netdev
Subsystem: networking drivers, qualcomm ppe driver, the rest · Maintainers: Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Luo Jie, Linus Torvalds

TDM(Time Division Multiplex) config controls the performance of the
PPE ports, which assigns the clock tickets for the PPE port to receive
and transmit packet.

Signed-off-by: Luo Jie <redacted>
---
 drivers/net/ethernet/qualcomm/ppe/ppe.c      | 111 ++++++++++++++++++-
 drivers/net/ethernet/qualcomm/ppe/ppe_regs.h |  30 +++++
 2 files changed, 140 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet/qualcomm/ppe/ppe.c
index 122e325b407d..85d8b06a326b 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
@@ -625,6 +625,111 @@ static int of_parse_ppe_qm(struct ppe_device *ppe_dev,
 	return ret;
 }
 
+static int of_parse_ppe_tdm(struct ppe_device *ppe_dev,
+			    struct device_node *ppe_node)
+{
+	struct device_node *tdm_node;
+	u32 *cfg, reg_val;
+	int ret, cnt;
+
+	tdm_node = of_get_child_by_name(ppe_node, "tdm-config");
+	if (!tdm_node)
+		return dev_err_probe(ppe_dev->dev, -ENODEV,
+				     "tdm-config is not defined\n");
+
+	cnt = of_property_count_u32_elems(tdm_node, "qcom,tdm-bm-config");
+	if (cnt < 0)
+		return dev_err_probe(ppe_dev->dev, -EINVAL,
+				     "Fail to get qcom,tdm-bm-config\n");
+
+	cfg = kmalloc_array(cnt, sizeof(*cfg), GFP_KERNEL | __GFP_ZERO);
+	if (!cfg)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(tdm_node, "qcom,tdm-bm-config", cfg, cnt);
+	if (ret) {
+		dev_err(ppe_dev->dev, "Fail to get qcom,tdm-bm-config\n");
+		goto parse_tdm_err;
+	}
+
+	/* Parse TDM BM configuration,
+	 * the dts property:
+	 * qcom,tdm-bm-config = <valid dir port second_valid second_port>;
+	 *
+	 * This config decides the number ticks available for physical port
+	 * to utilize buffer for receiving and transmiting packet.
+	 */
+	reg_val = FIELD_PREP(PPE_BM_TDM_CTRL_TDM_DEPTH, cnt / 5) |
+		  FIELD_PREP(PPE_BM_TDM_CTRL_TDM_OFFSET, 0) |
+		  FIELD_PREP(PPE_BM_TDM_CTRL_TDM_EN, 1);
+	ret = ppe_write(ppe_dev, PPE_BM_TDM_CTRL, reg_val);
+	if (ret)
+		return ret;
+
+	ret = 0;
+	while ((cnt - ret) / 5) {
+		reg_val = FIELD_PREP(PPE_BM_TDM_CFG_TBL_VALID, cfg[ret]) |
+			  FIELD_PREP(PPE_BM_TDM_CFG_TBL_DIR, cfg[ret + 1]) |
+			  FIELD_PREP(PPE_BM_TDM_CFG_TBL_PORT_NUM, cfg[ret + 2]) |
+			  FIELD_PREP(PPE_BM_TDM_CFG_TBL_SECOND_PORT_VALID, cfg[ret + 3]) |
+			  FIELD_PREP(PPE_BM_TDM_CFG_TBL_SECOND_PORT, cfg[ret + 4]);
+
+		ppe_write(ppe_dev,
+			  PPE_BM_TDM_CFG_TBL + (ret / 5) * PPE_BM_TDM_CFG_TBL_INC,
+			  reg_val);
+		ret += 5;
+	}
+
+	cnt = of_property_count_u32_elems(tdm_node, "qcom,tdm-port-scheduler-config");
+	if (cnt < 0) {
+		dev_err(ppe_dev->dev, "Fail to get qcom,tdm-port-scheduler-config\n");
+		goto parse_tdm_err;
+	}
+
+	cfg = krealloc_array(cfg, cnt, sizeof(*cfg), GFP_KERNEL | __GFP_ZERO);
+	if (!cfg) {
+		ret = -ENOMEM;
+		goto parse_tdm_err;
+	}
+
+	ret = of_property_read_u32_array(tdm_node, "qcom,tdm-port-scheduler-config",
+					 cfg, cnt);
+	if (ret) {
+		dev_err(ppe_dev->dev, "Fail to get qcom,tdm-port-scheduler-config\n");
+		goto parse_tdm_err;
+	}
+
+	/* Parse TDM scheduler configuration,
+	 * the dts property:
+	 * qcom,tdm-port-scheduler-config = <ensch_bmp ensch_port desch_port
+	 * desch_second_valid desch_second_port>;
+	 *
+	 * This config decides the ticks number available for packet enqueue
+	 * and dequeue on the physical port.
+	 */
+	reg_val = FIELD_PREP(PPE_PSCH_TDM_DEPTH_CFG_TDM_DEPTH, cnt / 5);
+	ppe_write(ppe_dev, PPE_PSCH_TDM_DEPTH_CFG, reg_val);
+
+	ret = 0;
+	while ((cnt - ret) / 5) {
+		reg_val = FIELD_PREP(PPE_PSCH_TDM_CFG_TBL_ENS_PORT_BITMAP, cfg[ret]) |
+			  FIELD_PREP(PPE_PSCH_TDM_CFG_TBL_ENS_PORT, cfg[ret + 1]) |
+			  FIELD_PREP(PPE_PSCH_TDM_CFG_TBL_DES_PORT, cfg[ret + 2]) |
+			  FIELD_PREP(PPE_PSCH_TDM_CFG_TBL_DES_SECOND_PORT_EN, cfg[ret + 3]) |
+			  FIELD_PREP(PPE_PSCH_TDM_CFG_TBL_DES_SECOND_PORT, cfg[ret + 4]);
+
+		ppe_write(ppe_dev,
+			  PPE_PSCH_TDM_CFG_TBL + (ret / 5) * PPE_PSCH_TDM_CFG_TBL_INC,
+			  reg_val);
+		ret += 5;
+	}
+
+	ret = 0;
+parse_tdm_err:
+	kfree(cfg);
+	return ret;
+};
+
 static int of_parse_ppe_config(struct ppe_device *ppe_dev,
 			       struct device_node *ppe_node)
 {
@@ -634,7 +739,11 @@ static int of_parse_ppe_config(struct ppe_device *ppe_dev,
 	if (ret)
 		return ret;
 
-	return of_parse_ppe_qm(ppe_dev, ppe_node);
+	ret = of_parse_ppe_qm(ppe_dev, ppe_node);
+	if (ret)
+		return ret;
+
+	return of_parse_ppe_tdm(ppe_dev, ppe_node);
 }
 
 static int qcom_ppe_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
index 3e75b75fa48c..589f92a4f607 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
@@ -7,14 +7,44 @@
 #ifndef __PPE_REGS_H__
 #define __PPE_REGS_H__
 
+#define PPE_BM_TDM_CTRL						0xb000
+#define PPE_BM_TDM_CTRL_NUM					1
+#define PPE_BM_TDM_CTRL_INC					4
+#define PPE_BM_TDM_CTRL_TDM_DEPTH				GENMASK(7, 0)
+#define PPE_BM_TDM_CTRL_TDM_OFFSET				GENMASK(14, 8)
+#define PPE_BM_TDM_CTRL_TDM_EN					BIT(31)
+
+#define PPE_BM_TDM_CFG_TBL					0xc000
+#define PPE_BM_TDM_CFG_TBL_NUM					128
+#define PPE_BM_TDM_CFG_TBL_INC					0x10
+#define PPE_BM_TDM_CFG_TBL_PORT_NUM				GENMASK(3, 0)
+#define PPE_BM_TDM_CFG_TBL_DIR					BIT(4)
+#define PPE_BM_TDM_CFG_TBL_VALID				BIT(5)
+#define PPE_BM_TDM_CFG_TBL_SECOND_PORT_VALID			BIT(6)
+#define PPE_BM_TDM_CFG_TBL_SECOND_PORT				GENMASK(11, 8)
+
 #define PPE_EG_BRIDGE_CONFIG					0x20044
 #define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN			BIT(2)
 
+#define PPE_PSCH_TDM_DEPTH_CFG					0x400000
+#define PPE_PSCH_TDM_DEPTH_CFG_NUM				1
+#define PPE_PSCH_TDM_DEPTH_CFG_INC				4
+#define PPE_PSCH_TDM_DEPTH_CFG_TDM_DEPTH			GENMASK(7, 0)
+
 #define PPE_DEQ_OPR_TBL						0x430000
 #define PPE_DEQ_OPR_TBL_NUM					300
 #define PPE_DEQ_OPR_TBL_INC					0x10
 #define PPE_ENQ_OPR_TBL_DEQ_DISABLE				BIT(0)
 
+#define PPE_PSCH_TDM_CFG_TBL					0x47a000
+#define PPE_PSCH_TDM_CFG_TBL_NUM				128
+#define PPE_PSCH_TDM_CFG_TBL_INC				0x10
+#define PPE_PSCH_TDM_CFG_TBL_DES_PORT				GENMASK(3, 0)
+#define PPE_PSCH_TDM_CFG_TBL_ENS_PORT				GENMASK(7, 4)
+#define PPE_PSCH_TDM_CFG_TBL_ENS_PORT_BITMAP			GENMASK(15, 8)
+#define PPE_PSCH_TDM_CFG_TBL_DES_SECOND_PORT_EN			BIT(16)
+#define PPE_PSCH_TDM_CFG_TBL_DES_SECOND_PORT			GENMASK(20, 17)
+
 #define PPE_BM_PORT_FC_MODE					0x600100
 #define PPE_BM_PORT_FC_MODE_NUM					15
 #define PPE_BM_PORT_FC_MODE_INC					4
-- 
2.42.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help