[RFC PATCH net-next 5/8] net: ti: icssg-config: Add SR1.0 configuration functions

Diogo Ivo diogo.ivo at siemens.com
Tue Dec 19 09:45:43 PST 2023


The SR1.0 firmware needs to configured differently from the
current SR2.0 firmware. Add the necessary functions.

Based on the work of Roger Quadros, Vignesh Raghavendra
and Grygorii Strashko in TI's 5.10 SDK [1].

[1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/?h=ti-linux-5.10.y

Co-developed-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Diogo Ivo <diogo.ivo at siemens.com>
---
 drivers/net/ethernet/ti/icssg/icssg_config.c | 90 ++++++++++++++++++--
 1 file changed, 83 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c
index 99de8a40ed60..9079714b15cf 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_config.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_config.c
@@ -18,8 +18,10 @@
  */
 
 /* IPG is in core_clk cycles */
-#define MII_RT_TX_IPG_100M	0x17
-#define MII_RT_TX_IPG_1G	0xb
+#define MII_RT_TX_IPG_100M_SR1	0x166
+#define MII_RT_TX_IPG_1G_SR1	0x1a
+#define MII_RT_TX_IPG_100M_SR2	0x17
+#define MII_RT_TX_IPG_1G_SR2	0xb
 
 #define	ICSSG_QUEUES_MAX		64
 #define	ICSSG_QUEUE_OFFSET		0xd00
@@ -205,14 +207,20 @@ void icssg_config_ipg(struct prueth_emac *emac)
 
 	switch (emac->speed) {
 	case SPEED_1000:
-		icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_1G);
+		icssg_mii_update_ipg(prueth->mii_rt, slice,
+				     prueth->pdata.is_sr1 ?
+				     MII_RT_TX_IPG_1G_SR1 : MII_RT_TX_IPG_1G_SR2);
 		break;
 	case SPEED_100:
-		icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M);
+		icssg_mii_update_ipg(prueth->mii_rt, slice,
+				     prueth->pdata.is_sr1 ?
+				     MII_RT_TX_IPG_100M_SR1 : MII_RT_TX_IPG_100M_SR2);
 		break;
 	case SPEED_10:
-		/* IPG for 10M is same as 100M */
-		icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M);
+		/* Firmware hardcodes IPG for SR1. SR2 same as 100M */
+		if (!prueth->pdata.is_sr1)
+			icssg_mii_update_ipg(prueth->mii_rt, slice,
+					     MII_RT_TX_IPG_100M_SR2);
 		break;
 	default:
 		/* Other links speeds not supported */
@@ -221,6 +229,56 @@ void icssg_config_ipg(struct prueth_emac *emac)
 	}
 }
 
+/* SR1: Set buffer sizes for the pools. There are 8 internal queues
+ * implemented in firmware, but only 4 tx channels/threads in the Egress
+ * direction to firmware. Need a high priority queue for management
+ * messages since they shouldn't be blocked even during high traffic
+ * situation. So use Q0-Q2 as data queues and Q3 as management queue
+ * in the max case. However for ease of configuration, use the max
+ * data queue + 1 for management message if we are not using max
+ * case.
+ *
+ * Allocate 4 MTU buffers per data queue.  Firmware requires
+ * pool sizes to be set for internal queues. Set the upper 5 queue
+ * pool size to min size of 128 bytes since there are only 3 tx
+ * data channels and management queue requires only minimum buffer.
+ * i.e lower queues are used by driver and highest priority queue
+ * from that is used for management message.
+ */
+
+static int emac_egress_buf_pool_size[] = {
+	PRUETH_EMAC_BUF_POOL_SIZE_SR1, PRUETH_EMAC_BUF_POOL_SIZE_SR1,
+	PRUETH_EMAC_BUF_POOL_SIZE_SR1, PRUETH_EMAC_BUF_POOL_MIN_SIZE_SR1,
+	PRUETH_EMAC_BUF_POOL_MIN_SIZE_SR1, PRUETH_EMAC_BUF_POOL_MIN_SIZE_SR1,
+	PRUETH_EMAC_BUF_POOL_MIN_SIZE_SR1, PRUETH_EMAC_BUF_POOL_MIN_SIZE_SR1};
+
+void icssg_config_sr1(struct prueth *prueth, struct prueth_emac *emac,
+		      int slice)
+{
+	struct icssg_config_sr1 *config;
+	void __iomem *va;
+	int i, index;
+
+	va = prueth->shram.va + slice * ICSSG_CONFIG_OFFSET_SLICE1;
+	config = &prueth->config[slice];
+	memset(config, 0, sizeof(*config));
+	config->addr_lo = cpu_to_le32(lower_32_bits(prueth->msmcram.pa));
+	config->addr_hi = cpu_to_le32(upper_32_bits(prueth->msmcram.pa));
+	config->num_tx_threads = 0;
+	config->rx_flow_id = emac->rx_flow_id_base; /* flow id for host port */
+	config->rx_mgr_flow_id = emac->rx_mgm_flow_id_base; /* for mgm ch */
+	config->rand_seed = get_random_u32();
+
+	for (i = PRUETH_EMAC_BUF_POOL_START_SR1; i < PRUETH_NUM_BUF_POOLS_SR1; i++) {
+		index =  i - PRUETH_EMAC_BUF_POOL_START_SR1;
+		config->tx_buf_sz[i] = cpu_to_le32(emac_egress_buf_pool_size[index]);
+	}
+
+	memcpy_toio(va, &prueth->config[slice], sizeof(prueth->config[slice]));
+
+	emac->speed = SPEED_1000;
+}
+
 static void emac_r30_cmd_init(struct prueth_emac *emac)
 {
 	struct icssg_r30_cmd __iomem *p;
@@ -331,6 +389,11 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
 	struct icssg_flow_cfg __iomem *flow_cfg;
 	int ret;
 
+	if (prueth->pdata.is_sr1) {
+		icssg_config_sr1(prueth, emac, slice);
+		return 0;
+	}
+
 	icssg_init_emac_mode(prueth);
 
 	memset_io(config, 0, TAS_GATE_MASK_LIST0);
@@ -435,19 +498,32 @@ int emac_set_port_state(struct prueth_emac *emac,
 
 void icssg_config_half_duplex(struct prueth_emac *emac)
 {
+	struct icssg_config_sr1 *config;
+	void __iomem *va;
+	int slice;
 	u32 val;
 
 	if (!emac->half_duplex)
 		return;
 
 	val = get_random_u32();
-	writel(val, emac->dram.va + HD_RAND_SEED_OFFSET);
+	if (emac->is_sr1) {
+		slice = prueth_emac_slice(emac);
+		va = emac->prueth->shram.va + slice * ICSSG_CONFIG_OFFSET_SLICE1;
+		config = (struct icssg_config_sr1 *)va;
+		writel(val, &config->rand_seed);
+	} else {
+		writel(val, emac->dram.va + HD_RAND_SEED_OFFSET);
+	}
 }
 
 void icssg_config_set_speed(struct prueth_emac *emac)
 {
 	u8 fw_speed;
 
+	if (emac->is_sr1)
+		return;
+
 	switch (emac->speed) {
 	case SPEED_1000:
 		fw_speed = FW_LINK_SPEED_1G;
-- 
2.43.0




More information about the linux-arm-kernel mailing list