diff mbox series

[v2,5/8] net: ti: icssg-config: Add SR1.0 configuration functions

Message ID 20240117161602.153233-6-diogo.ivo@siemens.com (mailing list archive)
State New, archived
Headers show
Series Add support for ICSSG-based Ethernet on SR1.0 devices | expand

Commit Message

Diogo Ivo Jan. 17, 2024, 4:14 p.m. UTC
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@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
---
Changes in v2:
 - Removed explicit references to SR2.0
 - Added static keyword to icssg_config_sr1() 

 drivers/net/ethernet/ti/icssg/icssg_config.c | 86 ++++++++++++++++++--
 1 file changed, 81 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c
index 99de8a40ed60..34bc16599a2d 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_config.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_config.c
@@ -18,6 +18,8 @@ 
  */
 
 /* IPG is in core_clk cycles */
+#define MII_RT_TX_IPG_100M_SR1	0x166
+#define MII_RT_TX_IPG_1G_SR1	0x1a
 #define MII_RT_TX_IPG_100M	0x17
 #define MII_RT_TX_IPG_1G	0xb
 
@@ -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);
 		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);
 		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);
 		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};
+
+static 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;