[dpdk-dev] [PATCH v3 06/14] net/ppfe: add MAC and host interface initialisation

Gagandeep Singh g.singh at nxp.com
Tue Oct 1 13:02:01 CEST 2019


HIF or host interface is responsible for transmit
and receive packets between physical ethernet
interfaces and HIF library defined logical interfaces.

This patch initialise that host interface and MAC.

Signed-off-by: Gagandeep Singh <g.singh at nxp.com>
Signed-off-by: Akhil Goyal <akhil.goyal at nxp.com>
Acked-by: Nipun Gupta <nipun.gupta at nxp.com>
---
 drivers/net/ppfe/Makefile      |  10 +
 drivers/net/ppfe/base/pfe.h    |  83 +++++
 drivers/net/ppfe/meson.build   |  12 +-
 drivers/net/ppfe/pfe_hal.c     | 635 +++++++++++++++++++++++++++++++++
 drivers/net/ppfe/pfe_hif.c     | 256 +++++++++++++
 drivers/net/ppfe/pfe_hif.h     | 106 ++++++
 drivers/net/ppfe/pfe_hif_lib.c |  20 ++
 drivers/net/ppfe/pfe_hif_lib.h | 162 +++++++++
 drivers/net/ppfe/pfe_mod.h     |   5 +
 drivers/net/ppfe/ppfe_ethdev.c | 153 +++++++-
 10 files changed, 1439 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ppfe/pfe_hal.c
 create mode 100644 drivers/net/ppfe/pfe_hif.c
 create mode 100644 drivers/net/ppfe/pfe_hif.h
 create mode 100644 drivers/net/ppfe/pfe_hif_lib.c
 create mode 100644 drivers/net/ppfe/pfe_hif_lib.h

diff --git a/drivers/net/ppfe/Makefile b/drivers/net/ppfe/Makefile
index b9e894ffd..0f1dba188 100644
--- a/drivers/net/ppfe/Makefile
+++ b/drivers/net/ppfe/Makefile
@@ -10,14 +10,24 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_pmd_ppfe.a
 
 CFLAGS += -O3 $(WERROR_FLAGS)
+CFLAGS += -Wno-pointer-arith
 CFLAGS += -I$(RTE_SDK)/drivers/bus/dpaa/include/
+CFLAGS += -I$(RTE_SDK)/drivers/net/ppfe/base/
 CFLAGS += -I$(RTE_SDK)/drivers/common/dpaax
 
 EXPORT_MAP := rte_pmd_ppfe_version.map
 LIBABIVER := 1
 
+# Driver uses below experimental APIs
+# rte_mem_iova2virt
+# rte_mem_virt2memseg
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+
 # Interfaces with DPDK
 SRCS-$(CONFIG_RTE_LIBRTE_PPFE_PMD) += ppfe_ethdev.c
+SRCS-$(CONFIG_RTE_LIBRTE_PPFE_PMD) += pfe_hal.c
+SRCS-$(CONFIG_RTE_LIBRTE_PPFE_PMD) += pfe_hif_lib.c
+SRCS-$(CONFIG_RTE_LIBRTE_PPFE_PMD) += pfe_hif.c
 
 LDLIBS += -lrte_bus_vdev
 LDLIBS += -lrte_bus_dpaa
diff --git a/drivers/net/ppfe/base/pfe.h b/drivers/net/ppfe/base/pfe.h
index c1fe71a3a..e59d3aa04 100644
--- a/drivers/net/ppfe/base/pfe.h
+++ b/drivers/net/ppfe/base/pfe.h
@@ -311,6 +311,70 @@ void bmu_set_config(void *base, struct BMU_CFG *cfg);
 enum mac_loop {LB_NONE, LB_EXT, LB_LOCAL};
 #endif
 
+void gemac_init(void *base, void *config);
+void gemac_disable_rx_checksum_offload(void *base);
+void gemac_enable_rx_checksum_offload(void *base);
+void gemac_set_mdc_div(void *base, int mdc_div);
+void gemac_set_speed(void *base, enum mac_speed gem_speed);
+void gemac_set_duplex(void *base, int duplex);
+void gemac_set_mode(void *base, int mode);
+void gemac_enable(void *base);
+void gemac_tx_disable(void *base);
+void gemac_tx_enable(void *base);
+void gemac_disable(void *base);
+void gemac_reset(void *base);
+void gemac_set_address(void *base, struct spec_addr *addr);
+struct spec_addr gemac_get_address(void *base);
+void gemac_set_loop(void *base, enum mac_loop gem_loop);
+void gemac_set_laddr1(void *base, struct pfe_mac_addr *address);
+void gemac_set_laddr2(void *base, struct pfe_mac_addr *address);
+void gemac_set_laddr3(void *base, struct pfe_mac_addr *address);
+void gemac_set_laddr4(void *base, struct pfe_mac_addr *address);
+void gemac_set_laddrN(void *base, struct pfe_mac_addr *address,
+		      unsigned int entry_index);
+void gemac_clear_laddr1(void *base);
+void gemac_clear_laddr2(void *base);
+void gemac_clear_laddr3(void *base);
+void gemac_clear_laddr4(void *base);
+void gemac_clear_laddrN(void *base, unsigned int entry_index);
+struct pfe_mac_addr gemac_get_hash(void *base);
+void gemac_set_hash(void *base, struct pfe_mac_addr *hash);
+struct pfe_mac_addr gem_get_laddr1(void *base);
+struct pfe_mac_addr gem_get_laddr2(void *base);
+struct pfe_mac_addr gem_get_laddr3(void *base);
+struct pfe_mac_addr gem_get_laddr4(void *base);
+struct pfe_mac_addr gem_get_laddrN(void *base, unsigned int entry_index);
+void gemac_set_config(void *base, struct gemac_cfg *cfg);
+void gemac_allow_broadcast(void *base);
+void gemac_no_broadcast(void *base);
+void gemac_enable_1536_rx(void *base);
+void gemac_disable_1536_rx(void *base);
+int gemac_set_rx(void *base, int mtu);
+void gemac_enable_rx_jmb(void *base);
+void gemac_disable_rx_jmb(void *base);
+void gemac_enable_stacked_vlan(void *base);
+void gemac_disable_stacked_vlan(void *base);
+void gemac_enable_pause_rx(void *base);
+void gemac_disable_pause_rx(void *base);
+void gemac_enable_pause_tx(void *base);
+void gemac_disable_pause_tx(void *base);
+void gemac_enable_copy_all(void *base);
+void gemac_disable_copy_all(void *base);
+void gemac_set_bus_width(void *base, int width);
+void gemac_set_wol(void *base, u32 wol_conf);
+
+void gpi_init(void *base, struct gpi_cfg *cfg);
+void gpi_reset(void *base);
+void gpi_enable(void *base);
+void gpi_disable(void *base);
+void gpi_set_config(void *base, struct gpi_cfg *cfg);
+
+void hif_init(void);
+void hif_tx_enable(void);
+void hif_tx_disable(void);
+void hif_rx_enable(void);
+void hif_rx_disable(void);
+
 /* Get Chip Revision level
  *
  */
@@ -336,4 +400,23 @@ static inline void hif_tx_dma_start(void)
 	writel(HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB, HIF_TX_CTRL);
 }
 
+
+static inline void *pfe_mem_ptov(phys_addr_t paddr)
+{
+	return rte_mem_iova2virt(paddr);
+}
+
+static phys_addr_t pfe_mem_vtop(uint64_t vaddr) __attribute__((unused));
+
+static inline phys_addr_t pfe_mem_vtop(uint64_t vaddr)
+{
+	const struct rte_memseg *memseg;
+
+	memseg = rte_mem_virt2memseg((void *)(uintptr_t)vaddr, NULL);
+	if (memseg)
+		return memseg->phys_addr + RTE_PTR_DIFF(vaddr, memseg->addr);
+
+	return (size_t)NULL;
+}
+
 #endif /* _PFE_H_ */
diff --git a/drivers/net/ppfe/meson.build b/drivers/net/ppfe/meson.build
index 8ca2cb87d..5d8f4f2e9 100644
--- a/drivers/net/ppfe/meson.build
+++ b/drivers/net/ppfe/meson.build
@@ -6,6 +6,14 @@ if host_machine.system() != 'linux'
 endif
 deps += ['bus_dpaa']
 
-sources = files('ppfe_ethdev.c')
+sources = files('ppfe_ethdev.c',
+		'pfe_hal.c',
+		'pfe_hif_lib.c',
+		'pfe_hif.c')
 
-includes += include_directories('../../bus/dpaa/include/')
+# Driver uses below experimental APIs
+# rte_mem_iova2virt
+# rte_mem_virt2memseg
+allow_experimental_apis = true
+
+includes += include_directories('base','../../bus/dpaa/include/')
diff --git a/drivers/net/ppfe/pfe_hal.c b/drivers/net/ppfe/pfe_hal.c
new file mode 100644
index 000000000..247634559
--- /dev/null
+++ b/drivers/net/ppfe/pfe_hal.c
@@ -0,0 +1,635 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2019 NXP
+ */
+
+#include "pfe_logs.h"
+#include "pfe_mod.h"
+
+#define PFE_MTU_RESET_MASK	0xC000FFFF
+/* TODO update
+ * MAX MTU on VLAN support
+ * EMAC_TRUNC_FL value in gemac_set_config
+ * ERR print in set_rx
+ */
+#define MAX_MTU_ON_REV1		(1878 + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN)
+
+void *cbus_base_addr;
+void *ddr_base_addr;
+unsigned long ddr_phys_base_addr;
+unsigned int ddr_size;
+static struct pe_info pe[MAX_PE];
+
+/* Initializes the PFE library.
+ * Must be called before using any of the library functions.
+ *
+ * @param[in] cbus_base		CBUS virtual base address (as mapped in
+ * the host CPU address space)
+ * @param[in] ddr_base		PFE DDR range virtual base address (as
+ * mapped in the host CPU address space)
+ * @param[in] ddr_phys_base	PFE DDR range physical base address (as
+ * mapped in platform)
+ * @param[in] size		PFE DDR range size (as defined by the host
+ * software)
+ */
+void
+pfe_lib_init(void *cbus_base, void *ddr_base, unsigned long ddr_phys_base,
+		  unsigned int size)
+{
+	cbus_base_addr = cbus_base;
+	ddr_base_addr = ddr_base;
+	ddr_phys_base_addr = ddr_phys_base;
+	ddr_size = size;
+
+	pe[CLASS0_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(0);
+	pe[CLASS0_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(0);
+	pe[CLASS0_ID].pmem_size = CLASS_IMEM_SIZE;
+	pe[CLASS0_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA;
+	pe[CLASS0_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR;
+	pe[CLASS0_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA;
+
+	pe[CLASS1_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(1);
+	pe[CLASS1_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(1);
+	pe[CLASS1_ID].pmem_size = CLASS_IMEM_SIZE;
+	pe[CLASS1_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA;
+	pe[CLASS1_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR;
+	pe[CLASS1_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA;
+
+	pe[CLASS2_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(2);
+	pe[CLASS2_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(2);
+	pe[CLASS2_ID].pmem_size = CLASS_IMEM_SIZE;
+	pe[CLASS2_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA;
+	pe[CLASS2_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR;
+	pe[CLASS2_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA;
+
+	pe[CLASS3_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(3);
+	pe[CLASS3_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(3);
+	pe[CLASS3_ID].pmem_size = CLASS_IMEM_SIZE;
+	pe[CLASS3_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA;
+	pe[CLASS3_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR;
+	pe[CLASS3_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA;
+
+	pe[CLASS4_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(4);
+	pe[CLASS4_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(4);
+	pe[CLASS4_ID].pmem_size = CLASS_IMEM_SIZE;
+	pe[CLASS4_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA;
+	pe[CLASS4_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR;
+	pe[CLASS4_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA;
+
+	pe[CLASS5_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(5);
+	pe[CLASS5_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(5);
+	pe[CLASS5_ID].pmem_size = CLASS_IMEM_SIZE;
+	pe[CLASS5_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA;
+	pe[CLASS5_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR;
+	pe[CLASS5_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA;
+
+	pe[TMU0_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(0);
+	pe[TMU0_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(0);
+	pe[TMU0_ID].pmem_size = TMU_IMEM_SIZE;
+	pe[TMU0_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA;
+	pe[TMU0_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR;
+	pe[TMU0_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA;
+
+	pe[TMU1_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(1);
+	pe[TMU1_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(1);
+	pe[TMU1_ID].pmem_size = TMU_IMEM_SIZE;
+	pe[TMU1_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA;
+	pe[TMU1_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR;
+	pe[TMU1_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA;
+
+	pe[TMU3_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(3);
+	pe[TMU3_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(3);
+	pe[TMU3_ID].pmem_size = TMU_IMEM_SIZE;
+	pe[TMU3_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA;
+	pe[TMU3_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR;
+	pe[TMU3_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA;
+
+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED)
+	pe[UTIL_ID].dmem_base_addr = UTIL_DMEM_BASE_ADDR;
+	pe[UTIL_ID].mem_access_wdata = UTIL_MEM_ACCESS_WDATA;
+	pe[UTIL_ID].mem_access_addr = UTIL_MEM_ACCESS_ADDR;
+	pe[UTIL_ID].mem_access_rdata = UTIL_MEM_ACCESS_RDATA;
+#endif
+}
+
+/**************************** MTIP GEMAC ***************************/
+
+/* Enable Rx Checksum Engine. With this enabled, Frame with bad IP,
+ *   TCP or UDP checksums are discarded
+ *
+ * @param[in] base	GEMAC base address.
+ */
+void
+gemac_enable_rx_checksum_offload(__rte_unused void *base)
+{
+	/*Do not find configuration to do this */
+}
+
+/* Disable Rx Checksum Engine.
+ *
+ * @param[in] base	GEMAC base address.
+ */
+void
+gemac_disable_rx_checksum_offload(__rte_unused void *base)
+{
+	/*Do not find configuration to do this */
+}
+
+/* GEMAC set speed.
+ * @param[in] base	GEMAC base address
+ * @param[in] speed	GEMAC speed (10, 100 or 1000 Mbps)
+ */
+void
+gemac_set_speed(void *base, enum mac_speed gem_speed)
+{
+	u32 ecr = readl(base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_SPEED;
+	u32 rcr = readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_RMII_10T;
+
+	switch (gem_speed) {
+	case SPEED_10M:
+			rcr |= EMAC_RCNTRL_RMII_10T;
+			break;
+
+	case SPEED_1000M:
+			ecr |= EMAC_ECNTRL_SPEED;
+			break;
+
+	case SPEED_100M:
+	default:
+			/*It is in 100M mode */
+			break;
+	}
+	writel(ecr, (base + EMAC_ECNTRL_REG));
+	writel(rcr, (base + EMAC_RCNTRL_REG));
+}
+
+/* GEMAC set duplex.
+ * @param[in] base	GEMAC base address
+ * @param[in] duplex	GEMAC duplex mode (Full, Half)
+ */
+void
+gemac_set_duplex(void *base, int duplex)
+{
+	if (duplex == DUPLEX_HALF) {
+		writel(readl(base + EMAC_TCNTRL_REG) & ~EMAC_TCNTRL_FDEN, base
+			+ EMAC_TCNTRL_REG);
+		writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_DRT, (base
+			+ EMAC_RCNTRL_REG));
+	} else {
+		writel(readl(base + EMAC_TCNTRL_REG) | EMAC_TCNTRL_FDEN, base
+			+ EMAC_TCNTRL_REG);
+		writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_DRT, (base
+			+ EMAC_RCNTRL_REG));
+	}
+}
+
+/* GEMAC set mode.
+ * @param[in] base	GEMAC base address
+ * @param[in] mode	GEMAC operation mode (MII, RMII, RGMII, SGMII)
+ */
+void
+gemac_set_mode(void *base, __rte_unused int mode)
+{
+	u32 val = readl(base + EMAC_RCNTRL_REG);
+
+	/*Remove loopbank*/
+	val &= ~EMAC_RCNTRL_LOOP;
+
+	/*Enable flow control and MII mode*/
+	val |= (EMAC_RCNTRL_FCE | EMAC_RCNTRL_MII_MODE | EMAC_RCNTRL_CRC_FWD);
+
+	writel(val, base + EMAC_RCNTRL_REG);
+}
+
+/* GEMAC enable function.
+ * @param[in] base	GEMAC base address
+ */
+void
+gemac_enable(void *base)
+{
+	writel(readl(base + EMAC_ECNTRL_REG) | EMAC_ECNTRL_ETHER_EN, base +
+		EMAC_ECNTRL_REG);
+}
+
+/* GEMAC disable function.
+ * @param[in] base	GEMAC base address
+ */
+void
+gemac_disable(void *base)
+{
+	writel(readl(base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_ETHER_EN, base +
+		EMAC_ECNTRL_REG);
+}
+
+/* GEMAC TX disable function.
+ * @param[in] base	GEMAC base address
+ */
+void
+gemac_tx_disable(void *base)
+{
+	writel(readl(base + EMAC_TCNTRL_REG) | EMAC_TCNTRL_GTS, base +
+		EMAC_TCNTRL_REG);
+}
+
+void
+gemac_tx_enable(void *base)
+{
+	writel(readl(base + EMAC_TCNTRL_REG) & ~EMAC_TCNTRL_GTS, base +
+			EMAC_TCNTRL_REG);
+}
+
+/* Sets the hash register of the MAC.
+ * This register is used for matching unicast and multicast frames.
+ *
+ * @param[in] base	GEMAC base address.
+ * @param[in] hash	64-bit hash to be configured.
+ */
+void
+gemac_set_hash(void *base, struct pfe_mac_addr *hash)
+{
+	writel(hash->bottom,  base + EMAC_GALR);
+	writel(hash->top, base + EMAC_GAUR);
+}
+
+void
+gemac_set_laddrN(void *base, struct pfe_mac_addr *address,
+		      unsigned int entry_index)
+{
+	if (entry_index < 1 || entry_index > EMAC_SPEC_ADDR_MAX)
+		return;
+
+	entry_index = entry_index - 1;
+	if (entry_index < 1) {
+		writel(htonl(address->bottom),  base + EMAC_PHY_ADDR_LOW);
+		writel((htonl(address->top) | 0x8808), base +
+			EMAC_PHY_ADDR_HIGH);
+	} else {
+		writel(htonl(address->bottom),  base + ((entry_index - 1) * 8)
+			+ EMAC_SMAC_0_0);
+		writel((htonl(address->top) | 0x8808), base + ((entry_index -
+			1) * 8) + EMAC_SMAC_0_1);
+	}
+}
+
+void
+gemac_clear_laddrN(void *base, unsigned int entry_index)
+{
+	if (entry_index < 1 || entry_index > EMAC_SPEC_ADDR_MAX)
+		return;
+
+	entry_index = entry_index - 1;
+	if (entry_index < 1) {
+		writel(0, base + EMAC_PHY_ADDR_LOW);
+		writel(0, base + EMAC_PHY_ADDR_HIGH);
+	} else {
+		writel(0,  base + ((entry_index - 1) * 8) + EMAC_SMAC_0_0);
+		writel(0, base + ((entry_index - 1) * 8) + EMAC_SMAC_0_1);
+	}
+}
+
+/* Set the loopback mode of the MAC.  This can be either no loopback for
+ * normal operation, local loopback through MAC internal loopback module or PHY
+ *   loopback for external loopback through a PHY.  This asserts the external
+ * loop pin.
+ *
+ * @param[in] base	GEMAC base address.
+ * @param[in] gem_loop	Loopback mode to be enabled. LB_LOCAL - MAC
+ * Loopback,
+ *			LB_EXT - PHY Loopback.
+ */
+void
+gemac_set_loop(void *base, __rte_unused enum mac_loop gem_loop)
+{
+	pr_info("%s()\n", __func__);
+	writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_LOOP, (base +
+		EMAC_RCNTRL_REG));
+}
+
+/* GEMAC allow frames
+ * @param[in] base	GEMAC base address
+ */
+void
+gemac_enable_copy_all(void *base)
+{
+	writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_PROM, (base +
+		EMAC_RCNTRL_REG));
+}
+
+/* GEMAC do not allow frames
+ * @param[in] base	GEMAC base address
+ */
+void
+gemac_disable_copy_all(void *base)
+{
+	writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_PROM, (base +
+		EMAC_RCNTRL_REG));
+}
+
+/* GEMAC allow broadcast function.
+ * @param[in] base	GEMAC base address
+ */
+void
+gemac_allow_broadcast(void *base)
+{
+	writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_BC_REJ, base +
+		EMAC_RCNTRL_REG);
+}
+
+/* GEMAC no broadcast function.
+ * @param[in] base	GEMAC base address
+ */
+void
+gemac_no_broadcast(void *base)
+{
+	writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_BC_REJ, base +
+		EMAC_RCNTRL_REG);
+}
+
+/* GEMAC enable 1536 rx function.
+ * @param[in]	base	GEMAC base address
+ */
+void
+gemac_enable_1536_rx(void *base)
+{
+	/* Set 1536 as Maximum frame length */
+	writel((readl(base + EMAC_RCNTRL_REG) & PFE_MTU_RESET_MASK)
+			| (1536 << 16),
+			base + EMAC_RCNTRL_REG);
+}
+
+/* GEMAC set Max rx function.
+ * @param[in]	base	GEMAC base address
+ */
+int
+gemac_set_rx(void *base, int mtu)
+{
+	if (mtu < HIF_RX_PKT_MIN_SIZE || mtu > JUMBO_FRAME_SIZE) {
+		PFE_PMD_ERR("Invalid or not support MTU size");
+		return -1;
+	}
+
+	if (pfe_svr == SVR_LS1012A_REV1 && mtu > MAX_MTU_ON_REV1) {
+		PFE_PMD_ERR("Max supported MTU on Rev1 is %d", MAX_MTU_ON_REV1 -
+				(RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN));
+		return -1;
+	}
+
+	writel((readl(base + EMAC_RCNTRL_REG) & PFE_MTU_RESET_MASK)
+			| (mtu << 16),
+			base + EMAC_RCNTRL_REG);
+	return 0;
+}
+
+/* GEMAC enable jumbo function.
+ * @param[in]	base	GEMAC base address
+ */
+void
+gemac_enable_rx_jmb(void *base)
+{
+	if (pfe_svr == SVR_LS1012A_REV1) {
+		PFE_PMD_ERR("Jumbo not supported on Rev1");
+		return;
+	}
+
+	writel((readl(base + EMAC_RCNTRL_REG) & PFE_MTU_RESET_MASK) |
+			(JUMBO_FRAME_SIZE << 16), base + EMAC_RCNTRL_REG);
+}
+
+/* GEMAC enable stacked vlan function.
+ * @param[in]	base	GEMAC base address
+ */
+void
+gemac_enable_stacked_vlan(__rte_unused void *base)
+{
+	/* MTIP doesn't support stacked vlan */
+}
+
+/* GEMAC enable pause rx function.
+ * @param[in] base	GEMAC base address
+ */
+void
+gemac_enable_pause_rx(void *base)
+{
+	writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_FCE,
+	       base + EMAC_RCNTRL_REG);
+}
+
+/* GEMAC disable pause rx function.
+ * @param[in] base	GEMAC base address
+ */
+void
+gemac_disable_pause_rx(void *base)
+{
+	writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_FCE,
+	       base + EMAC_RCNTRL_REG);
+}
+
+/* GEMAC enable pause tx function.
+ * @param[in] base GEMAC base address
+ */
+void
+gemac_enable_pause_tx(void *base)
+{
+	writel(EMAC_RX_SECTION_EMPTY_V, base + EMAC_RX_SECTION_EMPTY);
+}
+
+/* GEMAC disable pause tx function.
+ * @param[in] base GEMAC base address
+ */
+void
+gemac_disable_pause_tx(void *base)
+{
+	writel(0x0, base + EMAC_RX_SECTION_EMPTY);
+}
+
+/* GEMAC wol configuration
+ * @param[in] base	GEMAC base address
+ * @param[in] wol_conf	WoL register configuration
+ */
+void
+gemac_set_wol(void *base, u32 wol_conf)
+{
+	u32  val = readl(base + EMAC_ECNTRL_REG);
+
+	if (wol_conf)
+		val |= (EMAC_ECNTRL_MAGIC_ENA | EMAC_ECNTRL_SLEEP);
+	else
+		val &= ~(EMAC_ECNTRL_MAGIC_ENA | EMAC_ECNTRL_SLEEP);
+	writel(val, base + EMAC_ECNTRL_REG);
+}
+
+/* Sets Gemac bus width to 64bit
+ * @param[in] base       GEMAC base address
+ * @param[in] width     gemac bus width to be set possible values are 32/64/128
+ */
+void
+gemac_set_bus_width(__rte_unused void *base, __rte_unused int width)
+{
+}
+
+/* Sets Gemac configuration.
+ * @param[in] base	GEMAC base address
+ * @param[in] cfg	GEMAC configuration
+ */
+void
+gemac_set_config(void *base, struct gemac_cfg *cfg)
+{
+	/*GEMAC config taken from VLSI */
+	writel(0x00000004, base + EMAC_TFWR_STR_FWD);
+	writel(0x00000005, base + EMAC_RX_SECTION_FULL);
+
+	if (pfe_svr == SVR_LS1012A_REV1)
+		writel(0x00000768, base + EMAC_TRUNC_FL);
+	else
+		writel(0x00003fff, base + EMAC_TRUNC_FL);
+
+	writel(0x00000030, base + EMAC_TX_SECTION_EMPTY);
+	writel(0x00000000, base + EMAC_MIB_CTRL_STS_REG);
+
+	gemac_set_mode(base, cfg->mode);
+
+	gemac_set_speed(base, cfg->speed);
+
+	gemac_set_duplex(base, cfg->duplex);
+}
+
+/**************************** GPI ***************************/
+
+/* Initializes a GPI block.
+ * @param[in] base	GPI base address
+ * @param[in] cfg	GPI configuration
+ */
+void
+gpi_init(void *base, struct gpi_cfg *cfg)
+{
+	gpi_reset(base);
+
+	gpi_disable(base);
+
+	gpi_set_config(base, cfg);
+}
+
+/* Resets a GPI block.
+ * @param[in] base	GPI base address
+ */
+void
+gpi_reset(void *base)
+{
+	writel(CORE_SW_RESET, base + GPI_CTRL);
+}
+
+/* Enables a GPI block.
+ * @param[in] base	GPI base address
+ */
+void
+gpi_enable(void *base)
+{
+	writel(CORE_ENABLE, base + GPI_CTRL);
+}
+
+/* Disables a GPI block.
+ * @param[in] base	GPI base address
+ */
+void
+gpi_disable(void *base)
+{
+	writel(CORE_DISABLE, base + GPI_CTRL);
+}
+
+/* Sets the configuration of a GPI block.
+ * @param[in] base	GPI base address
+ * @param[in] cfg	GPI configuration
+ */
+void
+gpi_set_config(void *base, struct gpi_cfg *cfg)
+{
+	writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_ALLOC_CTRL),	base
+		+ GPI_LMEM_ALLOC_ADDR);
+	writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_FREE_CTRL),	base
+		+ GPI_LMEM_FREE_ADDR);
+	writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_ALLOC_CTRL),	base
+		+ GPI_DDR_ALLOC_ADDR);
+	writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL),	base
+		+ GPI_DDR_FREE_ADDR);
+	writel(CBUS_VIRT_TO_PFE(CLASS_INQ_PKTPTR), base + GPI_CLASS_ADDR);
+	writel(DDR_HDR_SIZE, base + GPI_DDR_DATA_OFFSET);
+	writel(LMEM_HDR_SIZE, base + GPI_LMEM_DATA_OFFSET);
+	writel(0, base + GPI_LMEM_SEC_BUF_DATA_OFFSET);
+	writel(0, base + GPI_DDR_SEC_BUF_DATA_OFFSET);
+	writel((DDR_HDR_SIZE << 16) |	LMEM_HDR_SIZE,	base + GPI_HDR_SIZE);
+	writel((DDR_BUF_SIZE << 16) |	LMEM_BUF_SIZE,	base + GPI_BUF_SIZE);
+
+	writel(((cfg->lmem_rtry_cnt << 16) | (GPI_DDR_BUF_EN << 1) |
+		GPI_LMEM_BUF_EN), base + GPI_RX_CONFIG);
+	writel(cfg->tmlf_txthres, base + GPI_TMLF_TX);
+	writel(cfg->aseq_len,	base + GPI_DTX_ASEQ);
+	writel(1, base + GPI_TOE_CHKSUM_EN);
+
+	if (cfg->mtip_pause_reg) {
+		writel(cfg->mtip_pause_reg, base + GPI_CSR_MTIP_PAUSE_REG);
+		writel(EGPI_PAUSE_TIME, base + GPI_TX_PAUSE_TIME);
+	}
+}
+
+/**************************** HIF ***************************/
+/* Initializes HIF copy block.
+ *
+ */
+void
+hif_init(void)
+{
+	/*Initialize HIF registers*/
+	writel((HIF_RX_POLL_CTRL_CYCLE << 16) | HIF_TX_POLL_CTRL_CYCLE,
+	       HIF_POLL_CTRL);
+}
+
+/* Enable hif tx DMA and interrupt
+ *
+ */
+void
+hif_tx_enable(void)
+{
+	writel(HIF_CTRL_DMA_EN, HIF_TX_CTRL);
+	writel((readl(HIF_INT_ENABLE) | HIF_INT_EN | HIF_TXPKT_INT_EN),
+	       HIF_INT_ENABLE);
+}
+
+/* Disable hif tx DMA and interrupt
+ *
+ */
+void
+hif_tx_disable(void)
+{
+	u32	hif_int;
+
+	writel(0, HIF_TX_CTRL);
+
+	hif_int = readl(HIF_INT_ENABLE);
+	hif_int &= HIF_TXPKT_INT_EN;
+	writel(hif_int, HIF_INT_ENABLE);
+}
+
+/* Enable hif rx DMA and interrupt
+ *
+ */
+void
+hif_rx_enable(void)
+{
+	hif_rx_dma_start();
+	writel((readl(HIF_INT_ENABLE) | HIF_INT_EN | HIF_RXPKT_INT_EN),
+	       HIF_INT_ENABLE);
+}
+
+/* Disable hif rx DMA and interrupt
+ *
+ */
+void
+hif_rx_disable(void)
+{
+	u32	hif_int;
+
+	writel(0, HIF_RX_CTRL);
+
+	hif_int = readl(HIF_INT_ENABLE);
+	hif_int &= HIF_RXPKT_INT_EN;
+	writel(hif_int, HIF_INT_ENABLE);
+}
diff --git a/drivers/net/ppfe/pfe_hif.c b/drivers/net/ppfe/pfe_hif.c
new file mode 100644
index 000000000..3a861b420
--- /dev/null
+++ b/drivers/net/ppfe/pfe_hif.c
@@ -0,0 +1,256 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2019 NXP
+ */
+
+#include "pfe_logs.h"
+#include "pfe_mod.h"
+#include <sys/ioctl.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+
+static int
+pfe_hif_alloc_descr(struct pfe_hif *hif)
+{
+	void *addr;
+	int err = 0;
+
+	PMD_INIT_FUNC_TRACE();
+
+	addr = rte_zmalloc(NULL, HIF_RX_DESC_NT * sizeof(struct hif_desc) +
+		HIF_TX_DESC_NT * sizeof(struct hif_desc), RTE_CACHE_LINE_SIZE);
+	if (!addr) {
+		PFE_PMD_ERR("Could not allocate buffer descriptors!");
+		err = -ENOMEM;
+		goto err0;
+	}
+
+	hif->descr_baseaddr_p = pfe_mem_vtop((uintptr_t)addr);
+	hif->descr_baseaddr_v = addr;
+	hif->rx_ring_size = HIF_RX_DESC_NT;
+	hif->tx_ring_size = HIF_TX_DESC_NT;
+
+	return 0;
+
+err0:
+	return err;
+}
+
+static void
+pfe_hif_free_descr(struct pfe_hif *hif)
+{
+	PMD_INIT_FUNC_TRACE();
+
+	rte_free(hif->descr_baseaddr_v);
+}
+
+#if defined(LS1012A_PFE_RESET_WA)
+static void
+pfe_hif_disable_rx_desc(struct pfe_hif *hif)
+{
+	u32 ii;
+	struct hif_desc	*desc = hif->rx_base;
+
+	/*Mark all descriptors as LAST_BD */
+	for (ii = 0; ii < hif->rx_ring_size; ii++) {
+		desc->ctrl |= BD_CTRL_LAST_BD;
+		desc++;
+	}
+}
+
+struct class_rx_hdr_t {
+	u32     next_ptr;       /* ptr to the start of the first DDR buffer */
+	u16     length;         /* total packet length */
+	u16     phyno;          /* input physical port number */
+	u32     status;         /* gemac status bits */
+	u32     status2;            /* reserved for software usage */
+};
+
+/* STATUS_BAD_FRAME_ERR is set for all errors (including checksums if enabled)
+ * except overflow
+ */
+#define STATUS_BAD_FRAME_ERR            BIT(16)
+#define STATUS_LENGTH_ERR               BIT(17)
+#define STATUS_CRC_ERR                  BIT(18)
+#define STATUS_TOO_SHORT_ERR            BIT(19)
+#define STATUS_TOO_LONG_ERR             BIT(20)
+#define STATUS_CODE_ERR                 BIT(21)
+#define STATUS_MC_HASH_MATCH            BIT(22)
+#define STATUS_CUMULATIVE_ARC_HIT       BIT(23)
+#define STATUS_UNICAST_HASH_MATCH       BIT(24)
+#define STATUS_IP_CHECKSUM_CORRECT      BIT(25)
+#define STATUS_TCP_CHECKSUM_CORRECT     BIT(26)
+#define STATUS_UDP_CHECKSUM_CORRECT     BIT(27)
+#define STATUS_OVERFLOW_ERR             BIT(28) /* GPI error */
+#define MIN_PKT_SIZE			64
+#define DUMMY_PKT_COUNT			128
+
+static inline void
+copy_to_lmem(u32 *dst, u32 *src, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i += sizeof(u32))	{
+		*dst = htonl(*src);
+		dst++; src++;
+	}
+}
+#if defined(RTE_TOOLCHAIN_GCC)
+__attribute__ ((optimize(1)))
+#endif
+static void
+send_dummy_pkt_to_hif(void)
+{
+	void *lmem_ptr, *ddr_ptr, *lmem_virt_addr;
+	u64 physaddr;
+	struct class_rx_hdr_t local_hdr;
+	static u32 dummy_pkt[] =  {
+		0x33221100, 0x2b785544, 0xd73093cb, 0x01000608,
+		0x04060008, 0x2b780200, 0xd73093cb, 0x0a01a8c0,
+		0x33221100, 0xa8c05544, 0x00000301, 0x00000000,
+		0x00000000, 0x00000000, 0x00000000, 0xbe86c51f };
+
+	ddr_ptr = (void *)(size_t)readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL);
+	if (!ddr_ptr)
+		return;
+
+	lmem_ptr = (void *)(size_t)readl(BMU1_BASE_ADDR + BMU_ALLOC_CTRL);
+	if (!lmem_ptr)
+		return;
+
+	PFE_PMD_INFO("Sending a dummy pkt to HIF %p %p", ddr_ptr, lmem_ptr);
+	physaddr = DDR_VIRT_TO_PFE(ddr_ptr);
+
+	lmem_virt_addr = (void *)CBUS_PFE_TO_VIRT((unsigned long)lmem_ptr);
+
+	local_hdr.phyno = htons(0); /* RX_PHY_0 */
+	local_hdr.length = htons(MIN_PKT_SIZE);
+
+	local_hdr.next_ptr = htonl((u32)physaddr);
+	/*Mark checksum is correct */
+	local_hdr.status = htonl((STATUS_IP_CHECKSUM_CORRECT |
+				STATUS_UDP_CHECKSUM_CORRECT |
+				STATUS_TCP_CHECKSUM_CORRECT |
+				STATUS_UNICAST_HASH_MATCH |
+				STATUS_CUMULATIVE_ARC_HIT));
+	copy_to_lmem((u32 *)lmem_virt_addr, (u32 *)&local_hdr,
+		     sizeof(local_hdr));
+
+	copy_to_lmem((u32 *)(lmem_virt_addr + LMEM_HDR_SIZE), (u32 *)dummy_pkt,
+		     0x40);
+
+	writel((unsigned long)lmem_ptr, CLASS_INQ_PKTPTR);
+}
+
+void
+pfe_hif_rx_idle(struct pfe_hif *hif)
+{
+	int hif_stop_loop = DUMMY_PKT_COUNT;
+	u32 rx_status;
+
+	pfe_hif_disable_rx_desc(hif);
+	PFE_PMD_INFO("Bringing hif to idle state...");
+	writel(0, HIF_INT_ENABLE);
+	/*If HIF Rx BDP is busy send a dummy packet */
+	do {
+		rx_status = readl(HIF_RX_STATUS);
+		if (rx_status & BDP_CSR_RX_DMA_ACTV)
+			send_dummy_pkt_to_hif();
+
+		sleep(1);
+	} while (--hif_stop_loop);
+
+	if (readl(HIF_RX_STATUS) & BDP_CSR_RX_DMA_ACTV)
+		PFE_PMD_ERR("Failed\n");
+	else
+		PFE_PMD_INFO("Done\n");
+}
+#endif
+
+/*
+ * pfe_hif_init
+ * This function initializes the baseaddresses and irq, etc.
+ */
+int
+pfe_hif_init(struct pfe *pfe)
+{
+	struct pfe_hif *hif = &pfe->hif;
+	int err;
+
+	PMD_INIT_FUNC_TRACE();
+
+#if defined(LS1012A_PFE_RESET_WA)
+	pfe_hif_rx_idle(hif);
+#endif
+
+	err = pfe_hif_alloc_descr(hif);
+	if (err)
+		goto err0;
+
+	rte_spinlock_init(&hif->tx_lock);
+	rte_spinlock_init(&hif->lock);
+
+	gpi_enable(HGPI_BASE_ADDR);
+	if (getenv("PPFE_INTR_SUPPORT")) {
+		struct epoll_event epoll_ev;
+		int event_fd = -1, epoll_fd, pfe_cdev_fd;
+
+		pfe_cdev_fd = open(PFE_CDEV_PATH, O_RDWR);
+		if (pfe_cdev_fd < 0) {
+			PFE_PMD_WARN("Unable to open PFE device file (%s).\n",
+				     PFE_CDEV_PATH);
+			pfe->cdev_fd = PFE_CDEV_INVALID_FD;
+			return -1;
+		}
+		pfe->cdev_fd = pfe_cdev_fd;
+
+		event_fd = eventfd(0, EFD_NONBLOCK);
+		/* hif interrupt enable */
+		err = ioctl(pfe->cdev_fd, PFE_CDEV_HIF_INTR_EN, &event_fd);
+		if (err) {
+			PFE_PMD_ERR("\nioctl failed for intr enable err: %d\n",
+					errno);
+			goto err0;
+		}
+		epoll_fd = epoll_create(1);
+		epoll_ev.events = EPOLLIN | EPOLLPRI | EPOLLET;
+		epoll_ev.data.fd = event_fd;
+		err = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event_fd, &epoll_ev);
+		if (err < 0) {
+			PFE_PMD_ERR("epoll_ctl failed with err = %d\n", errno);
+			goto err0;
+		}
+		pfe->hif.epoll_fd = epoll_fd;
+	}
+	return 0;
+err0:
+	return err;
+}
+
+/* pfe_hif_exit- */
+void
+pfe_hif_exit(struct pfe *pfe)
+{
+	struct pfe_hif *hif = &pfe->hif;
+
+	PMD_INIT_FUNC_TRACE();
+
+	rte_spinlock_lock(&hif->lock);
+	hif->shm->g_client_status[0] = 0;
+	/* Make sure all clients are disabled*/
+	hif->shm->g_client_status[1] = 0;
+
+	rte_spinlock_unlock(&hif->lock);
+
+	if (hif->setuped) {
+#if defined(LS1012A_PFE_RESET_WA)
+		pfe_hif_rx_idle(hif);
+#endif
+		/*Disable Rx/Tx */
+		hif_rx_disable();
+		hif_tx_disable();
+
+		pfe_hif_free_descr(hif);
+		pfe->hif.setuped = 0;
+	}
+	gpi_disable(HGPI_BASE_ADDR);
+}
diff --git a/drivers/net/ppfe/pfe_hif.h b/drivers/net/ppfe/pfe_hif.h
new file mode 100644
index 000000000..fa3c08cc7
--- /dev/null
+++ b/drivers/net/ppfe/pfe_hif.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2019 NXP
+ */
+
+#ifndef _PFE_HIF_H_
+#define _PFE_HIF_H_
+
+#define HIF_CLIENT_QUEUES_MAX	16
+#define HIF_RX_PKT_MIN_SIZE RTE_CACHE_LINE_SIZE
+/*
+ * HIF_TX_DESC_NT value should be always greter than 4,
+ * Otherwise HIF_TX_POLL_MARK will become zero.
+ */
+#define HIF_RX_DESC_NT		64
+#define HIF_TX_DESC_NT		2048
+
+enum {
+	PFE_CL_GEM0 = 0,
+	PFE_CL_GEM1,
+	HIF_CLIENTS_MAX
+};
+
+/*structure to store client queue info */
+struct hif_rx_queue {
+	struct rx_queue_desc *base;
+	u32	size;
+	u32	write_idx;
+};
+
+struct hif_tx_queue {
+	struct tx_queue_desc *base;
+	u32	size;
+	u32	ack_idx;
+};
+
+/*Structure to store the client info */
+struct hif_client {
+	unsigned int	rx_qn;
+	struct hif_rx_queue	rx_q[HIF_CLIENT_QUEUES_MAX];
+	unsigned int	tx_qn;
+	struct hif_tx_queue	tx_q[HIF_CLIENT_QUEUES_MAX];
+};
+
+/*HIF hardware buffer descriptor */
+struct hif_desc {
+	u32 ctrl;
+	u32 status;
+	u32 data;
+	u32 next;
+};
+
+struct __hif_desc {
+	u32 ctrl;
+	u32 status;
+	u32 data;
+};
+
+struct hif_desc_sw {
+	dma_addr_t data;
+	u16 len;
+	u8 client_id;
+	u8 q_no;
+	u16 flags;
+};
+
+struct pfe_hif {
+	/* To store registered clients in hif layer */
+	struct hif_client client[HIF_CLIENTS_MAX];
+	struct hif_shm *shm;
+
+	void	*descr_baseaddr_v;
+	unsigned long	descr_baseaddr_p;
+
+	struct hif_desc *rx_base;
+	u32	rx_ring_size;
+	u32	rxtoclean_index;
+	void	*rx_buf_addr[HIF_RX_DESC_NT];
+	void	*rx_buf_vaddr[HIF_RX_DESC_NT];
+	int	rx_buf_len[HIF_RX_DESC_NT];
+	unsigned int qno;
+	unsigned int client_id;
+	unsigned int client_ctrl;
+	unsigned int started;
+	unsigned int setuped;
+
+	struct hif_desc *tx_base;
+	u32	tx_ring_size;
+	u32	txtosend;
+	u32	txtoclean;
+	u32	txavail;
+	u32	txtoflush;
+	struct hif_desc_sw tx_sw_queue[HIF_TX_DESC_NT];
+	int32_t	epoll_fd; /**< File descriptor created for interrupt polling */
+
+/* tx_lock synchronizes hif packet tx as well as pfe_hif structure access */
+	rte_spinlock_t tx_lock;
+/* lock synchronizes hif rx queue processing */
+	rte_spinlock_t lock;
+	struct rte_device *dev;
+};
+
+int pfe_hif_init(struct pfe *pfe);
+void pfe_hif_exit(struct pfe *pfe);
+void pfe_hif_rx_idle(struct pfe_hif *hif);
+
+#endif /* _PFE_HIF_H_ */
diff --git a/drivers/net/ppfe/pfe_hif_lib.c b/drivers/net/ppfe/pfe_hif_lib.c
new file mode 100644
index 000000000..8f8121be1
--- /dev/null
+++ b/drivers/net/ppfe/pfe_hif_lib.c
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2019 NXP
+ */
+
+#include "pfe_logs.h"
+#include "pfe_mod.h"
+
+int
+pfe_hif_lib_init(__rte_unused struct pfe *pfe)
+{
+	PMD_INIT_FUNC_TRACE();
+
+	return 0;
+}
+
+void
+pfe_hif_lib_exit(__rte_unused struct pfe *pfe)
+{
+	PMD_INIT_FUNC_TRACE();
+}
diff --git a/drivers/net/ppfe/pfe_hif_lib.h b/drivers/net/ppfe/pfe_hif_lib.h
new file mode 100644
index 000000000..2db7338c2
--- /dev/null
+++ b/drivers/net/ppfe/pfe_hif_lib.h
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2019 NXP
+ */
+
+#ifndef _PFE_HIF_LIB_H_
+#define _PFE_HIF_LIB_H_
+
+#define HIF_CL_REQ_TIMEOUT	10
+#define GFP_DMA_PFE 0
+
+enum {
+	REQUEST_CL_REGISTER = 0,
+	REQUEST_CL_UNREGISTER,
+	HIF_REQUEST_MAX
+};
+
+enum {
+	/* Event to indicate that client rx queue is reached water mark level */
+	EVENT_HIGH_RX_WM = 0,
+	/* Event to indicate that, packet received for client */
+	EVENT_RX_PKT_IND,
+	/* Event to indicate that, packet tx done for client */
+	EVENT_TXDONE_IND,
+	HIF_EVENT_MAX
+};
+
+/*structure to store client queue info */
+
+/*structure to store client queue info */
+struct hif_client_rx_queue {
+	struct rx_queue_desc *base;
+	u32	size;
+	u32	read_idx;
+	u32	write_idx;
+	u16	queue_id;
+	u16	port_id;
+	void   *priv;
+};
+
+struct hif_client_tx_queue {
+	struct tx_queue_desc *base;
+	u32	size;
+	u32	read_idx;
+	u32	write_idx;
+	u32	tx_pending;
+	unsigned long jiffies_last_packet;
+	u32	nocpy_flag;
+	u32	prev_tmu_tx_pkts;
+	u32	done_tmu_tx_pkts;
+	u16	queue_id;
+	u16	port_id;
+	void   *priv;
+};
+
+struct hif_client_s {
+	int	id;
+	unsigned int	tx_qn;
+	unsigned int	rx_qn;
+	void	*rx_qbase;
+	void	*tx_qbase;
+	int	tx_qsize;
+	int	rx_qsize;
+	int	cpu_id;
+	int	port_id;
+	struct hif_client_tx_queue tx_q[HIF_CLIENT_QUEUES_MAX];
+	struct hif_client_rx_queue rx_q[HIF_CLIENT_QUEUES_MAX];
+	int (*event_handler)(void *data, int event, int qno);
+	unsigned long queue_mask[HIF_EVENT_MAX];
+	struct pfe *pfe;
+	void *priv;
+};
+
+/*
+ * Client specific shared memory
+ * It contains number of Rx/Tx queues, base addresses and queue sizes
+ */
+struct hif_client_shm {
+	u32 ctrl; /*0-7: number of Rx queues, 8-15: number of tx queues */
+	unsigned long rx_qbase; /*Rx queue base address */
+	u32 rx_qsize; /*each Rx queue size, all Rx queues are of same size */
+	unsigned long tx_qbase; /* Tx queue base address */
+	u32 tx_qsize; /*each Tx queue size, all Tx queues are of same size */
+};
+
+/*Client shared memory ctrl bit description */
+#define CLIENT_CTRL_RX_Q_CNT_OFST	0
+#define CLIENT_CTRL_TX_Q_CNT_OFST	8
+#define CLIENT_CTRL_RX_Q_CNT(ctrl)	(((ctrl) >> CLIENT_CTRL_RX_Q_CNT_OFST) \
+						& 0xFF)
+#define CLIENT_CTRL_TX_Q_CNT(ctrl)	(((ctrl) >> CLIENT_CTRL_TX_Q_CNT_OFST) \
+						& 0xFF)
+
+/*
+ * Shared memory used to communicate between HIF driver and host/client drivers
+ * Before starting the hif driver rx_buf_pool ans rx_buf_pool_cnt should be
+ * initialized with host buffers and buffers count in the pool.
+ * rx_buf_pool_cnt should be >= HIF_RX_DESC_NT.
+ *
+ */
+struct hif_shm {
+	u32 rx_buf_pool_cnt; /*Number of rx buffers available*/
+	/*Rx buffers required to initialize HIF rx descriptors */
+	struct rte_mempool *pool;
+	void *rx_buf_pool[HIF_RX_DESC_NT];
+	unsigned long g_client_status[2]; /*Global client status bit mask */
+	/* Client specific shared memory */
+	struct hif_client_shm client[HIF_CLIENTS_MAX];
+};
+
+#define CL_DESC_OWN	BIT(31)
+/* This sets owner ship to HIF driver */
+#define CL_DESC_LAST	BIT(30)
+/* This indicates last packet for multi buffers handling */
+#define CL_DESC_FIRST	BIT(29)
+/* This indicates first packet for multi buffers handling */
+
+#define CL_DESC_BUF_LEN(x)		((x) & 0xFFFF)
+#define CL_DESC_FLAGS(x)		(((x) & 0xF) << 16)
+#define CL_DESC_GET_FLAGS(x)		(((x) >> 16) & 0xF)
+
+struct rx_queue_desc {
+	void *data;
+	u32	ctrl; /*0-15bit len, 16-20bit flags, 31bit owner*/
+	u32	client_ctrl;
+};
+
+struct tx_queue_desc {
+	void *data;
+	u32	ctrl; /*0-15bit len, 16-20bit flags, 31bit owner*/
+};
+
+/* HIF Rx is not working properly for 2-byte aligned buffers and
+ * ip_header should be 4byte aligned for better iperformance.
+ * "ip_header = 64 + 6(hif_header) + 14 (MAC Header)" will be 4byte aligned.
+ * In case HW parse support:
+ * "ip_header = 64 + 6(hif_header) + 16 (parse) + 14 (MAC Header)" will be
+ * 4byte aligned.
+ */
+#define PFE_HIF_SIZE		sizeof(struct hif_hdr)
+
+#ifdef RTE_LIBRTE_PPFE_SW_PARSE
+#define PFE_PKT_HEADER_SZ	PFE_HIF_SIZE
+#else
+#define PFE_PKT_HEADER_SZ	(PFE_HIF_SIZE + sizeof(struct ppfe_parse))
+#endif
+
+#define MAX_L2_HDR_SIZE		14	/* Not correct for VLAN/PPPoE */
+#define MAX_L3_HDR_SIZE		20	/* Not correct for IPv6 */
+#define MAX_L4_HDR_SIZE		60	/* TCP with maximum options */
+#define MAX_HDR_SIZE		(MAX_L2_HDR_SIZE + MAX_L3_HDR_SIZE \
+				 + MAX_L4_HDR_SIZE)
+/* Used in page mode to clamp packet size to the maximum supported by the hif
+ *hw interface (<16KiB)
+ */
+#define MAX_PFE_PKT_SIZE	16380UL
+
+extern unsigned int emac_txq_cnt;
+
+int pfe_hif_lib_init(struct pfe *pfe);
+void pfe_hif_lib_exit(struct pfe *pfe);
+
+#endif /* _PFE_HIF_LIB_H_ */
diff --git a/drivers/net/ppfe/pfe_mod.h b/drivers/net/ppfe/pfe_mod.h
index e971547a9..f3382f3a7 100644
--- a/drivers/net/ppfe/pfe_mod.h
+++ b/drivers/net/ppfe/pfe_mod.h
@@ -7,6 +7,9 @@
 
 struct pfe;
 
+#include "pfe.h"
+#include "pfe_hif.h"
+#include "pfe_hif_lib.h"
 #include "pfe_eth.h"
 
 #define PHYID_MAX_VAL 32
@@ -42,6 +45,8 @@ struct pfe {
 	uint64_t ddr_size;
 	void *cbus_baseaddr;
 	uint64_t cbus_size;
+	struct ls1012a_pfe_platform_data platform_data;
+	struct pfe_hif hif;
 	struct pfe_eth eth;
 	int mdio_muxval[PHYID_MAX_VAL];
 	uint8_t nb_devs;
diff --git a/drivers/net/ppfe/ppfe_ethdev.c b/drivers/net/ppfe/ppfe_ethdev.c
index 77e3e5c30..6e8db20b8 100644
--- a/drivers/net/ppfe/ppfe_ethdev.c
+++ b/drivers/net/ppfe/ppfe_ethdev.c
@@ -23,9 +23,32 @@ static struct pfe *g_pfe;
  * information from HW.
  */
 unsigned int pfe_svr = SVR_LS1012A_REV1;
+static void *cbus_emac_base[3];
+static void *cbus_gpi_base[3];
 
 int ppfe_logtype_pmd;
 
+/* pfe_gemac_init
+ */
+static int
+pfe_gemac_init(struct pfe_eth_priv_s *priv)
+{
+	struct gemac_cfg cfg;
+
+	cfg.speed = SPEED_1000M;
+	cfg.duplex = DUPLEX_FULL;
+
+	gemac_set_config(priv->EMAC_baseaddr, &cfg);
+	gemac_allow_broadcast(priv->EMAC_baseaddr);
+	gemac_enable_1536_rx(priv->EMAC_baseaddr);
+	gemac_enable_stacked_vlan(priv->EMAC_baseaddr);
+	gemac_enable_pause_rx(priv->EMAC_baseaddr);
+	gemac_set_bus_width(priv->EMAC_baseaddr, 64);
+	gemac_enable_rx_checksum_offload(priv->EMAC_baseaddr);
+
+	return 0;
+}
+
 static void
 pfe_soc_version_get(void)
 {
@@ -100,18 +123,44 @@ pfe_eth_init(struct rte_vdev_device *vdev, struct pfe *pfe, int id)
 {
 	struct rte_eth_dev *eth_dev = NULL;
 	struct pfe_eth_priv_s *priv = NULL;
+	struct ls1012a_eth_platform_data *einfo;
+	struct ls1012a_pfe_platform_data *pfe_info;
 	int err;
 
 	eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*priv));
 	if (eth_dev == NULL)
 		return -ENOMEM;
 
+	/* Extract pltform data */
+	pfe_info = (struct ls1012a_pfe_platform_data *)&pfe->platform_data;
+	if (!pfe_info) {
+		PFE_PMD_ERR("pfe missing additional platform data");
+		err = -ENODEV;
+		goto err0;
+	}
+
+	einfo = (struct ls1012a_eth_platform_data *)pfe_info->ls1012a_eth_pdata;
+
+	/* einfo never be NULL, but no harm in having this check */
+	if (!einfo) {
+		PFE_PMD_ERR("pfe missing additional gemacs platform data");
+		err = -ENODEV;
+		goto err0;
+	}
+
 	priv = eth_dev->data->dev_private;
 	priv->ndev = eth_dev;
+	priv->id = einfo[id].gem_id;
 	priv->pfe = pfe;
 
 	pfe->eth.eth_priv[id] = priv;
 
+	/* Set the info in the priv to the current info */
+	priv->einfo = &einfo[id];
+	priv->EMAC_baseaddr = cbus_emac_base[id];
+	priv->PHY_baseaddr = cbus_emac_base[id];
+	priv->GPI_baseaddr = cbus_gpi_base[id];
+
 #define HIF_GEMAC_TMUQ_BASE	6
 	priv->low_tmu_q = HIF_GEMAC_TMUQ_BASE + (id * 2);
 	priv->high_tmu_q = priv->low_tmu_q + 1;
@@ -129,6 +178,7 @@ pfe_eth_init(struct rte_vdev_device *vdev, struct pfe *pfe, int id)
 	}
 
 	eth_dev->data->mtu = 1500;
+	pfe_gemac_init(priv);
 
 	eth_dev->data->nb_rx_queues = 1;
 	eth_dev->data->nb_tx_queues = 1;
@@ -146,6 +196,58 @@ pfe_eth_init(struct rte_vdev_device *vdev, struct pfe *pfe, int id)
 	return err;
 }
 
+static int
+pfe_get_gemac_if_proprties(struct pfe *pfe,
+		__rte_unused const struct device_node *parent,
+		unsigned int port, unsigned int if_cnt,
+		struct ls1012a_pfe_platform_data *pdata)
+{
+	const struct device_node *gem = NULL;
+	size_t size;
+	unsigned int ii = 0, phy_id = 0;
+	const u32 *addr;
+	const void *mac_addr;
+
+	for (ii = 0; ii < if_cnt; ii++) {
+		gem = of_get_next_child(parent, gem);
+		if (!gem)
+			goto err;
+		addr = of_get_property(gem, "reg", &size);
+		if (addr && (rte_be_to_cpu_32((unsigned int)*addr) == port))
+			break;
+	}
+
+	if (ii >= if_cnt) {
+		PFE_PMD_ERR("Failed to find interface = %d", if_cnt);
+		goto err;
+	}
+
+	pdata->ls1012a_eth_pdata[port].gem_id = port;
+
+	mac_addr = of_get_mac_address(gem);
+
+	if (mac_addr) {
+		memcpy(pdata->ls1012a_eth_pdata[port].mac_addr, mac_addr,
+		       ETH_ALEN);
+	}
+
+	addr = of_get_property(gem, "fsl,mdio-mux-val", &size);
+	if (!addr) {
+		PFE_PMD_ERR("Invalid mdio-mux-val....");
+	} else {
+		phy_id = rte_be_to_cpu_32((unsigned int)*addr);
+		pdata->ls1012a_eth_pdata[port].mdio_muxval = phy_id;
+	}
+	if (pdata->ls1012a_eth_pdata[port].phy_id < 32)
+		pfe->mdio_muxval[pdata->ls1012a_eth_pdata[port].phy_id] =
+			 pdata->ls1012a_eth_pdata[port].mdio_muxval;
+
+	return 0;
+
+err:
+	return -1;
+}
+
 /* Parse integer from integer argument */
 static int
 parse_integer_arg(const char *key __rte_unused,
@@ -204,7 +306,7 @@ pmd_pfe_probe(struct rte_vdev_device *vdev)
 	const uint32_t *addr;
 	uint64_t cbus_addr, ddr_size, cbus_size;
 	int rc = -1, fd = -1, gem_id;
-	unsigned int interface_count = 0;
+	unsigned int ii, interface_count = 0;
 	size_t size = 0;
 	struct pfe_vdev_init_params init_params = {
 		.gem_id = -1
@@ -268,6 +370,7 @@ pmd_pfe_probe(struct rte_vdev_device *vdev)
 		goto err;
 	}
 
+	g_pfe->ddr_baseaddr = pfe_mem_ptov(g_pfe->ddr_phys_baseaddr);
 	g_pfe->ddr_size = ddr_size;
 	g_pfe->cbus_size = cbus_size;
 
@@ -299,6 +402,42 @@ pmd_pfe_probe(struct rte_vdev_device *vdev)
 	PFE_PMD_INFO("num interfaces = %d ", interface_count);
 
 	g_pfe->max_intf  = interface_count;
+	g_pfe->platform_data.ls1012a_mdio_pdata[0].phy_mask = 0xffffffff;
+
+	for (ii = 0; ii < interface_count; ii++) {
+		pfe_get_gemac_if_proprties(g_pfe, np, ii, interface_count,
+					   &g_pfe->platform_data);
+	}
+
+	pfe_lib_init(g_pfe->cbus_baseaddr, g_pfe->ddr_baseaddr,
+		     g_pfe->ddr_phys_baseaddr, g_pfe->ddr_size);
+
+	PFE_PMD_INFO("CLASS version: %x", readl(CLASS_VERSION));
+	PFE_PMD_INFO("TMU version: %x", readl(TMU_VERSION));
+
+	PFE_PMD_INFO("BMU1 version: %x", readl(BMU1_BASE_ADDR + BMU_VERSION));
+	PFE_PMD_INFO("BMU2 version: %x", readl(BMU2_BASE_ADDR + BMU_VERSION));
+
+	PFE_PMD_INFO("EGPI1 version: %x", readl(EGPI1_BASE_ADDR + GPI_VERSION));
+	PFE_PMD_INFO("EGPI2 version: %x", readl(EGPI2_BASE_ADDR + GPI_VERSION));
+	PFE_PMD_INFO("HGPI version: %x", readl(HGPI_BASE_ADDR + GPI_VERSION));
+
+	PFE_PMD_INFO("HIF version: %x", readl(HIF_VERSION));
+	PFE_PMD_INFO("HIF NOPCY version: %x", readl(HIF_NOCPY_VERSION));
+
+	cbus_emac_base[0] = EMAC1_BASE_ADDR;
+	cbus_emac_base[1] = EMAC2_BASE_ADDR;
+
+	cbus_gpi_base[0] = EGPI1_BASE_ADDR;
+	cbus_gpi_base[1] = EGPI2_BASE_ADDR;
+
+	rc = pfe_hif_lib_init(g_pfe);
+	if (rc < 0)
+		goto err_hif_lib;
+
+	rc = pfe_hif_init(g_pfe);
+	if (rc < 0)
+		goto err_hif;
 	pfe_soc_version_get();
 eth_init:
 	if (init_params.gem_id < 0)
@@ -318,6 +457,12 @@ pmd_pfe_probe(struct rte_vdev_device *vdev)
 	return 0;
 
 err_eth:
+	pfe_hif_exit(g_pfe);
+
+err_hif:
+	pfe_hif_lib_exit(g_pfe);
+
+err_hif_lib:
 err_prop:
 	munmap(g_pfe->cbus_baseaddr, cbus_size);
 err:
@@ -347,6 +492,12 @@ pmd_pfe_remove(struct rte_vdev_device *vdev)
 	pfe_eth_exit(eth_dev, g_pfe);
 	munmap(g_pfe->cbus_baseaddr, g_pfe->cbus_size);
 
+	if (g_pfe->nb_devs == 0) {
+		pfe_hif_exit(g_pfe);
+		pfe_hif_lib_exit(g_pfe);
+		rte_free(g_pfe);
+		g_pfe = NULL;
+	}
 	return 0;
 }
 
-- 
2.17.1



More information about the dev mailing list