int i;
 
        addr = lower_32_bits(prueth->msmcram.pa);
-       if (slice)
-               addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
+       if (slice) {
+               if (prueth->pdata.banked_ms_ram)
+                       addr += MSMC_RAM_BANK_SIZE;
+               else
+                       addr += PRUETH_SW_TOTAL_BUF_SIZE_PER_SLICE;
+       }
 
        if (addr % SZ_64K) {
                dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n");
        }
 
        bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET;
-       /* workaround for f/w bug. bpool 0 needs to be initialized */
-       for (i = 0; i <  PRUETH_NUM_BUF_POOLS; i++) {
+
+       /* Configure buffer pools for forwarding buffers
+        * - used by firmware to store packets to be forwarded to other port
+        * - 8 total pools per slice
+        */
+       for (i = 0; i <  PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE; i++) {
                writel(addr, &bpool_cfg[i].addr);
-               writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len);
-               addr += PRUETH_EMAC_BUF_POOL_SIZE;
+               writel(PRUETH_SW_FWD_BUF_POOL_SIZE, &bpool_cfg[i].len);
+               addr += PRUETH_SW_FWD_BUF_POOL_SIZE;
        }
 
-       if (!slice)
-               addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
-       else
-               addr += PRUETH_SW_NUM_BUF_POOLS_HOST * PRUETH_SW_BUF_POOL_SIZE_HOST;
-
-       for (i = PRUETH_NUM_BUF_POOLS;
-            i < 2 * PRUETH_SW_NUM_BUF_POOLS_HOST + PRUETH_NUM_BUF_POOLS;
-            i++) {
-               /* The driver only uses first 4 queues per PRU so only initialize them */
-               if (i % PRUETH_SW_NUM_BUF_POOLS_HOST < PRUETH_SW_NUM_BUF_POOLS_PER_PRU) {
-                       writel(addr, &bpool_cfg[i].addr);
-                       writel(PRUETH_SW_BUF_POOL_SIZE_HOST, &bpool_cfg[i].len);
-                       addr += PRUETH_SW_BUF_POOL_SIZE_HOST;
+       /* Configure buffer pools for Local Injection buffers
+        *  - used by firmware to store packets received from host core
+        *  - 16 total pools per slice
+        */
+       for (i = 0; i < PRUETH_NUM_LI_BUF_POOLS_PER_SLICE; i++) {
+               int cfg_idx = i + PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE;
+
+               /* The driver only uses first 4 queues per PRU,
+                * so only initialize buffer for them
+                */
+               if ((i % PRUETH_NUM_LI_BUF_POOLS_PER_PORT_PER_SLICE)
+                        < PRUETH_SW_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE) {
+                       writel(addr, &bpool_cfg[cfg_idx].addr);
+                       writel(PRUETH_SW_LI_BUF_POOL_SIZE,
+                              &bpool_cfg[cfg_idx].len);
+                       addr += PRUETH_SW_LI_BUF_POOL_SIZE;
                } else {
-                       writel(0, &bpool_cfg[i].addr);
-                       writel(0, &bpool_cfg[i].len);
+                       writel(0, &bpool_cfg[cfg_idx].addr);
+                       writel(0, &bpool_cfg[cfg_idx].len);
                }
        }
 
-       if (!slice)
-               addr += PRUETH_SW_NUM_BUF_POOLS_HOST * PRUETH_SW_BUF_POOL_SIZE_HOST;
-       else
-               addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
+       /* Express RX buffer queue
+        *  - used by firmware to store express packets to be transmitted
+        *    to the host core
+        */
+       rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET;
+       for (i = 0; i < 3; i++)
+               writel(addr, &rxq_ctx->start[i]);
+
+       addr += PRUETH_SW_HOST_EXP_BUF_POOL_SIZE;
+       writel(addr, &rxq_ctx->end);
 
+       /* Pre-emptible RX buffer queue
+        *  - used by firmware to store preemptible packets to be transmitted
+        *    to the host core
+        */
        rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET;
        for (i = 0; i < 3; i++)
                writel(addr, &rxq_ctx->start[i]);
 
-       addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
-       writel(addr - SZ_2K, &rxq_ctx->end);
+       addr += PRUETH_SW_HOST_PRE_BUF_POOL_SIZE;
+       writel(addr, &rxq_ctx->end);
+
+       /* Set pointer for default dropped packet write
+        *  - used by firmware to temporarily store packet to be dropped
+        */
+       rxq_ctx = emac->dram.va + DEFAULT_MSMC_Q_OFFSET;
+       writel(addr, &rxq_ctx->start[0]);
 
        return 0;
 }
        u32 addr;
        int i;
 
-       /* Layout to have 64KB aligned buffer pool
-        * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1|
-        */
-
        addr = lower_32_bits(prueth->msmcram.pa);
-       if (slice)
-               addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
+       if (slice) {
+               if (prueth->pdata.banked_ms_ram)
+                       addr += MSMC_RAM_BANK_SIZE;
+               else
+                       addr += PRUETH_EMAC_TOTAL_BUF_SIZE_PER_SLICE;
+       }
 
        if (addr % SZ_64K) {
                dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n");
        }
 
        bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET;
-       /* workaround for f/w bug. bpool 0 needs to be initilalized */
-       writel(addr, &bpool_cfg[0].addr);
-       writel(0, &bpool_cfg[0].len);
 
-       for (i = PRUETH_EMAC_BUF_POOL_START;
-            i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS;
-            i++) {
-               writel(addr, &bpool_cfg[i].addr);
-               writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len);
-               addr += PRUETH_EMAC_BUF_POOL_SIZE;
+       /* Configure buffer pools for forwarding buffers
+        *  - in mac mode - no forwarding so initialize all pools to 0
+        *  - 8 total pools per slice
+        */
+       for (i = 0; i <  PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE; i++) {
+               writel(0, &bpool_cfg[i].addr);
+               writel(0, &bpool_cfg[i].len);
        }
 
-       if (!slice)
-               addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
-       else
-               addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2;
+       /* Configure buffer pools for Local Injection buffers
+        *  - used by firmware to store packets received from host core
+        *  - 16 total pools per slice
+        */
+       bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET;
+       for (i = 0; i < PRUETH_NUM_LI_BUF_POOLS_PER_SLICE; i++) {
+               int cfg_idx = i + PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE;
+
+               /* In EMAC mode, only first 4 buffers are used,
+                * as 1 slice needs to handle only 1 port
+                */
+               if (i < PRUETH_EMAC_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE) {
+                       writel(addr, &bpool_cfg[cfg_idx].addr);
+                       writel(PRUETH_EMAC_LI_BUF_POOL_SIZE,
+                              &bpool_cfg[cfg_idx].len);
+                       addr += PRUETH_EMAC_LI_BUF_POOL_SIZE;
+               } else {
+                       writel(0, &bpool_cfg[cfg_idx].addr);
+                       writel(0, &bpool_cfg[cfg_idx].len);
+               }
+       }
 
-       /* Pre-emptible RX buffer queue */
-       rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET;
+       /* Express RX buffer queue
+        *  - used by firmware to store express packets to be transmitted
+        *    to host core
+        */
+       rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET;
        for (i = 0; i < 3; i++)
                writel(addr, &rxq_ctx->start[i]);
 
-       addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
+       addr += PRUETH_EMAC_HOST_EXP_BUF_POOL_SIZE;
        writel(addr, &rxq_ctx->end);
 
-       /* Express RX buffer queue */
-       rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET;
+       /* Pre-emptible RX buffer queue
+        *  - used by firmware to store preemptible packets to be transmitted
+        *    to host core
+        */
+       rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET;
        for (i = 0; i < 3; i++)
                writel(addr, &rxq_ctx->start[i]);
 
-       addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
+       addr += PRUETH_EMAC_HOST_PRE_BUF_POOL_SIZE;
        writel(addr, &rxq_ctx->end);
 
+       /* Set pointer for default dropped packet write
+        *  - used by firmware to temporarily store packet to be dropped
+        */
+       rxq_ctx = emac->dram.va + DEFAULT_MSMC_Q_OFFSET;
+       writel(addr, &rxq_ctx->start[0]);
+
        return 0;
 }
 
 
 #define PRUETH_MAX_RX_FLOWS    1       /* excluding default flow */
 #define PRUETH_RX_FLOW_DATA    0
 
-#define PRUETH_EMAC_BUF_POOL_SIZE      SZ_8K
-#define PRUETH_EMAC_POOLS_PER_SLICE    24
-#define PRUETH_EMAC_BUF_POOL_START     8
-#define PRUETH_NUM_BUF_POOLS   8
-#define PRUETH_EMAC_RX_CTX_BUF_SIZE    SZ_16K  /* per slice */
-#define MSMC_RAM_SIZE  \
-       (2 * (PRUETH_EMAC_BUF_POOL_SIZE * PRUETH_NUM_BUF_POOLS + \
-        PRUETH_EMAC_RX_CTX_BUF_SIZE * 2))
-
-#define PRUETH_SW_BUF_POOL_SIZE_HOST   SZ_4K
-#define PRUETH_SW_NUM_BUF_POOLS_HOST   8
-#define PRUETH_SW_NUM_BUF_POOLS_PER_PRU 4
-#define MSMC_RAM_SIZE_SWITCH_MODE \
-       (MSMC_RAM_SIZE + \
-       (2 * PRUETH_SW_BUF_POOL_SIZE_HOST * PRUETH_SW_NUM_BUF_POOLS_HOST))
+/* Defines for forwarding path buffer pools:
+ *   - used by firmware to store packets to be forwarded to other port
+ *   - 8 total pools per slice
+ *   - only used in switch mode (as no forwarding in mac mode)
+ */
+#define PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE                     8
+#define PRUETH_SW_FWD_BUF_POOL_SIZE                            (SZ_8K)
+
+/* Defines for local injection path buffer pools:
+ *   - used by firmware to store packets received from host core
+ *   - 16 total pools per slice
+ *   - 8 pools per port per slice and each slice handles both ports
+ *   - only 4 out of 8 pools used per port (as only 4 real QoS levels in ICSSG)
+ *   - switch mode: 8 total pools used
+ *   - mac mode:    4 total pools used
+ */
+#define PRUETH_NUM_LI_BUF_POOLS_PER_SLICE                      16
+#define PRUETH_NUM_LI_BUF_POOLS_PER_PORT_PER_SLICE             8
+#define PRUETH_SW_LI_BUF_POOL_SIZE                             SZ_4K
+#define PRUETH_SW_USED_LI_BUF_POOLS_PER_SLICE                  8
+#define PRUETH_SW_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE         4
+#define PRUETH_EMAC_LI_BUF_POOL_SIZE                           SZ_8K
+#define PRUETH_EMAC_USED_LI_BUF_POOLS_PER_SLICE                        4
+#define PRUETH_EMAC_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE       4
+
+/* Defines for host egress path - express and preemptible buffers
+ *   - used by firmware to store express and preemptible packets
+ *     to be transmitted to host core
+ *   - used by both mac/switch modes
+ */
+#define PRUETH_SW_HOST_EXP_BUF_POOL_SIZE       SZ_16K
+#define PRUETH_SW_HOST_PRE_BUF_POOL_SIZE       (SZ_16K - SZ_2K)
+#define PRUETH_EMAC_HOST_EXP_BUF_POOL_SIZE     PRUETH_SW_HOST_EXP_BUF_POOL_SIZE
+#define PRUETH_EMAC_HOST_PRE_BUF_POOL_SIZE     PRUETH_SW_HOST_PRE_BUF_POOL_SIZE
+
+/* Buffer used by firmware to temporarily store packet to be dropped */
+#define PRUETH_SW_DROP_PKT_BUF_SIZE            SZ_2K
+#define PRUETH_EMAC_DROP_PKT_BUF_SIZE          PRUETH_SW_DROP_PKT_BUF_SIZE
+
+/* Total switch mode memory usage for buffers per slice */
+#define PRUETH_SW_TOTAL_BUF_SIZE_PER_SLICE \
+       (PRUETH_SW_FWD_BUF_POOL_SIZE * PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE + \
+        PRUETH_SW_LI_BUF_POOL_SIZE * PRUETH_SW_USED_LI_BUF_POOLS_PER_SLICE + \
+        PRUETH_SW_HOST_EXP_BUF_POOL_SIZE + \
+        PRUETH_SW_HOST_PRE_BUF_POOL_SIZE + \
+        PRUETH_SW_DROP_PKT_BUF_SIZE)
+
+/* Total switch mode memory usage for all buffers */
+#define PRUETH_SW_TOTAL_BUF_SIZE \
+       (2 * PRUETH_SW_TOTAL_BUF_SIZE_PER_SLICE)
+
+/* Total mac mode memory usage for buffers per slice */
+#define PRUETH_EMAC_TOTAL_BUF_SIZE_PER_SLICE \
+       (PRUETH_EMAC_LI_BUF_POOL_SIZE * \
+        PRUETH_EMAC_USED_LI_BUF_POOLS_PER_SLICE + \
+        PRUETH_EMAC_HOST_EXP_BUF_POOL_SIZE + \
+        PRUETH_EMAC_HOST_PRE_BUF_POOL_SIZE + \
+        PRUETH_EMAC_DROP_PKT_BUF_SIZE)
+
+/* Total mac mode memory usage for all buffers */
+#define PRUETH_EMAC_TOTAL_BUF_SIZE \
+       (2 * PRUETH_EMAC_TOTAL_BUF_SIZE_PER_SLICE)
+
+/* Size of 1 bank of MSMC/OC_SRAM memory */
+#define MSMC_RAM_BANK_SIZE                     SZ_256K
 
 #define PRUETH_SWITCH_FDB_MASK ((SIZE_OF_FDB / NUMBER_OF_FDB_BUCKET_ENTRIES) - 1)
 
 
                goto put_mem;
        }
 
-       msmc_ram_size = MSMC_RAM_SIZE;
        prueth->is_switchmode_supported = prueth->pdata.switch_mode;
-       if (prueth->is_switchmode_supported)
-               msmc_ram_size = MSMC_RAM_SIZE_SWITCH_MODE;
+       if (prueth->pdata.banked_ms_ram) {
+               /* Reserve 2 MSMC RAM banks for buffers to avoid arbitration */
+               msmc_ram_size = (2 * MSMC_RAM_BANK_SIZE);
+       } else {
+               msmc_ram_size = PRUETH_EMAC_TOTAL_BUF_SIZE;
+               if (prueth->is_switchmode_supported)
+                       msmc_ram_size = PRUETH_SW_TOTAL_BUF_SIZE;
+       }
 
        /* NOTE: FW bug needs buffer base to be 64KB aligned */
        prueth->msmcram.va =
 
 free_pool:
        gen_pool_free(prueth->sram_pool,
-                     (unsigned long)prueth->msmcram.va, msmc_ram_size);
+                     (unsigned long)prueth->msmcram.va,
+                     prueth->msmcram.size);
 
 put_mem:
        pruss_release_mem_region(prueth->pruss, &prueth->shram);
        icss_iep_put(prueth->iep0);
 
        gen_pool_free(prueth->sram_pool,
-                     (unsigned long)prueth->msmcram.va,
-                     MSMC_RAM_SIZE);
+               (unsigned long)prueth->msmcram.va,
+               prueth->msmcram.size);
 
        pruss_release_mem_region(prueth->pruss, &prueth->shram);
 
        .fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE,
        .quirk_10m_link_issue = 1,
        .switch_mode = 1,
+       .banked_ms_ram = 0,
 };
 
 static const struct prueth_pdata am64x_icssg_pdata = {
        .fdqring_mode = K3_RINGACC_RING_MODE_RING,
        .quirk_10m_link_issue = 1,
        .switch_mode = 1,
+       .banked_ms_ram = 1,
 };
 
 static const struct of_device_id prueth_dt_match[] = {