netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC,v3 01/12] fsl/fman: Add the FMan FLIB headers
@ 2015-05-07 13:05 Madalin Bucur
  2015-05-07 13:05 ` [RFC,v3 02/12] fsl/fman: Add the FMan FLIB Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

This patch presents the FMan Foundation Libraries (FLIB) headers.
The FMan FLib provides the basic API used by the FMan drivers to
configure and control the FMan hardware.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 .../ethernet/freescale/fman/flib/common/general.h  |  41 ++
 .../net/ethernet/freescale/fman/flib/fsl_fman.h    | 743 +++++++++++++++++++++
 2 files changed, 784 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/common/general.h
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman.h

diff --git a/drivers/net/ethernet/freescale/fman/flib/common/general.h b/drivers/net/ethernet/freescale/fman/flib/common/general.h
new file mode 100644
index 0000000..0501f01
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/common/general.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GENERAL_H
+#define __GENERAL_H
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#define iowrite32be(val, addr)		out_be32(&(*addr), val)
+#define ioread32be(addr)		in_be32(&(*addr))
+
+#endif	/* __GENERAL_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman.h
new file mode 100644
index 0000000..8534550
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman.h
@@ -0,0 +1,743 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_H
+#define __FSL_FMAN_H
+
+#include "common/general.h"
+#include <linux/delay.h>
+
+struct fman_ext_pool_params {
+	uint8_t id;		       /* External buffer pool id */
+	uint16_t size;		       /* External buffer pool buffer size */
+};
+
+struct fman_ext_pools {
+	uint8_t num_pools_used;	       /* Number of pools use by this port */
+	struct fman_ext_pool_params *ext_buf_pool;
+					/* Parameters for each port */
+};
+
+struct fman_backup_bm_pools {
+	uint8_t num_backup_pools;	/* Number of BM backup pools -
+					 * must be smaller than the total
+					 * number of pools defined for the
+					 * specified port.
+					 */
+	uint8_t *pool_ids;		/* num_of_backup_pools pool id's,
+					 * specifying which pools should be
+					 * used only as backup. Pool id's
+					 * specified here must be a subset
+					 * of the pools used by the specified
+					 * port.
+					 */
+};
+
+/* A structure for defining BM pool depletion criteria */
+struct fman_buf_pool_depletion {
+	bool buf_pool_depletion_enabled;
+	bool pools_grp_mode_enable;    /* select mode in which pause frames
+					* will be sent after a number of pools
+					* (all together!) are depleted
+					*/
+	uint8_t num_pools;	       /* the number of depleted pools that
+					* will invoke pause frames transmission.
+					*/
+	bool *pools_to_consider;       /* For each pool, true if it should be
+					* considered for depletion (Note - this
+					* pool must be used by this port!).
+					*/
+	bool single_pool_mode_enable;  /* select mode in which pause frames
+					* will be sent after a single-pool
+					* is depleted;
+					*/
+	bool *pools_to_consider_for_single_mode;
+				       /* For each pool, true if it should be
+					* considered for depletion (Note - this
+					* pool must be used by this port!)
+					*/
+};
+
+/* Enum for defining port DMA swap mode */
+enum fman_dma_swap_option {
+	FMAN_DMA_NO_SWP,	   /* No swap, transfer data as is.*/
+	FMAN_DMA_SWP_PPC_LE,	   /* The transferred data should be swapped
+				    * in PowerPc Little Endian mode.
+				    */
+	FMAN_DMA_SWP_BE		   /* The transferred data should be swapped
+				    * in Big Endian mode
+				    */
+};
+
+/* Enum for defining port DMA cache attributes */
+enum fman_dma_cache_option {
+	FMAN_DMA_NO_STASH = 0,	   /* Cacheable, no Allocate (No Stashing) */
+	FMAN_DMA_STASH = 1	   /* Cacheable and Allocate (Stashing on) */
+};
+
+typedef struct fm_prs_result_t fm_prs_result;
+typedef enum e_enet_mode enet_mode_t;
+
+struct fman_revision_info {
+	uint8_t major_rev;			/* Major revision */
+	uint8_t minor_rev;			/* Minor revision */
+};
+
+/* sizes */
+#define CAPWAP_FRAG_EXTRA_SPACE		32
+#define OFFSET_UNITS				16
+#define MAX_INT_OFFSET				240
+#define MAX_IC_SIZE				256
+#define MAX_EXT_OFFSET				496
+#define MAX_EXT_BUFFER_OFFSET			511
+
+/* Memory Mapped Registers */
+#define FMAN_LIODN_TBL	64	/* size of LIODN table */
+
+struct fman_fpm_regs {
+	uint32_t fmfp_tnc;	/* FPM TNUM Control 0x00 */
+	uint32_t fmfp_prc;	/* FPM Port_ID FmCtl Association 0x04 */
+	uint32_t fmfp_brkc;		/* FPM Breakpoint Control 0x08 */
+	uint32_t fmfp_mxd;	/* FPM Flush Control 0x0c */
+	uint32_t fmfp_dist1;	/* FPM Dispatch Thresholds1 0x10 */
+	uint32_t fmfp_dist2;	/* FPM Dispatch Thresholds2 0x14 */
+	uint32_t fm_epi;	/* FM Error Pending Interrupts 0x18 */
+	uint32_t fm_rie;	/* FM Error Interrupt Enable 0x1c */
+	uint32_t fmfp_fcev[4];	/* FPM FMan-Controller Event 1-4 0x20-0x2f */
+	uint32_t res0030[4];	/* res 0x30 - 0x3f */
+	uint32_t fmfp_cee[4];	/* PM FMan-Controller Event 1-4 0x40-0x4f */
+	uint32_t res0050[4];	/* res 0x50-0x5f */
+	uint32_t fmfp_tsc1;	/* FPM TimeStamp Control1 0x60 */
+	uint32_t fmfp_tsc2;	/* FPM TimeStamp Control2 0x64 */
+	uint32_t fmfp_tsp;	/* FPM Time Stamp 0x68 */
+	uint32_t fmfp_tsf;	/* FPM Time Stamp Fraction 0x6c */
+	uint32_t fm_rcr;	/* FM Rams Control 0x70 */
+	uint32_t fmfp_extc;	/* FPM External Requests Control 0x74 */
+	uint32_t fmfp_ext1;	/* FPM External Requests Config1 0x78 */
+	uint32_t fmfp_ext2;	/* FPM External Requests Config2 0x7c */
+	uint32_t fmfp_drd[16];	/* FPM Data_Ram Data 0-15 0x80 - 0xbf */
+	uint32_t fmfp_dra;	/* FPM Data Ram Access 0xc0 */
+	uint32_t fm_ip_rev_1;	/* FM IP Block Revision 1 0xc4 */
+	uint32_t fm_ip_rev_2;	/* FM IP Block Revision 2 0xc8 */
+	uint32_t fm_rstc;	/* FM Reset Command 0xcc */
+	uint32_t fm_cld;	/* FM Classifier Debug 0xd0 */
+	uint32_t fm_npi;	/* FM Normal Pending Interrupts 0xd4 */
+	uint32_t fmfp_exte;	/* FPM External Requests Enable 0xd8 */
+	uint32_t fmfp_ee;	/* FPM Event&Mask 0xdc */
+	uint32_t fmfp_cev[4];	/* FPM CPU Event 1-4 0xe0-0xef */
+	uint32_t res00f0[4];	/* res 0xf0-0xff */
+	uint32_t fmfp_ps[50];	/* FPM Port Status 0x100-0x1c7 */
+	uint32_t res01c8[14];	/* res 0x1c8-0x1ff */
+	uint32_t fmfp_clfabc;	/* FPM CLFABC 0x200 */
+	uint32_t fmfp_clfcc;	/* FPM CLFCC 0x204 */
+	uint32_t fmfp_clfaval;	/* FPM CLFAVAL 0x208 */
+	uint32_t fmfp_clfbval;	/* FPM CLFBVAL 0x20c */
+	uint32_t fmfp_clfcval;	/* FPM CLFCVAL 0x210 */
+	uint32_t fmfp_clfamsk;	/* FPM CLFAMSK 0x214 */
+	uint32_t fmfp_clfbmsk;	/* FPM CLFBMSK 0x218 */
+	uint32_t fmfp_clfcmsk;	/* FPM CLFCMSK 0x21c */
+	uint32_t fmfp_clfamc;	/* FPM CLFAMC 0x220 */
+	uint32_t fmfp_clfbmc;	/* FPM CLFBMC 0x224 */
+	uint32_t fmfp_clfcmc;	/* FPM CLFCMC 0x228 */
+	uint32_t fmfp_decceh;	/* FPM DECCEH 0x22c */
+	uint32_t res0230[116];	/* res 0x230 - 0x3ff */
+	uint32_t fmfp_ts[128];	/* 0x400: FPM Task Status 0x400 - 0x5ff */
+	uint32_t res0600[0x400 - 384];
+};
+
+struct fman_bmi_regs {
+	uint32_t fmbm_init; /* BMI Initialization 0x00 */
+	uint32_t fmbm_cfg1; /* BMI Configuration 1 0x04 */
+	uint32_t fmbm_cfg2; /* BMI Configuration 2 0x08 */
+	uint32_t res000c[5]; /* 0x0c - 0x1f */
+	uint32_t fmbm_ievr; /* Interrupt Event Register 0x20 */
+	uint32_t fmbm_ier; /* Interrupt Enable Register 0x24 */
+	uint32_t fmbm_ifr; /* Interrupt Force Register 0x28 */
+	uint32_t res002c[5]; /* 0x2c - 0x3f */
+	uint32_t fmbm_arb[8]; /* BMI Arbitration 0x40 - 0x5f */
+	uint32_t res0060[12]; /*0x60 - 0x8f */
+	uint32_t fmbm_dtc[3]; /* Debug Trap Counter 0x90 - 0x9b */
+	uint32_t res009c; /* 0x9c */
+	uint32_t fmbm_dcv[3][4]; /* Debug Compare val 0xa0-0xcf */
+	uint32_t fmbm_dcm[3][4]; /* Debug Compare Mask 0xd0-0xff */
+	uint32_t fmbm_gde; /* BMI Global Debug Enable 0x100 */
+	uint32_t fmbm_pp[63]; /* BMI Port Parameters 0x104 - 0x1ff */
+	uint32_t res0200; /* 0x200 */
+	uint32_t fmbm_pfs[63]; /* BMI Port FIFO Size 0x204 - 0x2ff */
+	uint32_t res0300; /* 0x300 */
+	uint32_t fmbm_spliodn[63]; /* Port Partition ID 0x304 - 0x3ff */
+};
+
+struct fman_qmi_regs {
+	uint32_t fmqm_gc; /* General Configuration Register 0x00 */
+	uint32_t res0004; /* 0x04 */
+	uint32_t fmqm_eie; /* Error Interrupt Event Register 0x08 */
+	uint32_t fmqm_eien; /* Error Interrupt Enable Register 0x0c */
+	uint32_t fmqm_eif; /* Error Interrupt Force Register 0x10 */
+	uint32_t fmqm_ie; /* Interrupt Event Register 0x14 */
+	uint32_t fmqm_ien; /* Interrupt Enable Register 0x18 */
+	uint32_t fmqm_if; /* Interrupt Force Register 0x1c */
+	uint32_t fmqm_gs; /* Global Status Register 0x20 */
+	uint32_t fmqm_ts; /* Task Status Register 0x24 */
+	uint32_t fmqm_etfc; /* Enqueue Total Frame Counter 0x28 */
+	uint32_t fmqm_dtfc; /* Dequeue Total Frame Counter 0x2c */
+	uint32_t fmqm_dc0; /* Dequeue Counter 0 0x30 */
+	uint32_t fmqm_dc1; /* Dequeue Counter 1 0x34 */
+	uint32_t fmqm_dc2; /* Dequeue Counter 2 0x38 */
+	uint32_t fmqm_dc3; /* Dequeue Counter 3 0x3c */
+	uint32_t fmqm_dfdc; /* Dequeue FQID from Default Counter 0x40 */
+	uint32_t fmqm_dfcc; /* Dequeue FQID from Context Counter 0x44 */
+	uint32_t fmqm_dffc; /* Dequeue FQID from FD Counter 0x48 */
+	uint32_t fmqm_dcc; /* Dequeue Confirm Counter 0x4c */
+	uint32_t res0050[7]; /* 0x50 - 0x6b */
+	uint32_t fmqm_tapc; /* Tnum Aging Period Control 0x6c */
+	uint32_t fmqm_dmcvc; /* Dequeue MAC Command Valid Counter 0x70 */
+	uint32_t fmqm_difdcc; /* Dequeue Invalid FD Command Counter 0x74 */
+	uint32_t fmqm_da1v; /* Dequeue A1 Valid Counter 0x78 */
+	uint32_t res007c; /* 0x7c */
+	uint32_t fmqm_dtc; /* 0x80 Debug Trap Counter 0x80 */
+	uint32_t fmqm_efddd; /* 0x84 Enqueue Frame desc Dynamic dbg 0x84 */
+	uint32_t res0088[2]; /* 0x88 - 0x8f */
+	struct {
+		uint32_t fmqm_dtcfg1; /* 0x90 dbg trap cfg 1 Register 0x00 */
+		uint32_t fmqm_dtval1; /* Debug Trap Value 1 Register 0x04 */
+		uint32_t fmqm_dtm1; /* Debug Trap Mask 1 Register 0x08 */
+		uint32_t fmqm_dtc1; /* Debug Trap Counter 1 Register 0x0c */
+		uint32_t fmqm_dtcfg2; /* dbg Trap cfg 2 Register 0x10 */
+		uint32_t fmqm_dtval2; /* Debug Trap Value 2 Register 0x14 */
+		uint32_t fmqm_dtm2; /* Debug Trap Mask 2 Register 0x18 */
+		uint32_t res001c; /* 0x1c */
+	} dbg_traps[3];	/* 0x90 - 0xef */
+	uint8_t res00f0[0x400 - 0xf0]; /* 0xf0 - 0x3ff */
+};
+
+struct fman_dma_regs {
+	uint32_t fmdmsr; /* FM DMA status register 0x00 */
+	uint32_t fmdmmr; /* FM DMA mode register 0x04 */
+	uint32_t fmdmtr; /* FM DMA bus threshold register 0x08 */
+	uint32_t fmdmhy; /* FM DMA bus hysteresis register 0x0c */
+	uint32_t fmdmsetr; /* FM DMA SOS emergency Threshold Register 0x10 */
+	uint32_t fmdmtah; /* FM DMA transfer bus address high reg 0x14 */
+	uint32_t fmdmtal; /* FM DMA transfer bus address low reg 0x18 */
+	uint32_t fmdmtcid; /* FM DMA transfer bus communication ID reg 0x1c */
+	uint32_t fmdmra; /* FM DMA bus internal ram address register 0x20 */
+	uint32_t fmdmrd; /* FM DMA bus internal ram data register 0x24 */
+	uint32_t fmdmwcr; /* FM DMA CAM watchdog counter value 0x28 */
+	uint32_t fmdmebcr; /* FM DMA CAM base in MURAM register 0x2c */
+	uint32_t fmdmccqdr; /* FM DMA CAM and CMD Queue Debug reg 0x30 */
+	uint32_t fmdmccqvr1; /* FM DMA CAM and CMD Queue Value reg #1 0x34 */
+	uint32_t fmdmccqvr2; /* FM DMA CAM and CMD Queue Value reg #2 0x38 */
+	uint32_t fmdmcqvr3; /* FM DMA CMD Queue Value register #3 0x3c */
+	uint32_t fmdmcqvr4; /* FM DMA CMD Queue Value register #4 0x40 */
+	uint32_t fmdmcqvr5; /* FM DMA CMD Queue Value register #5 0x44 */
+	uint32_t fmdmsefrc; /* FM DMA Semaphore Entry Full Reject Cntr 0x48 */
+	uint32_t fmdmsqfrc; /* FM DMA Semaphore Queue Full Reject Cntr 0x4c */
+	uint32_t fmdmssrc; /* FM DMA Semaphore SYNC Reject Counter 0x50 */
+	uint32_t fmdmdcr;  /* FM DMA Debug Counter 0x54 */
+	uint32_t fmdmemsr; /* FM DMA Emergency Smoother Register 0x58 */
+	uint32_t res005c; /* 0x5c */
+	uint32_t fmdmplr[FMAN_LIODN_TBL / 2]; /* DMA LIODN regs 0x60-0xdf */
+	uint32_t res00e0[0x400 - 56];
+};
+
+struct fman_rg {
+	struct fman_fpm_regs __iomem *fpm_rg;
+	struct fman_dma_regs __iomem *dma_rg;
+	struct fman_bmi_regs __iomem *bmi_rg;
+	struct fman_qmi_regs __iomem *qmi_rg;
+};
+
+enum fman_dma_cache_override {
+	E_FMAN_DMA_NO_CACHE_OR = 0, /* No override of the Cache field */
+	E_FMAN_DMA_NO_STASH_DATA, /* No data stashing in system level cache */
+	E_FMAN_DMA_MAY_STASH_DATA, /* Stashing allowed in sys level cache */
+	E_FMAN_DMA_STASH_DATA /* Stashing performed in system level cache */
+};
+
+enum fman_dma_aid_mode {
+	E_FMAN_DMA_AID_OUT_PORT_ID = 0,		  /* 4 LSB of PORT_ID */
+	E_FMAN_DMA_AID_OUT_TNUM			  /* 4 LSB of TNUM */
+};
+
+enum fman_dma_dbg_cnt_mode {
+	E_FMAN_DMA_DBG_NO_CNT = 0, /* No counting */
+	E_FMAN_DMA_DBG_CNT_DONE, /* Count DONE commands */
+	E_FMAN_DMA_DBG_CNT_COMM_Q_EM, /* command Q emergency signal */
+	E_FMAN_DMA_DBG_CNT_INT_READ_EM,	/* Read buf emergency signal */
+	E_FMAN_DMA_DBG_CNT_INT_WRITE_EM, /* Write buf emergency signal */
+	E_FMAN_DMA_DBG_CNT_FPM_WAIT, /* FPM WAIT signal */
+	E_FMAN_DMA_DBG_CNT_SIGLE_BIT_ECC, /* Single bit ECC errors */
+	E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT	/* RAW&WAR protection counter */
+};
+
+enum fman_dma_emergency_level {
+	E_FMAN_DMA_EM_EBS = 0, /* EBS emergency */
+	E_FMAN_DMA_EM_SOS /* SOS emergency */
+};
+
+enum fman_catastrophic_err {
+	E_FMAN_CATAST_ERR_STALL_PORT = 0, /* Port_ID stalled reset required */
+	E_FMAN_CATAST_ERR_STALL_TASK /* Only erroneous task is stalled */
+};
+
+enum fman_dma_err {
+	E_FMAN_DMA_ERR_CATASTROPHIC = 0, /* Catastrophic DMA error */
+	E_FMAN_DMA_ERR_REPORT /* Reported DMA error */
+};
+
+struct fman_cfg {
+	uint16_t liodn_bs_pr_port[FMAN_LIODN_TBL];	/* base per port */
+	uint8_t disp_limit_tsh;
+	uint8_t prs_disp_tsh;
+	uint8_t plcr_disp_tsh;
+	uint8_t kg_disp_tsh;
+	uint8_t bmi_disp_tsh;
+	uint8_t qmi_enq_disp_tsh;
+	uint8_t qmi_deq_disp_tsh;
+	uint8_t fm_ctl1_disp_tsh;
+	uint8_t fm_ctl2_disp_tsh;
+	enum fman_dma_cache_override dma_cache_override;
+	enum fman_dma_aid_mode dma_aid_mode;
+	bool dma_aid_override;
+	uint8_t dma_axi_dbg_num_of_beats;
+	uint8_t dma_cam_num_of_entries;
+	uint32_t dma_watchdog;
+	uint8_t dma_comm_qtsh_asrt_emer;
+	uint8_t dma_write_buf_tsh_asrt_emer;
+	uint8_t dma_read_buf_tsh_asrt_emer;
+	uint8_t dma_comm_qtsh_clr_emer;
+	uint8_t dma_write_buf_tsh_clr_emer;
+	uint8_t dma_read_buf_tsh_clr_emer;
+	uint32_t dma_sos_emergency;
+	enum fman_dma_dbg_cnt_mode dma_dbg_cnt_mode;
+	bool dma_stop_on_bus_error;
+	bool dma_en_emergency;
+	uint32_t dma_emergency_bus_select;
+	enum fman_dma_emergency_level dma_emergency_level;
+	bool dma_en_emergency_smoother;
+	uint32_t dma_emergency_switch_counter;
+	bool halt_on_external_activ;
+	bool halt_on_unrecov_ecc_err;
+	enum fman_catastrophic_err catastrophic_err;
+	enum fman_dma_err dma_err;
+	bool en_muram_test_mode;
+	bool en_iram_test_mode;
+	bool external_ecc_rams_enable;
+	uint16_t tnum_aging_period;
+	uint32_t exceptions;
+	uint16_t clk_freq;
+	bool pedantic_dma;
+	uint32_t cam_base_addr;
+	uint32_t fifo_base_addr;
+	uint32_t total_fifo_size;
+	uint8_t total_num_of_tasks;
+	bool qmi_deq_option_support;
+	uint32_t qmi_def_tnums_thresh;
+	bool fman_partition_array;
+	uint8_t num_of_fman_ctrl_evnt_regs;
+};
+
+/* Exceptions */
+#define FMAN_EX_DMA_BUS_ERROR			0x80000000
+#define FMAN_EX_DMA_READ_ECC			0x40000000
+#define FMAN_EX_DMA_SYSTEM_WRITE_ECC		0x20000000
+#define FMAN_EX_DMA_FM_WRITE_ECC		0x10000000
+#define FMAN_EX_FPM_STALL_ON_TASKS		0x08000000
+#define FMAN_EX_FPM_SINGLE_ECC			0x04000000
+#define FMAN_EX_FPM_DOUBLE_ECC			0x02000000
+#define FMAN_EX_QMI_SINGLE_ECC			0x01000000
+#define FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID	0x00800000
+#define FMAN_EX_QMI_DOUBLE_ECC			0x00400000
+#define FMAN_EX_BMI_LIST_RAM_ECC		0x00200000
+#define FMAN_EX_BMI_PIPELINE_ECC		0x00100000
+#define FMAN_EX_BMI_STATISTICS_RAM_ECC		0x00080000
+#define FMAN_EX_IRAM_ECC			0x00040000
+#define FMAN_EX_NURAM_ECC			0x00020000
+#define FMAN_EX_BMI_DISPATCH_RAM_ECC		0x00010000
+
+enum fman_exceptions {
+	E_FMAN_EX_DMA_BUS_ERROR = 0, /* DMA bus error. */
+	E_FMAN_EX_DMA_READ_ECC,	/* Read Buffer ECC error */
+	E_FMAN_EX_DMA_SYSTEM_WRITE_ECC,	/* Write Buffer ECC err on sys side */
+	E_FMAN_EX_DMA_FM_WRITE_ECC, /* Write Buffer ECC error on FM side */
+	E_FMAN_EX_FPM_STALL_ON_TASKS, /* Stall of tasks on FPM */
+	E_FMAN_EX_FPM_SINGLE_ECC, /* Single ECC on FPM. */
+	E_FMAN_EX_FPM_DOUBLE_ECC, /* Double ECC error on FPM ram access */
+	E_FMAN_EX_QMI_SINGLE_ECC, /* Single ECC on QMI. */
+	E_FMAN_EX_QMI_DOUBLE_ECC, /* Double bit ECC occurred on QMI */
+	E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,/* DeQ from unknown port id */
+	E_FMAN_EX_BMI_LIST_RAM_ECC, /* Linked List RAM ECC error */
+	E_FMAN_EX_BMI_STORAGE_PROFILE_ECC, /* storage profile */
+	E_FMAN_EX_BMI_STATISTICS_RAM_ECC, /* Statistics RAM ECC Err Enable */
+	E_FMAN_EX_BMI_DISPATCH_RAM_ECC,	/* Dispatch RAM ECC Error Enable */
+	E_FMAN_EX_IRAM_ECC, /* Double bit ECC occurred on IRAM*/
+	E_FMAN_EX_MURAM_ECC /* Double bit ECC occurred on MURAM*/
+};
+
+#define FPM_PRT_FM_CTL1	0x00000001
+#define FPM_PRT_FM_CTL2	0x00000002
+
+/* DMA definitions */
+
+/* masks */
+#define DMA_MODE_AID_OR			0x20000000
+#define DMA_MODE_SBER			0x10000000
+#define DMA_MODE_BER			0x00200000
+#define DMA_MODE_EB			0x00100000
+#define DMA_MODE_ECC			0x00000020
+#define DMA_MODE_PRIVILEGE_PROT	0x00001000
+#define DMA_MODE_SECURE_PROT		0x00000800
+#define DMA_MODE_EMER_READ		0x00080000
+#define DMA_MODE_EMER_WRITE		0x00040000
+#define DMA_MODE_CACHE_OR_MASK		0xC0000000
+#define DMA_MODE_CEN_MASK		0x0000E000
+#define DMA_MODE_DBG_MASK		0x00000380
+#define DMA_MODE_AXI_DBG_MASK		0x0F000000
+
+#define DMA_EMSR_EMSTR_MASK		0x0000FFFF
+
+#define DMA_TRANSFER_PORTID_MASK	0xFF000000
+#define DMA_TRANSFER_TNUM_MASK		0x00FF0000
+#define DMA_TRANSFER_LIODN_MASK	0x00000FFF
+
+#define DMA_HIGH_LIODN_MASK		0x0FFF0000
+#define DMA_LOW_LIODN_MASK		0x00000FFF
+
+#define DMA_STATUS_CMD_QUEUE_NOT_EMPTY	0x10000000
+#define DMA_STATUS_BUS_ERR		0x08000000
+#define DMA_STATUS_READ_ECC		0x04000000
+#define DMA_STATUS_SYSTEM_WRITE_ECC	0x02000000
+#define DMA_STATUS_FM_WRITE_ECC	0x01000000
+#define DMA_STATUS_SYSTEM_DPEXT_ECC	0x00800000
+#define DMA_STATUS_FM_DPEXT_ECC	0x00400000
+#define DMA_STATUS_SYSTEM_DPDAT_ECC	0x00200000
+#define DMA_STATUS_FM_DPDAT_ECC	0x00100000
+#define DMA_STATUS_FM_SPDAT_ECC	0x00080000
+
+#define FM_LIODN_BASE_MASK		0x00000FFF
+
+/* shifts */
+#define DMA_MODE_CACHE_OR_SHIFT		30
+#define DMA_MODE_BUS_PRI_SHIFT			16
+#define DMA_MODE_AXI_DBG_SHIFT			24
+#define DMA_MODE_CEN_SHIFT			13
+#define DMA_MODE_BUS_PROT_SHIFT		10
+#define DMA_MODE_DBG_SHIFT			7
+#define DMA_MODE_EMER_LVL_SHIFT		6
+#define DMA_MODE_AID_MODE_SHIFT		4
+#define DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS	16
+#define DMA_MODE_MAX_CAM_NUM_OF_ENTRIES	32
+
+#define DMA_THRESH_COMMQ_SHIFT			24
+#define DMA_THRESH_READ_INT_BUF_SHIFT		16
+
+#define DMA_LIODN_SHIFT				16
+
+#define DMA_TRANSFER_PORTID_SHIFT		24
+#define DMA_TRANSFER_TNUM_SHIFT		16
+
+/* sizes */
+#define DMA_MAX_WATCHDOG			0xffffffff
+
+/* others */
+#define DMA_CAM_SIZEOF_ENTRY			0x40
+#define DMA_CAM_ALIGN				0x40
+#define DMA_CAM_UNITS				8
+
+/* General defines */
+
+#define FM_DEBUG_STATUS_REGISTER_OFFSET	0x000d1084UL
+#define FM_UCODE_DEBUG_INSTRUCTION		0x6ffff805UL
+#define FM_PORT_MAX_BW_WEIGHTS			64
+
+/* FPM defines */
+
+/* masks */
+#define FPM_EV_MASK_DOUBLE_ECC		0x80000000
+#define FPM_EV_MASK_STALL		0x40000000
+#define FPM_EV_MASK_SINGLE_ECC		0x20000000
+#define FPM_EV_MASK_RELEASE_FM		0x00010000
+#define FPM_EV_MASK_DOUBLE_ECC_EN	0x00008000
+#define FPM_EV_MASK_STALL_EN		0x00004000
+#define FPM_EV_MASK_SINGLE_ECC_EN	0x00002000
+#define FPM_EV_MASK_EXTERNAL_HALT	0x00000008
+#define FPM_EV_MASK_ECC_ERR_HALT	0x00000004
+
+#define FPM_RAM_RAMS_ECC_EN		0x80000000
+#define FPM_RAM_IRAM_ECC_EN		0x40000000
+#define FPM_RAM_MURAM_ECC		0x00008000
+#define FPM_RAM_IRAM_ECC		0x00004000
+#define FPM_RAM_MURAM_TEST_ECC		0x20000000
+#define FPM_RAM_IRAM_TEST_ECC		0x10000000
+#define FPM_RAM_RAMS_ECC_EN_SRC_SEL	0x08000000
+
+#define FPM_IRAM_ECC_ERR_EX_EN		0x00020000
+#define FPM_MURAM_ECC_ERR_EX_EN		0x00040000
+
+#define FPM_REV1_MAJOR_MASK		0x0000FF00
+#define FPM_REV1_MINOR_MASK		0x000000FF
+
+#define FPM_REV2_INTEG_MASK		0x00FF0000
+#define FPM_REV2_ERR_MASK		0x0000FF00
+#define FPM_REV2_CFG_MASK		0x000000FF
+
+#define FPM_TS_FRACTION_MASK		0x0000FFFF
+#define FPM_TS_CTL_EN			0x80000000
+
+#define FPM_PRC_REALSE_STALLED		0x00800000
+
+#define FPM_PS_STALLED			0x00800000
+#define FPM_PS_FM_CTL1_SEL		0x80000000
+#define FPM_PS_FM_CTL2_SEL		0x40000000
+#define FPM_PS_FM_CTL_SEL_MASK	(FPM_PS_FM_CTL1_SEL | FPM_PS_FM_CTL2_SEL)
+
+#define FPM_RSTC_FM_RESET		0x80000000
+
+#define FPM_DISP_LIMIT_MASK		0x1F000000
+#define FPM_THR1_PRS_MASK		0xFF000000
+#define FPM_THR1_KG_MASK		0x00FF0000
+#define FPM_THR1_PLCR_MASK		0x0000FF00
+#define FPM_THR1_BMI_MASK		0x000000FF
+
+#define FPM_THR2_QMI_ENQ_MASK		0xFF000000
+#define FPM_THR2_QMI_DEQ_MASK		0x000000FF
+#define FPM_THR2_FM_CTL1_MASK		0x00FF0000
+#define FPM_THR2_FM_CTL2_MASK		0x0000FF00
+
+/* shifts */
+#define FPM_DISP_LIMIT_SHIFT		24
+
+#define FPM_THR1_PRS_SHIFT		24
+#define FPM_THR1_KG_SHIFT		16
+#define FPM_THR1_PLCR_SHIFT		8
+#define FPM_THR1_BMI_SHIFT		0
+
+#define FPM_THR2_QMI_ENQ_SHIFT		24
+#define FPM_THR2_QMI_DEQ_SHIFT		0
+#define FPM_THR2_FM_CTL1_SHIFT		16
+#define FPM_THR2_FM_CTL2_SHIFT		8
+
+#define FPM_EV_MASK_CAT_ERR_SHIFT	1
+#define FPM_EV_MASK_DMA_ERR_SHIFT	0
+
+#define FPM_REV1_MAJOR_SHIFT		8
+#define FPM_REV1_MINOR_SHIFT		0
+
+#define FPM_REV2_INTEG_SHIFT		16
+#define FPM_REV2_ERR_SHIFT		8
+#define FPM_REV2_CFG_SHIFT		0
+
+#define FPM_TS_INT_SHIFT		16
+
+#define FPM_PORT_FM_CTL_PORTID_SHIFT	24
+
+#define FPM_PS_FM_CTL_SEL_SHIFT		30
+#define FPM_PRC_ORA_FM_CTL_SEL_SHIFT	16
+
+#define FPM_DISP_LIMIT_SHIFT		24
+
+/* Interrupts defines */
+#define FPM_EVENT_FM_CTL_0		0x00008000
+#define FPM_EVENT_FM_CTL		0x0000FF00
+#define FPM_EVENT_FM_CTL_BRK		0x00000080
+
+/* others */
+#define FPM_MAX_DISP_LIMIT		31
+#define FPM_RSTC_FM_RESET		0x80000000
+#define FPM_RSTC_MAC0_RESET		0x40000000
+#define FPM_RSTC_MAC1_RESET		0x20000000
+#define FPM_RSTC_MAC2_RESET		0x10000000
+#define FPM_RSTC_MAC3_RESET		0x08000000
+#define FPM_RSTC_MAC8_RESET		0x04000000
+#define FPM_RSTC_MAC4_RESET		0x02000000
+#define FPM_RSTC_MAC5_RESET		0x01000000
+#define FPM_RSTC_MAC6_RESET		0x00800000
+#define FPM_RSTC_MAC7_RESET		0x00400000
+#define FPM_RSTC_MAC9_RESET		0x00200000
+/* BMI defines */
+/* masks */
+#define BMI_INIT_START				0x80000000
+#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC	0x80000000
+#define BMI_ERR_INTR_EN_LIST_RAM_ECC		0x40000000
+#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC	0x20000000
+#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC	0x10000000
+#define BMI_NUM_OF_TASKS_MASK			0x3F000000
+#define BMI_NUM_OF_EXTRA_TASKS_MASK		0x000F0000
+#define BMI_NUM_OF_DMAS_MASK			0x00000F00
+#define BMI_NUM_OF_EXTRA_DMAS_MASK		0x0000000F
+#define BMI_FIFO_SIZE_MASK			0x000003FF
+#define BMI_EXTRA_FIFO_SIZE_MASK		0x03FF0000
+#define BMI_CFG1_FIFO_SIZE_MASK		0x03FF0000
+#define BMI_CFG2_DMAS_MASK			0x0000003F
+#define BMI_TOTAL_FIFO_SIZE_MASK		0x07FF0000
+#define BMI_TOTAL_NUM_OF_TASKS_MASK		0x007F0000
+
+/* shifts */
+#define BMI_CFG2_TASKS_SHIFT		16
+#define BMI_CFG2_DMAS_SHIFT		0
+#define BMI_CFG1_FIFO_SIZE_SHIFT	16
+#define BMI_FIFO_SIZE_SHIFT		0
+#define BMI_EXTRA_FIFO_SIZE_SHIFT	16
+#define BMI_NUM_OF_TASKS_SHIFT		24
+#define BMI_EXTRA_NUM_OF_TASKS_SHIFT	16
+#define BMI_NUM_OF_DMAS_SHIFT		8
+#define BMI_EXTRA_NUM_OF_DMAS_SHIFT	0
+
+/* others */
+#define BMI_FIFO_ALIGN			0x100
+#define FMAN_BMI_FIFO_UNITS		0x100
+
+/* QMI defines */
+/* masks */
+#define QMI_CFG_ENQ_EN			0x80000000
+#define QMI_CFG_DEQ_EN			0x40000000
+#define QMI_CFG_EN_COUNTERS		0x10000000
+#define QMI_CFG_SOFT_RESET		0x01000000
+#define QMI_CFG_DEQ_MASK		0x0000003F
+#define QMI_CFG_ENQ_MASK		0x00003F00
+
+#define QMI_ERR_INTR_EN_DOUBLE_ECC	0x80000000
+#define QMI_ERR_INTR_EN_DEQ_FROM_DEF	0x40000000
+#define QMI_INTR_EN_SINGLE_ECC		0x80000000
+
+/* shifts */
+#define QMI_CFG_ENQ_SHIFT		8
+#define QMI_TAPC_TAP			22
+
+#define QMI_GS_HALT_NOT_BUSY		0x00000002
+
+/* IRAM defines */
+/* masks */
+#define IRAM_IADD_AIE			0x80000000
+#define IRAM_READY			0x80000000
+
+uint32_t fman_get_bmi_err_event(struct fman_bmi_regs __iomem *bmi_rg);
+uint32_t fman_get_qmi_err_event(struct fman_qmi_regs __iomem *qmi_rg);
+uint32_t fman_get_dma_com_id(struct fman_dma_regs __iomem *dma_rg);
+uint64_t fman_get_dma_addr(struct fman_dma_regs __iomem *dma_rg);
+uint32_t fman_get_dma_err_event(struct fman_dma_regs __iomem *dma_rg);
+uint32_t fman_get_fpm_err_event(struct fman_fpm_regs __iomem *fpm_rg);
+uint32_t fman_get_muram_err_event(struct fman_fpm_regs __iomem *fpm_rg);
+uint32_t fman_get_iram_err_event(struct fman_fpm_regs __iomem *fpm_rg);
+uint32_t fman_get_qmi_event(struct fman_qmi_regs __iomem *qmi_rg);
+uint32_t fman_get_fpm_error_interrupts(struct fman_fpm_regs __iomem *fpm_rg);
+uint8_t fman_get_qmi_deq_th(struct fman_qmi_regs __iomem *qmi_rg);
+uint8_t fman_get_qmi_enq_th(struct fman_qmi_regs __iomem *qmi_rg);
+uint16_t fman_get_size_of_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+			       uint8_t port_id);
+uint16_t fman_get_size_of_extra_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+				     uint8_t port_id);
+uint8_t fman_get_num_of_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+			      uint8_t port_id);
+uint8_t fman_get_num_extra_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+				 uint8_t port_id);
+uint8_t fman_get_num_of_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+			     uint8_t port_id);
+uint8_t fman_get_num_extra_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+				uint8_t port_id);
+uint32_t fman_get_normal_pending(struct fman_fpm_regs __iomem *fpm_rg);
+uint32_t fman_get_controller_event(struct fman_fpm_regs __iomem *fpm_rg,
+				   uint8_t reg_id);
+uint32_t fman_get_error_pending(struct fman_fpm_regs __iomem *fpm_rg);
+void fman_get_revision(struct fman_fpm_regs __iomem *fpm_rg, uint8_t *major,
+		       uint8_t *minor);
+
+int fman_set_erratum_10gmac_a004_wa(struct fman_fpm_regs __iomem *fpm_rg);
+void fman_set_order_restoration_per_port(struct fman_fpm_regs __iomem *fpm_rg,
+					 uint8_t port_id, bool is_rx_port);
+void fman_set_qmi_enq_th(struct fman_qmi_regs __iomem *qmi_rg, uint8_t val);
+void fman_set_qmi_deq_th(struct fman_qmi_regs __iomem *qmi_rg, uint8_t val);
+void fman_set_liodn_per_port(struct fman_rg *fman_rg,
+			     uint8_t port_id,
+			     uint16_t liodn_base, uint16_t liodn_offset);
+void fman_set_size_of_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+			   uint8_t port_id,
+			   uint32_t size_of_fifo, uint32_t extra_size_of_fifo);
+void fman_set_num_of_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+			   uint8_t port_id,
+			   uint8_t num_of_tasks, uint8_t num_of_extra_tasks);
+void fman_set_num_of_open_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+			       uint8_t port_id,
+			       uint8_t num_of_open_dmas,
+			       uint8_t num_of_extra_open_dmas,
+			       uint8_t total_num_of_dmas);
+int fman_set_exception(struct fman_rg *fman_rg,
+		       enum fman_exceptions exception, bool enable);
+
+void fman_defconfig(struct fman_cfg *cfg);
+int fman_fpm_init(struct fman_fpm_regs __iomem *fpm_rg, struct fman_cfg *cfg);
+int fman_bmi_init(struct fman_bmi_regs __iomem *bmi_rg, struct fman_cfg *cfg);
+int fman_qmi_init(struct fman_qmi_regs __iomem *qmi_rg, struct fman_cfg *cfg);
+int fman_dma_init(struct fman_dma_regs __iomem *dma_rg, struct fman_cfg *cfg);
+void fman_free_resources(struct fman_rg *fman_rg);
+int fman_enable(struct fman_rg *fman_rg, struct fman_cfg *cfg);
+void fman_resume(struct fman_fpm_regs __iomem *fpm_rg);
+
+void fman_enable_time_stamp(struct fman_fpm_regs __iomem *fpm_rg,
+			    uint8_t count1ubit, uint16_t fm_clk_freq);
+void fman_enable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg);
+void fman_disable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg);
+int fman_reset_mac(struct fman_fpm_regs __iomem *fpm_rg, uint8_t mac_id);
+bool fman_rams_ecc_is_external_ctl(struct fman_fpm_regs __iomem *fpm_rg);
+bool fman_is_qmi_halt_not_busy_state(struct fman_qmi_regs __iomem *qmi_rg);
+
+/* default values */
+#define DEFAULT_CATASTROPHIC_ERR		E_FMAN_CATAST_ERR_STALL_PORT
+#define DEFAULT_DMA_ERR				E_FMAN_DMA_ERR_CATASTROPHIC
+/* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_HALT_ON_EXTERNAL_ACTIVATION	false
+/* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_HALT_ON_UNRECOVERABLE_ECC_ERROR false
+#define DEFAULT_EXTERNAL_ECC_RAMS_ENABLE	false
+#define DEFAULT_AID_OVERRIDE			false
+#define DEFAULT_AID_MODE			E_FMAN_DMA_AID_OUT_TNUM
+#define DEFAULT_DMA_COMM_Q_LOW			0x2A
+#define DEFAULT_DMA_COMM_Q_HIGH		0x3F
+#define DEFAULT_CACHE_OVERRIDE			E_FMAN_DMA_NO_CACHE_OR
+#define DEFAULT_DMA_CAM_NUM_OF_ENTRIES		64
+#define DEFAULT_DMA_DBG_CNT_MODE		E_FMAN_DMA_DBG_NO_CNT
+#define DEFAULT_DMA_EN_EMERGENCY		false
+#define DEFAULT_DMA_SOS_EMERGENCY		0
+#define DEFAULT_DMA_WATCHDOG			0	/* disabled */
+#define DEFAULT_DMA_EN_EMERGENCY_SMOOTHER	false
+#define DEFAULT_DMA_EMERGENCY_SWITCH_COUNTER	0
+#define DEFAULT_DISP_LIMIT			0
+#define DEFAULT_PRS_DISP_TH			16
+#define DEFAULT_PLCR_DISP_TH			16
+#define DEFAULT_KG_DISP_TH			16
+#define DEFAULT_BMI_DISP_TH			16
+#define DEFAULT_QMI_ENQ_DISP_TH		16
+#define DEFAULT_QMI_DEQ_DISP_TH		16
+#define DEFAULT_FM_CTL1_DISP_TH		16
+#define DEFAULT_FM_CTL2_DISP_TH		16
+#define DEFAULT_TNUM_AGING_PERIOD		4
+
+#endif	/* __FSL_FMAN_H */
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 02/12] fsl/fman: Add the FMan FLIB
  2015-05-07 13:05 [RFC,v3 01/12] fsl/fman: Add the FMan FLIB headers Madalin Bucur
@ 2015-05-07 13:05 ` Madalin Bucur
  2015-05-07 13:05   ` [RFC,v3 03/12] fsl/fman: Add the FMan port FLIB headers Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

The FMan FLib provides the basic API used by the FMan drivers to
configure and control the FMan hardware.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 drivers/net/ethernet/freescale/Kconfig       |   1 +
 drivers/net/ethernet/freescale/Makefile      |   2 +
 drivers/net/ethernet/freescale/fman/Kconfig  |   7 +
 drivers/net/ethernet/freescale/fman/Makefile |   5 +
 drivers/net/ethernet/freescale/fman/fman.c   | 978 +++++++++++++++++++++++++++
 5 files changed, 993 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/fman/Kconfig
 create mode 100644 drivers/net/ethernet/freescale/fman/Makefile
 create mode 100644 drivers/net/ethernet/freescale/fman/fman.c

diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index 25e3425..24e938d 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -55,6 +55,7 @@ config FEC_MPC52xx_MDIO
 	  If compiled as module, it will be called fec_mpc52xx_phy.
 
 source "drivers/net/ethernet/freescale/fs_enet/Kconfig"
+source "drivers/net/ethernet/freescale/fman/Kconfig"
 
 config FSL_PQ_MDIO
 	tristate "Freescale PQ MDIO"
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index 71debd1..4097c58 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -17,3 +17,5 @@ gianfar_driver-objs := gianfar.o \
 		gianfar_ethtool.o
 obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
 ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
+
+obj-$(CONFIG_FSL_FMAN) += fman/
diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
new file mode 100644
index 0000000..8aeae29
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -0,0 +1,7 @@
+config FSL_FMAN
+	bool "FMan support"
+	depends on FSL_SOC || COMPILE_TEST
+	default n
+	help
+		Freescale Data-Path Acceleration Architecture Frame Manager
+		(FMan) support
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
new file mode 100644
index 0000000..a718f7c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -0,0 +1,5 @@
+subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib
+
+obj-y		+= fsl_fman.o
+
+fsl_fman-objs			:= fman.o
diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c
new file mode 100644
index 0000000..d9ea1e8
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -0,0 +1,978 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_fman.h"
+
+uint32_t fman_get_bmi_err_event(struct fman_bmi_regs __iomem *bmi_rg)
+{
+	uint32_t event, mask, force;
+
+	event = ioread32be(&bmi_rg->fmbm_ievr);
+	mask = ioread32be(&bmi_rg->fmbm_ier);
+	event &= mask;
+	/* clear the forced events */
+	force = ioread32be(&bmi_rg->fmbm_ifr);
+	if (force & event)
+		iowrite32be(force & ~event, &bmi_rg->fmbm_ifr);
+	/* clear the acknowledged events */
+	iowrite32be(event, &bmi_rg->fmbm_ievr);
+	return event;
+}
+
+uint32_t fman_get_qmi_err_event(struct fman_qmi_regs __iomem *qmi_rg)
+{
+	uint32_t event, mask, force;
+
+	event = ioread32be(&qmi_rg->fmqm_eie);
+	mask = ioread32be(&qmi_rg->fmqm_eien);
+	event &= mask;
+
+	/* clear the forced events */
+	force = ioread32be(&qmi_rg->fmqm_eif);
+	if (force & event)
+		iowrite32be(force & ~event, &qmi_rg->fmqm_eif);
+	/* clear the acknowledged events */
+	iowrite32be(event, &qmi_rg->fmqm_eie);
+	return event;
+}
+
+uint32_t fman_get_dma_com_id(struct fman_dma_regs __iomem *dma_rg)
+{
+	return ioread32be(&dma_rg->fmdmtcid);
+}
+
+uint64_t fman_get_dma_addr(struct fman_dma_regs __iomem *dma_rg)
+{
+	uint64_t addr;
+
+	addr = (uint64_t)ioread32be(&dma_rg->fmdmtal);
+	addr |= ((uint64_t)(ioread32be(&dma_rg->fmdmtah)) << 32);
+
+	return addr;
+}
+
+uint32_t fman_get_dma_err_event(struct fman_dma_regs __iomem *dma_rg)
+{
+	uint32_t status, mask;
+
+	status = ioread32be(&dma_rg->fmdmsr);
+	mask = ioread32be(&dma_rg->fmdmmr);
+
+	/* clear DMA_STATUS_BUS_ERR if mask has no DMA_MODE_BER */
+	if ((mask & DMA_MODE_BER) != DMA_MODE_BER)
+		status &= ~DMA_STATUS_BUS_ERR;
+
+	/* clear relevant bits if mask has no DMA_MODE_ECC */
+	if ((mask & DMA_MODE_ECC) != DMA_MODE_ECC)
+		status &= ~(DMA_STATUS_FM_SPDAT_ECC |
+			    DMA_STATUS_READ_ECC |
+			    DMA_STATUS_SYSTEM_WRITE_ECC |
+			    DMA_STATUS_FM_WRITE_ECC);
+
+	/* clear set events */
+	iowrite32be(status, &dma_rg->fmdmsr);
+
+	return status;
+}
+
+uint32_t fman_get_fpm_err_event(struct fman_fpm_regs __iomem *fpm_rg)
+{
+	uint32_t event;
+
+	event = ioread32be(&fpm_rg->fmfp_ee);
+	/* clear the all occurred events */
+	iowrite32be(event, &fpm_rg->fmfp_ee);
+	return event;
+}
+
+uint32_t fman_get_muram_err_event(struct fman_fpm_regs __iomem *fpm_rg)
+{
+	uint32_t event, mask;
+
+	event = ioread32be(&fpm_rg->fm_rcr);
+	mask = ioread32be(&fpm_rg->fm_rie);
+
+	/* clear MURAM event bit (do not clear IRAM event) */
+	iowrite32be(event & ~FPM_RAM_IRAM_ECC, &fpm_rg->fm_rcr);
+
+	if ((mask & FPM_MURAM_ECC_ERR_EX_EN))
+		return event;
+	else
+		return 0;
+}
+
+uint32_t fman_get_iram_err_event(struct fman_fpm_regs __iomem *fpm_rg)
+{
+	uint32_t event, mask;
+
+	event = ioread32be(&fpm_rg->fm_rcr);
+	mask = ioread32be(&fpm_rg->fm_rie);
+	/* clear IRAM event bit (do not clear MURAM event) */
+	iowrite32be(event & ~FPM_RAM_MURAM_ECC, &fpm_rg->fm_rcr);
+
+	if ((mask & FPM_IRAM_ECC_ERR_EX_EN))
+		return event;
+	else
+		return 0;
+}
+
+uint32_t fman_get_qmi_event(struct fman_qmi_regs __iomem *qmi_rg)
+{
+	uint32_t event, mask, force;
+
+	event = ioread32be(&qmi_rg->fmqm_ie);
+	mask = ioread32be(&qmi_rg->fmqm_ien);
+	event &= mask;
+	/* clear the forced events */
+	force = ioread32be(&qmi_rg->fmqm_if);
+	if (force & event)
+		iowrite32be(force & ~event, &qmi_rg->fmqm_if);
+	/* clear the acknowledged events */
+	iowrite32be(event, &qmi_rg->fmqm_ie);
+	return event;
+}
+
+void fman_enable_time_stamp(struct fman_fpm_regs __iomem *fpm_rg,
+			    uint8_t count1ubit, uint16_t fm_clk_freq)
+{
+	uint32_t tmp;
+	uint64_t frac;
+	uint32_t intgr;
+	uint32_t ts_freq = (uint32_t)(1 << count1ubit);	/* in Mhz */
+
+	/* configure timestamp so that bit 8 will count 1 microsecond
+	 * Find effective count rate at TIMESTAMP least significant bits:
+	 * Effective_Count_Rate = 1MHz x 2^8 = 256MHz
+	 * Find frequency ratio between effective count rate and the clock:
+	 * Effective_Count_Rate / CLK e.g. for 600 MHz clock:
+	 * 256/600 = 0.4266666...
+	 */
+
+	intgr = ts_freq / fm_clk_freq;
+	/* we multiply by 2^16 to keep the fraction of the division
+	 * we do not div back, since we write this value as a fraction
+	 * see spec
+	 */
+
+	frac = ((ts_freq << 16) - (intgr << 16) * fm_clk_freq) / fm_clk_freq;
+	/* we check remainder of the division in order to round up if not int */
+	if (((ts_freq << 16) - (intgr << 16) * fm_clk_freq) % fm_clk_freq)
+		frac++;
+
+	tmp = (intgr << FPM_TS_INT_SHIFT) | (uint16_t)frac;
+	iowrite32be(tmp, &fpm_rg->fmfp_tsc2);
+
+	/* enable timestamp with original clock */
+	iowrite32be(FPM_TS_CTL_EN, &fpm_rg->fmfp_tsc1);
+}
+
+uint32_t fman_get_fpm_error_interrupts(struct fman_fpm_regs __iomem *fpm_rg)
+{
+	return ioread32be(&fpm_rg->fm_epi);
+}
+
+int fman_set_erratum_10gmac_a004_wa(struct fman_fpm_regs __iomem *fpm_rg)
+{
+	int timeout = 100;
+
+	iowrite32be(0x40000000, &fpm_rg->fmfp_extc);
+
+	while ((ioread32be(&fpm_rg->fmfp_extc) & 0x40000000) && --timeout)
+		usleep_range(10, 11);
+
+	if (!timeout)
+		return -EIO;
+	return 0;
+}
+
+void fman_set_order_restoration_per_port(struct fman_fpm_regs __iomem *fpm_rg,
+					 uint8_t port_id, bool is_rx_port)
+{
+	uint32_t tmp = 0;
+
+	tmp = (uint32_t)(port_id << FPM_PORT_FM_CTL_PORTID_SHIFT);
+
+	tmp |= (FPM_PRT_FM_CTL2 | FPM_PRT_FM_CTL1);
+
+	/* order restoration */
+	if (port_id % 2)
+		tmp |= (FPM_PRT_FM_CTL1 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT);
+	else
+		tmp |= (FPM_PRT_FM_CTL2 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT);
+
+	iowrite32be(tmp, &fpm_rg->fmfp_prc);
+}
+
+uint8_t fman_get_qmi_deq_th(struct fman_qmi_regs __iomem *qmi_rg)
+{
+	return (uint8_t)ioread32be(&qmi_rg->fmqm_gc);
+}
+
+uint8_t fman_get_qmi_enq_th(struct fman_qmi_regs __iomem *qmi_rg)
+{
+	return (uint8_t)(ioread32be(&qmi_rg->fmqm_gc) >> 8);
+}
+
+void fman_set_qmi_enq_th(struct fman_qmi_regs __iomem *qmi_rg, uint8_t val)
+{
+	uint32_t tmp_reg;
+
+	tmp_reg = ioread32be(&qmi_rg->fmqm_gc);
+	tmp_reg &= ~QMI_CFG_ENQ_MASK;
+	tmp_reg |= ((uint32_t)val << 8);
+	iowrite32be(tmp_reg, &qmi_rg->fmqm_gc);
+}
+
+void fman_set_qmi_deq_th(struct fman_qmi_regs __iomem *qmi_rg, uint8_t val)
+{
+	uint32_t tmp_reg;
+
+	tmp_reg = ioread32be(&qmi_rg->fmqm_gc);
+	tmp_reg &= ~QMI_CFG_DEQ_MASK;
+	tmp_reg |= (uint32_t)val;
+	iowrite32be(tmp_reg, &qmi_rg->fmqm_gc);
+}
+
+void fman_set_liodn_per_port(struct fman_rg *fman_rg, uint8_t port_id,
+			     uint16_t liodn_base, uint16_t liodn_ofst)
+{
+	uint32_t tmp;
+
+	/* set LIODN base for this port */
+	tmp = ioread32be(&fman_rg->dma_rg->fmdmplr[port_id / 2]);
+	if (port_id % 2) {
+		tmp &= ~FM_LIODN_BASE_MASK;
+		tmp |= (uint32_t)liodn_base;
+	} else {
+		tmp &= ~(FM_LIODN_BASE_MASK << DMA_LIODN_SHIFT);
+		tmp |= (uint32_t)liodn_base << DMA_LIODN_SHIFT;
+	}
+	iowrite32be(tmp, &fman_rg->dma_rg->fmdmplr[port_id / 2]);
+	iowrite32be((uint32_t)liodn_ofst,
+		    &fman_rg->bmi_rg->fmbm_spliodn[port_id - 1]);
+}
+
+int fman_reset_mac(struct fman_fpm_regs __iomem *fpm_rg, uint8_t mac_id)
+{
+	uint32_t msk, timeout = 100;
+
+	/* Get the relevant bit mask */
+	switch (mac_id) {
+	case 0:
+		msk = FPM_RSTC_MAC0_RESET;
+		break;
+	case 1:
+		msk = FPM_RSTC_MAC1_RESET;
+		break;
+	case 2:
+		msk = FPM_RSTC_MAC2_RESET;
+		break;
+	case 3:
+		msk = FPM_RSTC_MAC3_RESET;
+		break;
+	case 4:
+		msk = FPM_RSTC_MAC4_RESET;
+		break;
+	case 5:
+		msk = FPM_RSTC_MAC5_RESET;
+		break;
+	case 6:
+		msk = FPM_RSTC_MAC6_RESET;
+		break;
+	case 7:
+		msk = FPM_RSTC_MAC7_RESET;
+		break;
+	case 8:
+		msk = FPM_RSTC_MAC8_RESET;
+		break;
+	case 9:
+		msk = FPM_RSTC_MAC9_RESET;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* reset */
+	iowrite32be(msk, &fpm_rg->fm_rstc);
+	while ((ioread32be(&fpm_rg->fm_rstc) & msk) && --timeout)
+		usleep_range(10, 11);
+
+	if (!timeout)
+		return -EIO;
+	return 0;
+}
+
+uint16_t fman_get_size_of_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+			       uint8_t port_id)
+{
+	uint32_t tmp_reg;
+
+	tmp_reg = ioread32be(&bmi_rg->fmbm_pfs[port_id - 1]);
+	return (uint16_t)((tmp_reg & BMI_FIFO_SIZE_MASK) + 1);
+}
+
+uint16_t fman_get_size_of_extra_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+				     uint8_t port_id)
+{
+	uint32_t tmp_reg;
+
+	tmp_reg = ioread32be(&bmi_rg->fmbm_pfs[port_id - 1]);
+	return (uint16_t)((tmp_reg & BMI_EXTRA_FIFO_SIZE_MASK) >>
+			   BMI_EXTRA_FIFO_SIZE_SHIFT);
+}
+
+void fman_set_size_of_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+			   uint8_t port_id, uint32_t sz_fifo,
+			   uint32_t extra_sz_fifo)
+{
+	uint32_t tmp;
+
+	/* calculate reg */
+	tmp = (uint32_t)((sz_fifo / FMAN_BMI_FIFO_UNITS - 1) |
+			  ((extra_sz_fifo / FMAN_BMI_FIFO_UNITS) <<
+			   BMI_EXTRA_FIFO_SIZE_SHIFT));
+	iowrite32be(tmp, &bmi_rg->fmbm_pfs[port_id - 1]);
+}
+
+uint8_t fman_get_num_of_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+			      uint8_t port_id)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+	return (uint8_t)(((tmp & BMI_NUM_OF_TASKS_MASK) >>
+			   BMI_NUM_OF_TASKS_SHIFT) + 1);
+}
+
+uint8_t fman_get_num_extra_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+				 uint8_t port_id)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+	return (uint8_t)((tmp & BMI_NUM_OF_EXTRA_TASKS_MASK) >>
+			  BMI_EXTRA_NUM_OF_TASKS_SHIFT);
+}
+
+void fman_set_num_of_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+			   uint8_t port_id, uint8_t num_tasks,
+			   uint8_t num_extra_tasks)
+{
+	uint32_t tmp;
+
+	/* calculate reg */
+	tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) &
+	    ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK);
+	tmp |= ((uint32_t)((num_tasks - 1) << BMI_NUM_OF_TASKS_SHIFT) |
+		(uint32_t)(num_extra_tasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT));
+	iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]);
+}
+
+uint8_t fman_get_num_of_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+			     uint8_t port_id)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+	return (uint8_t)(((tmp & BMI_NUM_OF_DMAS_MASK) >>
+			   BMI_NUM_OF_DMAS_SHIFT) + 1);
+}
+
+uint8_t fman_get_num_extra_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+				uint8_t port_id)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+	return (uint8_t)((tmp & BMI_NUM_OF_EXTRA_DMAS_MASK) >>
+			  BMI_EXTRA_NUM_OF_DMAS_SHIFT);
+}
+
+void fman_set_num_of_open_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+			       uint8_t port_id, uint8_t num_open_dmas,
+			       uint8_t num_extra_open_dmas,
+			       uint8_t total_num_dmas)
+{
+	uint32_t tmp = 0;
+
+	/* calculate reg */
+	tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) &
+	    ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK);
+	tmp |= (uint32_t)(((num_open_dmas - 1) << BMI_NUM_OF_DMAS_SHIFT) |
+			   (num_extra_open_dmas <<
+			    BMI_EXTRA_NUM_OF_DMAS_SHIFT));
+	iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]);
+
+	/* update total num of DMA's with committed number of open DMAS,
+	 * and max uncommitted pool.
+	 */
+	if (total_num_dmas) {
+		tmp = ioread32be(&bmi_rg->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK;
+		tmp |= (uint32_t)(total_num_dmas - 1) << BMI_CFG2_DMAS_SHIFT;
+		iowrite32be(tmp, &bmi_rg->fmbm_cfg2);
+	}
+}
+
+/* API Init unit functions */
+
+void fman_defconfig(struct fman_cfg *cfg)
+{
+	memset(cfg, 0, sizeof(struct fman_cfg));
+
+	cfg->catastrophic_err = DEFAULT_CATASTROPHIC_ERR;
+	cfg->dma_err = DEFAULT_DMA_ERR;
+	cfg->halt_on_external_activ = DEFAULT_HALT_ON_EXTERNAL_ACTIVATION;
+	cfg->halt_on_unrecov_ecc_err = DEFAULT_HALT_ON_UNRECOVERABLE_ECC_ERROR;
+	cfg->en_iram_test_mode = false;
+	cfg->en_muram_test_mode = false;
+	cfg->external_ecc_rams_enable = DEFAULT_EXTERNAL_ECC_RAMS_ENABLE;
+
+	cfg->dma_aid_override = DEFAULT_AID_OVERRIDE;
+	cfg->dma_aid_mode = DEFAULT_AID_MODE;
+	cfg->dma_comm_qtsh_clr_emer = DEFAULT_DMA_COMM_Q_LOW;
+	cfg->dma_comm_qtsh_asrt_emer = DEFAULT_DMA_COMM_Q_HIGH;
+	cfg->dma_cache_override = DEFAULT_CACHE_OVERRIDE;
+	cfg->dma_cam_num_of_entries = DEFAULT_DMA_CAM_NUM_OF_ENTRIES;
+	cfg->dma_dbg_cnt_mode = DEFAULT_DMA_DBG_CNT_MODE;
+	cfg->dma_en_emergency = DEFAULT_DMA_EN_EMERGENCY;
+	cfg->dma_sos_emergency = DEFAULT_DMA_SOS_EMERGENCY;
+	cfg->dma_watchdog = DEFAULT_DMA_WATCHDOG;
+	cfg->dma_en_emergency_smoother = DEFAULT_DMA_EN_EMERGENCY_SMOOTHER;
+	cfg->dma_emergency_switch_counter =
+	    DEFAULT_DMA_EMERGENCY_SWITCH_COUNTER;
+	cfg->disp_limit_tsh = DEFAULT_DISP_LIMIT;
+	cfg->prs_disp_tsh = DEFAULT_PRS_DISP_TH;
+	cfg->plcr_disp_tsh = DEFAULT_PLCR_DISP_TH;
+	cfg->kg_disp_tsh = DEFAULT_KG_DISP_TH;
+	cfg->bmi_disp_tsh = DEFAULT_BMI_DISP_TH;
+	cfg->qmi_enq_disp_tsh = DEFAULT_QMI_ENQ_DISP_TH;
+	cfg->qmi_deq_disp_tsh = DEFAULT_QMI_DEQ_DISP_TH;
+	cfg->fm_ctl1_disp_tsh = DEFAULT_FM_CTL1_DISP_TH;
+	cfg->fm_ctl2_disp_tsh = DEFAULT_FM_CTL2_DISP_TH;
+
+	cfg->pedantic_dma = false;
+	cfg->tnum_aging_period = DEFAULT_TNUM_AGING_PERIOD;
+	cfg->dma_stop_on_bus_error = false;
+	cfg->qmi_deq_option_support = false;
+}
+
+/*  fm_init
+ *  Initializes the FM module
+ *  h_fm - FM module descriptor
+ *  Return	  0 on success; Error code otherwise.
+ */
+int fman_dma_init(struct fman_dma_regs __iomem *dma_rg, struct fman_cfg *cfg)
+{
+	uint32_t tmp_reg;
+
+	/* Init DMA Registers */
+
+	/* clear status reg events */
+	tmp_reg = (DMA_STATUS_BUS_ERR | DMA_STATUS_READ_ECC |
+		   DMA_STATUS_SYSTEM_WRITE_ECC | DMA_STATUS_FM_WRITE_ECC);
+	iowrite32be(ioread32be(&dma_rg->fmdmsr) | tmp_reg, &dma_rg->fmdmsr);
+
+	/* configure mode register */
+	tmp_reg = 0;
+	tmp_reg |= cfg->dma_cache_override << DMA_MODE_CACHE_OR_SHIFT;
+	if (cfg->dma_aid_override)
+		tmp_reg |= DMA_MODE_AID_OR;
+	if (cfg->exceptions & FMAN_EX_DMA_BUS_ERROR)
+		tmp_reg |= DMA_MODE_BER;
+	if ((cfg->exceptions & FMAN_EX_DMA_SYSTEM_WRITE_ECC) |
+	    (cfg->exceptions & FMAN_EX_DMA_READ_ECC) |
+	    (cfg->exceptions & FMAN_EX_DMA_FM_WRITE_ECC))
+		tmp_reg |= DMA_MODE_ECC;
+	if (cfg->dma_stop_on_bus_error)
+		tmp_reg |= DMA_MODE_SBER;
+	if (cfg->dma_axi_dbg_num_of_beats)
+		tmp_reg |= (uint32_t)(DMA_MODE_AXI_DBG_MASK &
+				       ((cfg->dma_axi_dbg_num_of_beats -
+					 1) << DMA_MODE_AXI_DBG_SHIFT));
+
+	if (cfg->dma_en_emergency) {
+		tmp_reg |= cfg->dma_emergency_bus_select;
+		tmp_reg |= cfg->dma_emergency_level << DMA_MODE_EMER_LVL_SHIFT;
+		if (cfg->dma_en_emergency_smoother)
+			iowrite32be(cfg->dma_emergency_switch_counter,
+				    &dma_rg->fmdmemsr);
+	}
+	tmp_reg |= ((cfg->dma_cam_num_of_entries / DMA_CAM_UNITS) - 1) <<
+	    DMA_MODE_CEN_SHIFT;
+	tmp_reg |= DMA_MODE_SECURE_PROT;
+	tmp_reg |= cfg->dma_dbg_cnt_mode << DMA_MODE_DBG_SHIFT;
+	tmp_reg |= cfg->dma_aid_mode << DMA_MODE_AID_MODE_SHIFT;
+
+	if (cfg->pedantic_dma)
+		tmp_reg |= DMA_MODE_EMER_READ;
+
+	iowrite32be(tmp_reg, &dma_rg->fmdmmr);
+
+	/* configure thresholds register */
+	tmp_reg = ((uint32_t)cfg->dma_comm_qtsh_asrt_emer <<
+		   DMA_THRESH_COMMQ_SHIFT) |
+	    ((uint32_t)cfg->dma_read_buf_tsh_asrt_emer <<
+	     DMA_THRESH_READ_INT_BUF_SHIFT) |
+	    ((uint32_t)cfg->dma_write_buf_tsh_asrt_emer);
+
+	iowrite32be(tmp_reg, &dma_rg->fmdmtr);
+
+	/* configure hysteresis register */
+	tmp_reg = ((uint32_t)cfg->dma_comm_qtsh_clr_emer <<
+		   DMA_THRESH_COMMQ_SHIFT) |
+	    ((uint32_t)cfg->dma_read_buf_tsh_clr_emer <<
+	     DMA_THRESH_READ_INT_BUF_SHIFT) |
+	    ((uint32_t)cfg->dma_write_buf_tsh_clr_emer);
+
+	iowrite32be(tmp_reg, &dma_rg->fmdmhy);
+
+	/* configure emergency threshold */
+	iowrite32be(cfg->dma_sos_emergency, &dma_rg->fmdmsetr);
+
+	/* configure Watchdog */
+	iowrite32be((cfg->dma_watchdog * cfg->clk_freq), &dma_rg->fmdmwcr);
+
+	iowrite32be(cfg->cam_base_addr, &dma_rg->fmdmebcr);
+
+	return 0;
+}
+
+int fman_fpm_init(struct fman_fpm_regs __iomem *fpm_rg, struct fman_cfg *cfg)
+{
+	uint32_t tmp_reg;
+	int i;
+
+	/* Init FPM Registers */
+
+	tmp_reg = (uint32_t)(cfg->disp_limit_tsh << FPM_DISP_LIMIT_SHIFT);
+	iowrite32be(tmp_reg, &fpm_rg->fmfp_mxd);
+
+	tmp_reg = (((uint32_t)cfg->prs_disp_tsh << FPM_THR1_PRS_SHIFT) |
+		   ((uint32_t)cfg->kg_disp_tsh << FPM_THR1_KG_SHIFT) |
+		   ((uint32_t)cfg->plcr_disp_tsh << FPM_THR1_PLCR_SHIFT) |
+		   ((uint32_t)cfg->bmi_disp_tsh << FPM_THR1_BMI_SHIFT));
+	iowrite32be(tmp_reg, &fpm_rg->fmfp_dist1);
+
+	tmp_reg =
+		(((uint32_t)cfg->qmi_enq_disp_tsh << FPM_THR2_QMI_ENQ_SHIFT) |
+		 ((uint32_t)cfg->qmi_deq_disp_tsh << FPM_THR2_QMI_DEQ_SHIFT) |
+		 ((uint32_t)cfg->fm_ctl1_disp_tsh << FPM_THR2_FM_CTL1_SHIFT) |
+		 ((uint32_t)cfg->fm_ctl2_disp_tsh << FPM_THR2_FM_CTL2_SHIFT));
+	iowrite32be(tmp_reg, &fpm_rg->fmfp_dist2);
+
+	/* define exceptions and error behavior */
+	tmp_reg = 0;
+	/* Clear events */
+	tmp_reg |= (FPM_EV_MASK_STALL | FPM_EV_MASK_DOUBLE_ECC |
+		    FPM_EV_MASK_SINGLE_ECC);
+	/* enable interrupts */
+	if (cfg->exceptions & FMAN_EX_FPM_STALL_ON_TASKS)
+		tmp_reg |= FPM_EV_MASK_STALL_EN;
+	if (cfg->exceptions & FMAN_EX_FPM_SINGLE_ECC)
+		tmp_reg |= FPM_EV_MASK_SINGLE_ECC_EN;
+	if (cfg->exceptions & FMAN_EX_FPM_DOUBLE_ECC)
+		tmp_reg |= FPM_EV_MASK_DOUBLE_ECC_EN;
+	tmp_reg |= (cfg->catastrophic_err << FPM_EV_MASK_CAT_ERR_SHIFT);
+	tmp_reg |= (cfg->dma_err << FPM_EV_MASK_DMA_ERR_SHIFT);
+	if (!cfg->halt_on_external_activ)
+		tmp_reg |= FPM_EV_MASK_EXTERNAL_HALT;
+	if (!cfg->halt_on_unrecov_ecc_err)
+		tmp_reg |= FPM_EV_MASK_ECC_ERR_HALT;
+	iowrite32be(tmp_reg, &fpm_rg->fmfp_ee);
+
+	/* clear all fmCtls event registers */
+	for (i = 0; i < cfg->num_of_fman_ctrl_evnt_regs; i++)
+		iowrite32be(0xFFFFFFFF, &fpm_rg->fmfp_cev[i]);
+
+	/* RAM ECC -  enable and clear events */
+	/* first we need to clear all parser memory,
+	 * as it is uninitialized and may cause ECC errors
+	 */
+	/* event bits */
+	tmp_reg = (FPM_RAM_MURAM_ECC | FPM_RAM_IRAM_ECC);
+	/* Rams enable not effected by RCR bit,
+	 * but by a COP configuration
+	 */
+	if (cfg->external_ecc_rams_enable)
+		tmp_reg |= FPM_RAM_RAMS_ECC_EN_SRC_SEL;
+
+	/* enable test mode */
+	if (cfg->en_muram_test_mode)
+		tmp_reg |= FPM_RAM_MURAM_TEST_ECC;
+	if (cfg->en_iram_test_mode)
+		tmp_reg |= FPM_RAM_IRAM_TEST_ECC;
+	iowrite32be(tmp_reg, &fpm_rg->fm_rcr);
+
+	tmp_reg = 0;
+	if (cfg->exceptions & FMAN_EX_IRAM_ECC) {
+		tmp_reg |= FPM_IRAM_ECC_ERR_EX_EN;
+		fman_enable_rams_ecc(fpm_rg);
+	}
+	if (cfg->exceptions & FMAN_EX_NURAM_ECC) {
+		tmp_reg |= FPM_MURAM_ECC_ERR_EX_EN;
+		fman_enable_rams_ecc(fpm_rg);
+	}
+	iowrite32be(tmp_reg, &fpm_rg->fm_rie);
+
+	return 0;
+}
+
+int fman_bmi_init(struct fman_bmi_regs __iomem *bmi_rg, struct fman_cfg *cfg)
+{
+	uint32_t tmp_reg;
+
+	/* Init BMI Registers */
+
+	/* define common resources */
+	tmp_reg = cfg->fifo_base_addr;
+	tmp_reg = tmp_reg / BMI_FIFO_ALIGN;
+
+	tmp_reg |= ((cfg->total_fifo_size / FMAN_BMI_FIFO_UNITS - 1) <<
+		    BMI_CFG1_FIFO_SIZE_SHIFT);
+	iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg1);
+
+	tmp_reg = ((uint32_t)(cfg->total_num_of_tasks - 1) <<
+		   BMI_CFG2_TASKS_SHIFT);
+	/* num of DMA's will be dynamically updated when each port is set */
+	iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg2);
+
+	/* define unmaskable exceptions, enable and clear events */
+	tmp_reg = 0;
+	iowrite32be(BMI_ERR_INTR_EN_LIST_RAM_ECC |
+		    BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC |
+		    BMI_ERR_INTR_EN_STATISTICS_RAM_ECC |
+		    BMI_ERR_INTR_EN_DISPATCH_RAM_ECC, &bmi_rg->fmbm_ievr);
+
+	if (cfg->exceptions & FMAN_EX_BMI_LIST_RAM_ECC)
+		tmp_reg |= BMI_ERR_INTR_EN_LIST_RAM_ECC;
+	if (cfg->exceptions & FMAN_EX_BMI_PIPELINE_ECC)
+		tmp_reg |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+	if (cfg->exceptions & FMAN_EX_BMI_STATISTICS_RAM_ECC)
+		tmp_reg |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+	if (cfg->exceptions & FMAN_EX_BMI_DISPATCH_RAM_ECC)
+		tmp_reg |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+	iowrite32be(tmp_reg, &bmi_rg->fmbm_ier);
+
+	return 0;
+}
+
+int fman_qmi_init(struct fman_qmi_regs __iomem *qmi_rg, struct fman_cfg *cfg)
+{
+	uint32_t tmp_reg;
+	uint16_t period_in_fm_clocks;
+	uint8_t remainder;
+
+	/* Init QMI Registers */
+
+	/* Clear error interrupt events */
+
+	iowrite32be(QMI_ERR_INTR_EN_DOUBLE_ECC | QMI_ERR_INTR_EN_DEQ_FROM_DEF,
+		    &qmi_rg->fmqm_eie);
+	tmp_reg = 0;
+	if (cfg->exceptions & FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID)
+		tmp_reg |= QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+	if (cfg->exceptions & FMAN_EX_QMI_DOUBLE_ECC)
+		tmp_reg |= QMI_ERR_INTR_EN_DOUBLE_ECC;
+	/* enable events */
+	iowrite32be(tmp_reg, &qmi_rg->fmqm_eien);
+
+	if (cfg->tnum_aging_period) {
+		/* tnum_aging_period is in units of usec,
+		 * p_fmClockFreq in Mhz
+		 */
+		period_in_fm_clocks = (uint16_t)
+			(cfg->tnum_aging_period * cfg->clk_freq);
+		/* period_in_fm_clocks must be a 64 multiple */
+		remainder = period_in_fm_clocks % 64;
+		if (remainder) {
+			tmp_reg = (uint32_t)((period_in_fm_clocks / 64) + 1);
+		} else {
+			tmp_reg = (uint32_t)(period_in_fm_clocks / 64);
+			if (!tmp_reg)
+				tmp_reg = 1;
+		}
+		tmp_reg <<= QMI_TAPC_TAP;
+		iowrite32be(tmp_reg, &qmi_rg->fmqm_tapc);
+	}
+	tmp_reg = 0;
+	/* Clear interrupt events */
+	iowrite32be(QMI_INTR_EN_SINGLE_ECC, &qmi_rg->fmqm_ie);
+	if (cfg->exceptions & FMAN_EX_QMI_SINGLE_ECC)
+		tmp_reg |= QMI_INTR_EN_SINGLE_ECC;
+	/* enable events */
+	iowrite32be(tmp_reg, &qmi_rg->fmqm_ien);
+
+	return 0;
+}
+
+int fman_enable(struct fman_rg *fman_rg, struct fman_cfg *cfg)
+{
+	uint32_t cfg_reg = 0;
+
+	/* Enable all modules */
+
+	/* clear&enable global counters	 - calculate reg and save for later,
+	 * because it's the same reg for QMI enable
+	 */
+	cfg_reg = QMI_CFG_EN_COUNTERS;
+	if (cfg->qmi_deq_option_support)
+		cfg_reg |= (uint32_t)(((cfg->qmi_def_tnums_thresh) << 8) |
+				       cfg->qmi_def_tnums_thresh);
+
+	iowrite32be(BMI_INIT_START, &fman_rg->bmi_rg->fmbm_init);
+	iowrite32be(cfg_reg | QMI_CFG_ENQ_EN | QMI_CFG_DEQ_EN,
+		    &fman_rg->qmi_rg->fmqm_gc);
+
+	return 0;
+}
+
+void fman_free_resources(struct fman_rg *fman_rg)
+{
+	/* disable BMI and QMI */
+	iowrite32be(0, &fman_rg->bmi_rg->fmbm_init);
+	iowrite32be(0, &fman_rg->qmi_rg->fmqm_gc);
+
+	/* release BMI resources */
+	iowrite32be(0, &fman_rg->bmi_rg->fmbm_cfg2);
+	iowrite32be(0, &fman_rg->bmi_rg->fmbm_cfg1);
+
+	/* disable ECC */
+	iowrite32be(0, &fman_rg->fpm_rg->fm_rcr);
+}
+
+/* API Run-time Control uint functions	  */
+
+uint32_t fman_get_normal_pending(struct fman_fpm_regs __iomem *fpm_rg)
+{
+	return ioread32be(&fpm_rg->fm_npi);
+}
+
+uint32_t fman_get_error_pending(struct fman_fpm_regs __iomem *fpm_rg)
+{
+	return ioread32be(&fpm_rg->fm_epi);
+}
+
+void fman_enable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&fpm_rg->fm_rcr);
+	if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL)
+		iowrite32be(tmp | FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr);
+	else
+		iowrite32be(tmp | FPM_RAM_RAMS_ECC_EN |
+			    FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr);
+}
+
+void fman_disable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&fpm_rg->fm_rcr);
+	if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL)
+		iowrite32be(tmp & ~FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr);
+	else
+		iowrite32be(tmp & ~(FPM_RAM_RAMS_ECC_EN | FPM_RAM_IRAM_ECC_EN),
+			    &fpm_rg->fm_rcr);
+}
+
+int fman_set_exception(struct fman_rg *fman_rg,
+		       enum fman_exceptions exception, bool enable)
+{
+	uint32_t tmp;
+
+	switch (exception) {
+	case E_FMAN_EX_DMA_BUS_ERROR:
+		tmp = ioread32be(&fman_rg->dma_rg->fmdmmr);
+		if (enable)
+			tmp |= DMA_MODE_BER;
+		else
+			tmp &= ~DMA_MODE_BER;
+		/* disable bus error */
+		iowrite32be(tmp, &fman_rg->dma_rg->fmdmmr);
+		break;
+	case E_FMAN_EX_DMA_READ_ECC:
+	case E_FMAN_EX_DMA_SYSTEM_WRITE_ECC:
+	case E_FMAN_EX_DMA_FM_WRITE_ECC:
+		tmp = ioread32be(&fman_rg->dma_rg->fmdmmr);
+		if (enable)
+			tmp |= DMA_MODE_ECC;
+		else
+			tmp &= ~DMA_MODE_ECC;
+		iowrite32be(tmp, &fman_rg->dma_rg->fmdmmr);
+		break;
+	case E_FMAN_EX_FPM_STALL_ON_TASKS:
+		tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee);
+		if (enable)
+			tmp |= FPM_EV_MASK_STALL_EN;
+		else
+			tmp &= ~FPM_EV_MASK_STALL_EN;
+		iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee);
+		break;
+	case E_FMAN_EX_FPM_SINGLE_ECC:
+		tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee);
+		if (enable)
+			tmp |= FPM_EV_MASK_SINGLE_ECC_EN;
+		else
+			tmp &= ~FPM_EV_MASK_SINGLE_ECC_EN;
+		iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee);
+		break;
+	case E_FMAN_EX_FPM_DOUBLE_ECC:
+		tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee);
+		if (enable)
+			tmp |= FPM_EV_MASK_DOUBLE_ECC_EN;
+		else
+			tmp &= ~FPM_EV_MASK_DOUBLE_ECC_EN;
+		iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee);
+		break;
+	case E_FMAN_EX_QMI_SINGLE_ECC:
+		tmp = ioread32be(&fman_rg->qmi_rg->fmqm_ien);
+		if (enable)
+			tmp |= QMI_INTR_EN_SINGLE_ECC;
+		else
+			tmp &= ~QMI_INTR_EN_SINGLE_ECC;
+		iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_ien);
+		break;
+	case E_FMAN_EX_QMI_DOUBLE_ECC:
+		tmp = ioread32be(&fman_rg->qmi_rg->fmqm_eien);
+		if (enable)
+			tmp |= QMI_ERR_INTR_EN_DOUBLE_ECC;
+		else
+			tmp &= ~QMI_ERR_INTR_EN_DOUBLE_ECC;
+		iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_eien);
+		break;
+	case E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID:
+		tmp = ioread32be(&fman_rg->qmi_rg->fmqm_eien);
+		if (enable)
+			tmp |= QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+		else
+			tmp &= ~QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+		iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_eien);
+		break;
+	case E_FMAN_EX_BMI_LIST_RAM_ECC:
+		tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+		if (enable)
+			tmp |= BMI_ERR_INTR_EN_LIST_RAM_ECC;
+		else
+			tmp &= ~BMI_ERR_INTR_EN_LIST_RAM_ECC;
+		iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+		break;
+	case E_FMAN_EX_BMI_STORAGE_PROFILE_ECC:
+		tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+		if (enable)
+			tmp |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+		else
+			tmp &= ~BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+		iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+		break;
+	case E_FMAN_EX_BMI_STATISTICS_RAM_ECC:
+		tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+		if (enable)
+			tmp |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+		else
+			tmp &= ~BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+		iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+		break;
+	case E_FMAN_EX_BMI_DISPATCH_RAM_ECC:
+		tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+		if (enable)
+			tmp |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+		else
+			tmp &= ~BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+		iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+		break;
+	case E_FMAN_EX_IRAM_ECC:
+		tmp = ioread32be(&fman_rg->fpm_rg->fm_rie);
+		if (enable) {
+			/* enable ECC if not enabled */
+			fman_enable_rams_ecc(fman_rg->fpm_rg);
+			/* enable ECC interrupts */
+			tmp |= FPM_IRAM_ECC_ERR_EX_EN;
+		} else {
+			/* ECC mechanism may be disabled,
+			 * depending on driver status
+			 */
+			fman_disable_rams_ecc(fman_rg->fpm_rg);
+			tmp &= ~FPM_IRAM_ECC_ERR_EX_EN;
+		}
+		iowrite32be(tmp, &fman_rg->fpm_rg->fm_rie);
+		break;
+	case E_FMAN_EX_MURAM_ECC:
+		tmp = ioread32be(&fman_rg->fpm_rg->fm_rie);
+		if (enable) {
+			/* enable ECC if not enabled */
+			fman_enable_rams_ecc(fman_rg->fpm_rg);
+			/* enable ECC interrupts */
+			tmp |= FPM_MURAM_ECC_ERR_EX_EN;
+		} else {
+			/* ECC mechanism may be disabled,
+			 * depending on driver status
+			 */
+			fman_disable_rams_ecc(fman_rg->fpm_rg);
+			tmp &= ~FPM_MURAM_ECC_ERR_EX_EN;
+		}
+		iowrite32be(tmp, &fman_rg->fpm_rg->fm_rie);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+void fman_get_revision(struct fman_fpm_regs __iomem *fpm_rg,
+		       uint8_t *major, uint8_t *minor)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&fpm_rg->fm_ip_rev_1);
+	*major =
+	    (uint8_t)((tmp & FPM_REV1_MAJOR_MASK) >> FPM_REV1_MAJOR_SHIFT);
+	*minor =
+	    (uint8_t)((tmp & FPM_REV1_MINOR_MASK) >> FPM_REV1_MINOR_SHIFT);
+}
+
+bool fman_is_qmi_halt_not_busy_state(struct fman_qmi_regs __iomem *qmi_rg)
+{
+	return !!(ioread32be(&qmi_rg->fmqm_gs) & QMI_GS_HALT_NOT_BUSY);
+}
+
+void fman_resume(struct fman_fpm_regs __iomem *fpm_rg)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&fpm_rg->fmfp_ee);
+	/* clear tmp_reg event bits in order not to clear standing events */
+	tmp &= ~(FPM_EV_MASK_DOUBLE_ECC |
+		 FPM_EV_MASK_STALL | FPM_EV_MASK_SINGLE_ECC);
+	tmp |= FPM_EV_MASK_RELEASE_FM;
+
+	iowrite32be(tmp, &fpm_rg->fmfp_ee);
+}
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 03/12] fsl/fman: Add the FMan port FLIB headers
  2015-05-07 13:05 ` [RFC,v3 02/12] fsl/fman: Add the FMan FLIB Madalin Bucur
@ 2015-05-07 13:05   ` Madalin Bucur
  2015-05-07 13:05     ` [RFC,v3 04/12] fsl/fman: Add the FMan port FLIB Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

The FMan Port Flib provides basic API used by the drivers to
configure and control the FMan Port hardware.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 .../net/ethernet/freescale/fman/flib/fman_common.h |  73 ++++
 .../ethernet/freescale/fman/flib/fsl_fman_port.h   | 462 +++++++++++++++++++++
 .../net/ethernet/freescale/fman/flib/fsl_fman_sp.h |  66 +++
 3 files changed, 601 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/fman_common.h
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_sp.h

diff --git a/drivers/net/ethernet/freescale/fman/flib/fman_common.h b/drivers/net/ethernet/freescale/fman/flib/fman_common.h
new file mode 100644
index 0000000..e186ed9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fman_common.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FMAN_COMMON_H
+#define __FMAN_COMMON_H
+
+/* NIA Description */
+#define NIA_ORDER_RESTOR			0x00800000
+#define NIA_ENG_FM_CTL				0x00000000
+#define NIA_ENG_PRS				0x00440000
+#define NIA_ENG_KG				0x00480000
+#define NIA_ENG_PLCR				0x004C0000
+#define NIA_ENG_BMI				0x00500000
+#define NIA_ENG_QMI_ENQ				0x00540000
+#define NIA_ENG_QMI_DEQ				0x00580000
+#define NIA_ENG_MASK				0x007C0000
+
+#define NIA_FM_CTL_AC_CC			0x00000006
+#define NIA_FM_CTL_AC_HC			0x0000000C
+#define NIA_FM_CTL_AC_IND_MODE_TX		0x00000008
+#define NIA_FM_CTL_AC_IND_MODE_RX		0x0000000A
+#define NIA_FM_CTL_AC_FRAG			0x0000000e
+#define NIA_FM_CTL_AC_PRE_FETCH			0x00000010
+#define NIA_FM_CTL_AC_POST_FETCH_PCD		0x00000012
+#define NIA_FM_CTL_AC_POST_FETCH_PCD_UDP_LEN	0x00000018
+#define NIA_FM_CTL_AC_POST_FETCH_NO_PCD		0x00000012
+#define NIA_FM_CTL_AC_FRAG_CHECK		0x00000014
+#define NIA_FM_CTL_AC_PRE_CC			0x00000020
+
+#define NIA_BMI_AC_ENQ_FRAME			0x00000002
+#define NIA_BMI_AC_TX_RELEASE			0x000002C0
+#define NIA_BMI_AC_RELEASE			0x000000C0
+#define NIA_BMI_AC_DISCARD			0x000000C1
+#define NIA_BMI_AC_TX				0x00000274
+#define NIA_BMI_AC_FETCH			0x00000208
+#define NIA_BMI_AC_MASK				0x000003FF
+
+#define NIA_KG_DIRECT				0x00000100
+#define NIA_KG_CC_EN				0x00000200
+#define NIA_PLCR_ABSOLUTE			0x00008000
+
+#define NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA	0x00000202
+#define NIA_BMI_AC_FETCH_ALL_FRAME		0x0000020c
+
+#endif	/* __FMAN_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h
new file mode 100644
index 0000000..8903c99
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_PORT_H
+#define __FSL_FMAN_PORT_H
+
+#include "fsl_fman_sp.h"
+
+/* Registers bit fields */
+
+/* BMI defines */
+#define BMI_EBD_EN				0x80000000
+
+#define BMI_PORT_CFG_EN				0x80000000
+#define BMI_PORT_CFG_FDOVR			0x02000000
+#define BMI_PORT_CFG_IM				0x01000000
+
+#define BMI_PORT_STATUS_BSY			0x80000000
+
+#define BMI_DMA_ATTR_SWP_SHIFT			FMAN_SP_DMA_ATTR_SWP_SHIFT
+#define BMI_DMA_ATTR_IC_STASH_ON		0x10000000
+#define BMI_DMA_ATTR_HDR_STASH_ON		0x04000000
+#define BMI_DMA_ATTR_SG_STASH_ON		0x01000000
+#define BMI_DMA_ATTR_WRITE_OPTIMIZE		FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE
+
+#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT	16
+#define BMI_RX_FIFO_THRESHOLD_ETHE		0x80000000
+
+#define BMI_TX_FRAME_END_CS_IGNORE_SHIFT	24
+#define BMI_RX_FRAME_END_CS_IGNORE_SHIFT	24
+#define BMI_RX_FRAME_END_CUT_SHIFT		16
+
+#define BMI_IC_TO_EXT_SHIFT			FMAN_SP_IC_TO_EXT_SHIFT
+#define BMI_IC_FROM_INT_SHIFT			FMAN_SP_IC_FROM_INT_SHIFT
+
+#define BMI_INT_BUF_MARG_SHIFT			28
+#define BMI_EXT_BUF_MARG_START_SHIFT		FMAN_SP_EXT_BUF_MARG_START_SHIFT
+
+#define BMI_CMD_MR_LEAC				0x00200000
+#define BMI_CMD_MR_SLEAC			0x00100000
+#define BMI_CMD_MR_MA				0x00080000
+#define BMI_CMD_MR_DEAS				0x00040000
+#define BMI_CMD_RX_MR_DEF			(BMI_CMD_MR_LEAC | \
+						BMI_CMD_MR_SLEAC | \
+						BMI_CMD_MR_MA | \
+						BMI_CMD_MR_DEAS)
+#define BMI_CMD_TX_MR_DEF			0
+#define BMI_CMD_OP_MR_DEF			(BMI_CMD_MR_DEAS | \
+						BMI_CMD_MR_MA)
+
+#define BMI_CMD_ATTR_ORDER			0x80000000
+#define BMI_CMD_ATTR_SYNC			0x02000000
+#define BMI_CMD_ATTR_COLOR_SHIFT		26
+
+#define BMI_FIFO_PIPELINE_DEPTH_SHIFT		12
+#define BMI_NEXT_ENG_FD_BITS_SHIFT		24
+#define BMI_FRAME_END_CS_IGNORE_SHIFT		24
+
+#define BMI_COUNTERS_EN				0x80000000
+
+#define BMI_EXT_BUF_POOL_VALID			FMAN_SP_EXT_BUF_POOL_VALID
+#define BMI_EXT_BUF_POOL_EN_COUNTER		FMAN_SP_EXT_BUF_POOL_EN_COUNTER
+#define BMI_EXT_BUF_POOL_BACKUP		FMAN_SP_EXT_BUF_POOL_BACKUP
+#define BMI_EXT_BUF_POOL_ID_SHIFT		16
+#define BMI_EXT_BUF_POOL_ID_MASK		0x003F0000
+#define BMI_POOL_DEP_NUM_OF_POOLS_SHIFT		16
+
+#define BMI_TX_FIFO_MIN_FILL_SHIFT		16
+#define BMI_TX_FIFO_PIPELINE_DEPTH_SHIFT	12
+
+#define MAX_PERFORMANCE_TASK_COMP		64
+#define MAX_PERFORMANCE_RX_QUEUE_COMP		64
+#define MAX_PERFORMANCE_TX_QUEUE_COMP		8
+#define MAX_PERFORMANCE_DMA_COMP		16
+#define MAX_PERFORMANCE_FIFO_COMP		1024
+
+#define BMI_PERFORMANCE_TASK_COMP_SHIFT		24
+#define BMI_PERFORMANCE_QUEUE_COMP_SHIFT	16
+#define BMI_PERFORMANCE_DMA_COMP_SHIFT		12
+
+#define BMI_SG_DISABLE				FMAN_SP_SG_DISABLE
+
+/* QMI defines */
+#define QMI_PORT_CFG_EN				0x80000000
+#define QMI_PORT_CFG_EN_COUNTERS		0x10000000
+
+#define QMI_PORT_STATUS_DEQ_TNUM_BSY		0x80000000
+#define QMI_PORT_STATUS_DEQ_FD_BSY		0x20000000
+
+#define QMI_DEQ_CFG_PRI				0x80000000
+#define QMI_DEQ_CFG_TYPE1			0x10000000
+#define QMI_DEQ_CFG_TYPE2			0x20000000
+#define QMI_DEQ_CFG_TYPE3			0x30000000
+#define QMI_DEQ_CFG_PREFETCH_PARTIAL		0x01000000
+#define QMI_DEQ_CFG_PREFETCH_FULL		0x03000000
+#define QMI_DEQ_CFG_SP_MASK			0xf
+#define QMI_DEQ_CFG_SP_SHIFT			20
+
+/* General port defines */
+#define FMAN_PORT_EXT_POOLS_NUM(fm_rev_maj) \
+		(((fm_rev_maj) == 4) ? 4 : 8)
+#define FMAN_PORT_MAX_EXT_POOLS_NUM	8
+#define FMAN_PORT_OBS_EXT_POOLS_NUM	2
+#define FMAN_PORT_CG_MAP_NUM		8
+#define FMAN_PORT_PRS_RESULT_WORDS_NUM	8
+#define FMAN_PORT_BMI_FIFO_UNITS	0x100
+#define FMAN_PORT_IC_OFFSET_UNITS	0x10
+
+/* FM Port Register Map */
+
+/* BMI Rx port register map */
+struct fman_port_rx_bmi_regs {
+	uint32_t fmbm_rcfg;		/* Rx Configuration */
+	uint32_t fmbm_rst;		/* Rx Status */
+	uint32_t fmbm_rda;		/* Rx DMA attributes*/
+	uint32_t fmbm_rfp;		/* Rx FIFO Parameters*/
+	uint32_t fmbm_rfed;		/* Rx Frame End Data*/
+	uint32_t fmbm_ricp;		/* Rx Internal Context Parameters*/
+	uint32_t fmbm_rim;		/* Rx Internal Buffer Margins*/
+	uint32_t fmbm_rebm;		/* Rx External Buffer Margins*/
+	uint32_t fmbm_rfne;		/* Rx Frame Next Engine*/
+	uint32_t fmbm_rfca;		/* Rx Frame Command Attributes.*/
+	uint32_t fmbm_rfpne;		/* Rx Frame Parser Next Engine*/
+	uint32_t fmbm_rpso;		/* Rx Parse Start Offset*/
+	uint32_t fmbm_rpp;		/* Rx Policer Profile  */
+	uint32_t fmbm_rccb;		/* Rx Coarse Classification Base */
+	uint32_t fmbm_reth;		/* Rx Excessive Threshold */
+	uint32_t reserved003c[1];	/* (0x03C 0x03F) */
+	uint32_t fmbm_rprai[FMAN_PORT_PRS_RESULT_WORDS_NUM];
+					/* Rx Parse Results Array Init*/
+	uint32_t fmbm_rfqid;		/* Rx Frame Queue ID*/
+	uint32_t fmbm_refqid;		/* Rx Error Frame Queue ID*/
+	uint32_t fmbm_rfsdm;		/* Rx Frame Status Discard Mask*/
+	uint32_t fmbm_rfsem;		/* Rx Frame Status Error Mask*/
+	uint32_t fmbm_rfene;		/* Rx Frame Enqueue Next Engine */
+	uint32_t reserved0074[0x2];	/* (0x074-0x07C)  */
+	uint32_t fmbm_rcmne; /* Rx Frame Continuous Mode Next Engine */
+	uint32_t reserved0080[0x20];/* (0x080 0x0FF)  */
+	uint32_t fmbm_ebmpi[FMAN_PORT_MAX_EXT_POOLS_NUM];
+					/* Buffer Manager pool Information-*/
+	uint32_t fmbm_acnt[FMAN_PORT_MAX_EXT_POOLS_NUM];
+					/* Allocate Counter-*/
+	uint32_t reserved0130[8];
+					/* 0x130/0x140 - 0x15F reserved -*/
+	uint32_t fmbm_rcgm[FMAN_PORT_CG_MAP_NUM];
+					/* Congestion Group Map*/
+	uint32_t fmbm_mpd;		/* BM Pool Depletion  */
+	uint32_t reserved0184[0x1F];	/* (0x184 0x1FF) */
+	uint32_t fmbm_rstc;		/* Rx Statistics Counters*/
+	uint32_t fmbm_rfrc;		/* Rx Frame Counter*/
+	uint32_t fmbm_rfbc;		/* Rx Bad Frames Counter*/
+	uint32_t fmbm_rlfc;		/* Rx Large Frames Counter*/
+	uint32_t fmbm_rffc;		/* Rx Filter Frames Counter*/
+	uint32_t fmbm_rfdc;		/* Rx Frame Discard Counter*/
+	uint32_t fmbm_rfldec;		/* Rx Frames List DMA Error Counter*/
+	uint32_t fmbm_rodc;		/* Rx Out of Buffers Discard nntr*/
+	uint32_t fmbm_rbdc;		/* Rx Buffers Deallocate Counter*/
+	uint32_t reserved0224[0x17];	/* (0x224 0x27F) */
+	uint32_t fmbm_rpc;		/* Rx Performance Counters*/
+	uint32_t fmbm_rpcp;		/* Rx Performance Count Parameters*/
+	uint32_t fmbm_rccn;		/* Rx Cycle Counter*/
+	uint32_t fmbm_rtuc;		/* Rx Tasks Utilization Counter*/
+	uint32_t fmbm_rrquc;		/* Rx Receive Queue Utilization cntr*/
+	uint32_t fmbm_rduc;		/* Rx DMA Utilization Counter*/
+	uint32_t fmbm_rfuc;		/* Rx FIFO Utilization Counter*/
+	uint32_t fmbm_rpac;		/* Rx Pause Activation Counter*/
+	uint32_t reserved02a0[0x18];	/* (0x2A0 0x2FF) */
+	uint32_t fmbm_rdbg;		/* Rx Debug-*/
+};
+
+/* BMI Tx port register map */
+struct fman_port_tx_bmi_regs {
+	uint32_t fmbm_tcfg;		/* Tx Configuration */
+	uint32_t fmbm_tst;		/* Tx Status */
+	uint32_t fmbm_tda;		/* Tx DMA attributes */
+	uint32_t fmbm_tfp;		/* Tx FIFO Parameters */
+	uint32_t fmbm_tfed;		/* Tx Frame End Data */
+	uint32_t fmbm_ticp;		/* Tx Internal Context Parameters */
+	uint32_t fmbm_tfdne;		/* Tx Frame Dequeue Next Engine. */
+	uint32_t fmbm_tfca;		/* Tx Frame Command attribute. */
+	uint32_t fmbm_tcfqid;		/* Tx Confirmation Frame Queue ID. */
+	uint32_t fmbm_tefqid;		/* Tx Frame Error Queue ID */
+	uint32_t fmbm_tfene;		/* Tx Frame Enqueue Next Engine */
+	uint32_t fmbm_trlmts;		/* Tx Rate Limiter Scale */
+	uint32_t fmbm_trlmt;		/* Tx Rate Limiter */
+	uint32_t reserved0034[0x0e];	/* (0x034-0x6c) */
+	uint32_t fmbm_tccb;		/* Tx Coarse Classification base */
+	uint32_t fmbm_tfne;		/* Tx Frame Next Engine */
+	/* Tx Priority based Flow Control (PFC) Mapping */
+	uint32_t fmbm_tpfcm[0x02];
+	/* Tx Frame Continuous Mode Next Engine */
+	uint32_t fmbm_tcmne;
+	uint32_t reserved0080[0x60];	/* (0x080-0x200) */
+	uint32_t fmbm_tstc;		/* Tx Statistics Counters */
+	uint32_t fmbm_tfrc;		/* Tx Frame Counter */
+	uint32_t fmbm_tfdc;		/* Tx Frames Discard Counter */
+	uint32_t fmbm_tfledc;		/* Tx Frame len error discard cntr */
+	uint32_t fmbm_tfufdc;		/* Tx Frame unsprt frmt discard cntr*/
+	uint32_t fmbm_tbdc;		/* Tx Buffers Deallocate Counter */
+	uint32_t reserved0218[0x1A];	/* (0x218-0x280) */
+	uint32_t fmbm_tpc;		/* Tx Performance Counters*/
+	uint32_t fmbm_tpcp;		/* Tx Performance Count Parameters*/
+	uint32_t fmbm_tccn;		/* Tx Cycle Counter*/
+	uint32_t fmbm_ttuc;		/* Tx Tasks Utilization Counter*/
+	uint32_t fmbm_ttcquc;		/* Tx Transmit conf Q util Counter*/
+	uint32_t fmbm_tduc;		/* Tx DMA Utilization Counter*/
+	uint32_t fmbm_tfuc;		/* Tx FIFO Utilization Counter*/
+};
+
+/* BMI O/H port register map */
+struct fman_port_oh_bmi_regs {
+	uint32_t fmbm_ocfg;		/* O/H Configuration  */
+	uint32_t fmbm_ost;		/* O/H Status */
+	uint32_t fmbm_oda;		/* O/H DMA attributes  */
+	uint32_t fmbm_oicp;		/* O/H Internal Context Parameters */
+	uint32_t fmbm_ofdne;		/* O/H Frame Dequeue Next Engine  */
+	uint32_t fmbm_ofne;		/* O/H Frame Next Engine  */
+	uint32_t fmbm_ofca;		/* O/H Frame Command Attributes.  */
+	uint32_t fmbm_ofpne;		/* O/H Frame Parser Next Engine	 */
+	uint32_t fmbm_opso;		/* O/H Parse Start Offset  */
+	uint32_t fmbm_opp;		/* O/H Policer Profile */
+	uint32_t fmbm_occb;		/* O/H Coarse Classification base */
+	uint32_t fmbm_oim;		/* O/H Internal margins*/
+	uint32_t fmbm_ofp;		/* O/H Fifo Parameters*/
+	uint32_t fmbm_ofed;		/* O/H Frame End Data*/
+	uint32_t reserved0030[2];	/* (0x038 - 0x03F) */
+	uint32_t fmbm_oprai[FMAN_PORT_PRS_RESULT_WORDS_NUM];
+				/* O/H Parse Results Array Initialization  */
+	uint32_t fmbm_ofqid;		/* O/H Frame Queue ID  */
+	uint32_t fmbm_oefqid;		/* O/H Error Frame Queue ID  */
+	uint32_t fmbm_ofsdm;		/* O/H Frame Status Discard Mask  */
+	uint32_t fmbm_ofsem;		/* O/H Frame Status Error Mask	*/
+	uint32_t fmbm_ofene;		/* O/H Frame Enqueue Next Engine  */
+	uint32_t fmbm_orlmts;		/* O/H Rate Limiter Scale  */
+	uint32_t fmbm_orlmt;		/* O/H Rate Limiter  */
+	uint32_t fmbm_ocmne;		/* O/H Continuous Mode Next Engine  */
+	uint32_t reserved0080[0x20];	/* 0x080 - 0x0FF Reserved */
+	uint32_t fmbm_oebmpi[2];	/* Buf Mngr Observed Pool Info */
+	uint32_t reserved0108[0x16];	/* 0x108 - 0x15F Reserved */
+	uint32_t fmbm_ocgm;		/* Observed Congestion Group Map */
+	uint32_t reserved0164[0x7];	/* 0x164 - 0x17F Reserved */
+	uint32_t fmbm_ompd;		/* Observed BMan Pool Depletion */
+	uint32_t reserved0184[0x1F];	/* 0x184 - 0x1FF Reserved */
+	uint32_t fmbm_ostc;		/* O/H Statistics Counters  */
+	uint32_t fmbm_ofrc;		/* O/H Frame Counter  */
+	uint32_t fmbm_ofdc;		/* O/H Frames Discard Counter  */
+	uint32_t fmbm_ofledc;		/* O/H Frames Len Err Discard Cntr */
+	uint32_t fmbm_ofufdc;		/* O/H Frames Unsprtd Discard Cutr  */
+	uint32_t fmbm_offc;		/* O/H Filter Frames Counter  */
+	uint32_t fmbm_ofwdc;		/* Rx Frames WRED Discard Counter  */
+	uint32_t fmbm_ofldec;		/* O/H Frames List DMA Error Cntr */
+	uint32_t fmbm_obdc;		/* O/H Buffers Deallocate Counter */
+	uint32_t reserved0218[0x17];	/* (0x218 - 0x27F) */
+	uint32_t fmbm_opc;		/* O/H Performance Counters  */
+	uint32_t fmbm_opcp;		/* O/H Performance Count Parameters */
+	uint32_t fmbm_occn;		/* O/H Cycle Counter  */
+	uint32_t fmbm_otuc;		/* O/H Tasks Utilization Counter  */
+	uint32_t fmbm_oduc;		/* O/H DMA Utilization Counter */
+	uint32_t fmbm_ofuc;		/* O/H FIFO Utilization Counter */
+};
+
+/* BMI port register map */
+union fman_port_bmi_regs {
+	struct fman_port_rx_bmi_regs rx;
+	struct fman_port_tx_bmi_regs tx;
+	struct fman_port_oh_bmi_regs oh;
+};
+
+/* QMI port register map */
+struct fman_port_qmi_regs {
+	uint32_t fmqm_pnc;		/* PortID n Configuration Register */
+	uint32_t fmqm_pns;		/* PortID n Status Register */
+	uint32_t fmqm_pnts;		/* PortID n Task Status Register */
+	uint32_t reserved00c[4];	/* 0xn00C - 0xn01B */
+	uint32_t fmqm_pnen;		/* PortID n Enqueue NIA Register */
+	uint32_t fmqm_pnetfc;		/* PortID n Enq Total Frame Counter */
+	uint32_t reserved024[2];	/* 0xn024 - 0x02B */
+	uint32_t fmqm_pndn;		/* PortID n Dequeue NIA Register */
+	uint32_t fmqm_pndc;		/* PortID n Dequeue Config Register */
+	uint32_t fmqm_pndtfc;		/* PortID n Dequeue tot Frame cntr */
+	uint32_t fmqm_pndfdc;		/* PortID n Dequeue FQID Dflt Cntr */
+	uint32_t fmqm_pndcc;		/* PortID n Dequeue Confirm Counter */
+};
+
+enum fman_port_dma_swap {
+	E_FMAN_PORT_DMA_NO_SWAP,	/* No swap, transfer data as is */
+	E_FMAN_PORT_DMA_SWAP_LE,
+	/* The transferred data should be swapped in PPC Little Endian mode */
+	E_FMAN_PORT_DMA_SWAP_BE
+	/* The transferred data should be swapped in Big Endian mode */
+};
+
+/* Default port color */
+enum fman_port_color {
+	E_FMAN_PORT_COLOR_GREEN,	/* Default port color is green */
+	E_FMAN_PORT_COLOR_YELLOW,	/* Default port color is yellow */
+	E_FMAN_PORT_COLOR_RED,		/* Default port color is red */
+	E_FMAN_PORT_COLOR_OVERRIDE	/* Ignore color */
+};
+
+/* QMI dequeue from the SP channel - types */
+enum fman_port_deq_type {
+	E_FMAN_PORT_DEQ_BY_PRI,
+	/* Priority precedence and Intra-Class scheduling */
+	E_FMAN_PORT_DEQ_ACTIVE_FQ,
+	/* Active FQ precedence and Intra-Class scheduling */
+	E_FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS
+	/* Active FQ precedence and override Intra-Class scheduling */
+};
+
+/* QMI dequeue prefetch modes */
+enum fman_port_deq_prefetch {
+	E_FMAN_PORT_DEQ_NO_PREFETCH, /* No prefetch mode */
+	E_FMAN_PORT_DEQ_PART_PREFETCH, /* Partial prefetch mode */
+	E_FMAN_PORT_DEQ_FULL_PREFETCH /* Full prefetch mode */
+};
+
+/* Parameters for defining performance counters behavior */
+struct fman_port_perf_cnt_params {
+	uint8_t task_val;	/* Task compare value */
+	uint8_t queue_val;
+	/* Rx or Tx conf queue compare value (unused for O/H ports) */
+	uint8_t dma_val;	/* Dma compare value */
+	uint32_t fifo_val;	/* Fifo compare value (in bytes) */
+};
+
+/* FM Port configuration structure, used at init */
+struct fman_port_cfg {
+	struct fman_port_perf_cnt_params perf_cnt_params;
+	/* BMI parameters */
+	enum fman_port_dma_swap dma_swap_data;
+	bool dma_ic_stash_on;
+	bool dma_header_stash_on;
+	bool dma_sg_stash_on;
+	bool dma_write_optimize;
+	uint16_t ic_ext_offset;
+	uint8_t ic_int_offset;
+	uint16_t ic_size;
+	enum fman_port_color color;
+	bool sync_req;
+	bool discard_override;
+	uint8_t checksum_bytes_ignore;
+	uint8_t rx_cut_end_bytes;
+	uint32_t rx_pri_elevation;
+	uint32_t rx_fifo_thr;
+	uint8_t rx_fd_bits;
+	uint8_t int_buf_start_margin;
+	uint16_t ext_buf_start_margin;
+	uint16_t ext_buf_end_margin;
+	uint32_t tx_fifo_min_level;
+	uint32_t tx_fifo_low_comf_level;
+	uint8_t tx_fifo_deq_pipeline_depth;
+	bool stats_counters_enable;
+	bool perf_counters_enable;
+	/* QMI parameters */
+	bool deq_high_pri;
+	enum fman_port_deq_type deq_type;
+	enum fman_port_deq_prefetch deq_prefetch_opt;
+	uint16_t deq_byte_cnt;
+	bool queue_counters_enable;
+	bool no_scatter_gather;
+	int errata_A006675;
+	int errata_A006320;
+	int excessive_threshold_register;
+	int fmbm_rebm_has_sgd;
+	int fmbm_tfne_has_features;
+	int qmi_deq_options_support;
+};
+
+enum fman_port_type {
+	E_FMAN_PORT_TYPE_OP = 0,
+	/* Offline parsing port, shares id-s with
+	 * host command, so must have exclusive id-s
+	 */
+	E_FMAN_PORT_TYPE_RX,	    /* 1G Rx port */
+	E_FMAN_PORT_TYPE_RX_10G,    /* 10G Rx port */
+	E_FMAN_PORT_TYPE_TX,	    /* 1G Tx port */
+	E_FMAN_PORT_TYPE_TX_10G,     /* 10G Tx port */
+	E_FMAN_PORT_TYPE_DUMMY
+};
+
+struct fman_port_params {
+	uint32_t discard_mask;
+	uint32_t err_mask;
+	uint32_t dflt_fqid;
+	uint32_t err_fqid;
+	uint8_t deq_sp;
+	bool dont_release_buf;
+};
+
+/* Port context - used by most API functions */
+struct fman_port {
+	enum fman_port_type type;
+	uint8_t fm_rev_maj;
+	uint8_t fm_rev_min;
+	union fman_port_bmi_regs __iomem *bmi_regs;
+	struct fman_port_qmi_regs __iomem *qmi_regs;
+	uint8_t ext_pools_num;
+};
+
+/* External buffer pools configuration */
+struct fman_port_bpools {
+	uint8_t count;			/* Num of pools to set up */
+	bool counters_enable;		/* Enable allocate counters */
+	uint8_t grp_bp_depleted_num;
+	/* Number of depleted pools - if reached the BMI indicates
+	 * the MAC to send a pause frame
+	 */
+	struct {
+		uint8_t bpid;		/* BM pool ID */
+		uint16_t size;
+		/* Pool's size - must be in ascending order */
+		bool is_backup;
+		/* If this is a backup pool */
+		bool grp_bp_depleted;
+		/* Consider this buffer in multiple pools depletion criteria*/
+		bool single_bp_depleted;
+		/* Consider this buffer in single pool depletion criteria */
+	} bpool[FMAN_PORT_MAX_EXT_POOLS_NUM];
+};
+
+
+/*   FM Port API */
+void fman_port_defconfig(struct fman_port_cfg *cfg, enum fman_port_type type);
+int fman_port_init(struct fman_port *port,
+		   struct fman_port_cfg *cfg, struct fman_port_params *params);
+int fman_port_enable(struct fman_port *port);
+int fman_port_disable(const struct fman_port *port);
+int fman_port_set_bpools(const struct fman_port *port,
+			 const struct fman_port_bpools *bp);
+int fman_port_set_perf_cnt_params(struct fman_port *port,
+				  struct fman_port_perf_cnt_params *params);
+
+#endif	/* __FSL_FMAN_PORT_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_sp.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_sp.h
new file mode 100644
index 0000000..0f7bce1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_sp.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_SP_H
+#define __FSL_FMAN_SP_H
+
+#include "common/general.h"
+#include "fsl_fman.h"
+
+/* Registers bit fields */
+#define FMAN_SP_EXT_BUF_POOL_EN_COUNTER	    0x40000000
+#define FMAN_SP_EXT_BUF_POOL_VALID		    0x80000000
+#define FMAN_SP_EXT_BUF_POOL_BACKUP		    0x20000000
+#define FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE	    0x00100000
+#define FMAN_SP_SG_DISABLE			    0x80000000
+
+/* shifts */
+#define FMAN_SP_EXT_BUF_POOL_ID_SHIFT		    16
+#define FMAN_SP_POOL_DEP_NUM_OF_POOLS_SHIFT	    16
+#define FMAN_SP_EXT_BUF_MARG_START_SHIFT	    16
+#define FMAN_SP_EXT_BUF_MARG_END_SHIFT		    0
+#define FMAN_SP_DMA_ATTR_SWP_SHIFT		    30
+#define FMAN_SP_DMA_ATTR_IC_CACHE_SHIFT	    28
+#define FMAN_SP_DMA_ATTR_HDR_CACHE_SHIFT	    26
+#define FMAN_SP_DMA_ATTR_SG_CACHE_SHIFT	    24
+#define FMAN_SP_IC_TO_EXT_SHIFT		    16
+#define FMAN_SP_IC_FROM_INT_SHIFT		    8
+#define FMAN_SP_IC_SIZE_SHIFT			    0
+
+/* defaults */
+#define DEFAULT_FMAN_SP_DMA_SWAP_DATA			      FMAN_DMA_NO_SWP
+#define DEFAULT_FMAN_SP_DMA_INT_CONTEXT_CACHE_ATTR	      FMAN_DMA_NO_STASH
+#define DEFAULT_FMAN_SP_DMA_HEADER_CACHE_ATTR		      FMAN_DMA_NO_STASH
+#define DEFAULT_FMAN_SP_DMA_SCATTER_GATHER_CACHE_ATTR	      FMAN_DMA_NO_STASH
+#define DEFAULT_FMAN_SP_DMA_WRITE_OPTIMIZE		      true
+#define DEFAULT_FMAN_SP_NO_SCATTER_GATHER		      false
+
+#endif	/* __FSL_FMAN_SP_H */
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 04/12] fsl/fman: Add the FMan port FLIB
  2015-05-07 13:05   ` [RFC,v3 03/12] fsl/fman: Add the FMan port FLIB headers Madalin Bucur
@ 2015-05-07 13:05     ` Madalin Bucur
  2015-05-07 13:05       ` [RFC,v3 05/12] fsl/fman: Add the FMan MAC FLIB headers Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

The FMan Port FLib provides basic API used by the drivers to
configure and control the FMan Port hardware.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 drivers/net/ethernet/freescale/fman/Kconfig        |   1 +
 drivers/net/ethernet/freescale/fman/Makefile       |   2 +
 drivers/net/ethernet/freescale/fman/port/Makefile  |   3 +
 .../net/ethernet/freescale/fman/port/fman_port.c   | 728 +++++++++++++++++++++
 4 files changed, 734 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/fman/port/Makefile
 create mode 100644 drivers/net/ethernet/freescale/fman/port/fman_port.c

diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
index 8aeae29..af42c3a 100644
--- a/drivers/net/ethernet/freescale/fman/Kconfig
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -5,3 +5,4 @@ config FSL_FMAN
 	help
 		Freescale Data-Path Acceleration Architecture Frame Manager
 		(FMan) support
+
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index a718f7c..a9ae0aa 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -3,3 +3,5 @@ subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib
 obj-y		+= fsl_fman.o
 
 fsl_fman-objs			:= fman.o
+
+obj-y	+= port/
diff --git a/drivers/net/ethernet/freescale/fman/port/Makefile b/drivers/net/ethernet/freescale/fman/port/Makefile
new file mode 100644
index 0000000..54b1fa4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/port/Makefile
@@ -0,0 +1,3 @@
+obj-y	+= fsl_fman_port.o
+
+fsl_fman_port-objs		:= fman_port.o
diff --git a/drivers/net/ethernet/freescale/fman/port/fman_port.c b/drivers/net/ethernet/freescale/fman/port/fman_port.c
new file mode 100644
index 0000000..7d04084
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/port/fman_port.c
@@ -0,0 +1,728 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "common/general.h"
+
+#include "fman_common.h"
+#include "fsl_fman_port.h"
+
+/* problem Eyal: the following should not be here*/
+#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME	0x00000028
+
+static uint32_t get_no_pcd_nia_bmi_ac_enc_frame(struct fman_port_cfg *cfg)
+{
+	if (cfg->errata_A006675)
+		return NIA_ENG_FM_CTL |
+		    NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME;
+	else
+		return NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME;
+}
+
+static int init_bmi_rx(struct fman_port *port,
+		       struct fman_port_cfg *cfg,
+		       struct fman_port_params *params)
+{
+	struct fman_port_rx_bmi_regs __iomem *regs = &port->bmi_regs->rx;
+	uint32_t tmp;
+
+	/* Rx Configuration register */
+	tmp = 0;
+	if (cfg->discard_override)
+		tmp |= BMI_PORT_CFG_FDOVR;
+	iowrite32be(tmp, &regs->fmbm_rcfg);
+
+	/* DMA attributes */
+	tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+	if (cfg->dma_ic_stash_on)
+		tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+	if (cfg->dma_header_stash_on)
+		tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+	if (cfg->dma_sg_stash_on)
+		tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+	if (cfg->dma_write_optimize)
+		tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
+	iowrite32be(tmp, &regs->fmbm_rda);
+
+	/* Rx FIFO parameters */
+	tmp = (cfg->rx_pri_elevation / FMAN_PORT_BMI_FIFO_UNITS - 1) <<
+	    BMI_RX_FIFO_PRI_ELEVATION_SHIFT;
+	tmp |= cfg->rx_fifo_thr / FMAN_PORT_BMI_FIFO_UNITS - 1;
+	iowrite32be(tmp, &regs->fmbm_rfp);
+
+	if (cfg->excessive_threshold_register)
+		/* always allow access to the extra resources */
+		iowrite32be(BMI_RX_FIFO_THRESHOLD_ETHE, &regs->fmbm_reth);
+
+	/* Frame end data */
+	tmp = (uint32_t)cfg->checksum_bytes_ignore <<
+	    BMI_RX_FRAME_END_CS_IGNORE_SHIFT;
+	tmp |= (uint32_t)cfg->rx_cut_end_bytes << BMI_RX_FRAME_END_CUT_SHIFT;
+	if (cfg->errata_A006320)
+		tmp &= 0xffe0ffff;
+	iowrite32be(tmp, &regs->fmbm_rfed);
+
+	/* Internal context parameters */
+	tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_TO_EXT_SHIFT;
+	tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_FROM_INT_SHIFT;
+	tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+	iowrite32be(tmp, &regs->fmbm_ricp);
+
+	/* Internal buffer offset */
+	tmp = ((uint32_t)cfg->int_buf_start_margin / FMAN_PORT_IC_OFFSET_UNITS)
+	    << BMI_INT_BUF_MARG_SHIFT;
+	iowrite32be(tmp, &regs->fmbm_rim);
+
+	/* External buffer margins */
+	tmp = (uint32_t)cfg->ext_buf_start_margin <<
+	    BMI_EXT_BUF_MARG_START_SHIFT;
+	tmp |= (uint32_t)cfg->ext_buf_end_margin;
+	if (cfg->fmbm_rebm_has_sgd && cfg->no_scatter_gather)
+		tmp |= BMI_SG_DISABLE;
+	iowrite32be(tmp, &regs->fmbm_rebm);
+
+	/* Frame attributes */
+	tmp = BMI_CMD_RX_MR_DEF;
+	tmp |= BMI_CMD_ATTR_ORDER;
+	tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+	if (cfg->sync_req)
+		tmp |= BMI_CMD_ATTR_SYNC;
+
+	iowrite32be(tmp, &regs->fmbm_rfca);
+
+	/* NIA */
+	tmp = (uint32_t)cfg->rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT;
+	tmp |= get_no_pcd_nia_bmi_ac_enc_frame(cfg);
+
+	iowrite32be(tmp, &regs->fmbm_rfne);
+
+	/* Enqueue NIA */
+	iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, &regs->fmbm_rfene);
+
+	/* Default/error queues */
+	iowrite32be((params->dflt_fqid & 0x00FFFFFF), &regs->fmbm_rfqid);
+	iowrite32be((params->err_fqid & 0x00FFFFFF), &regs->fmbm_refqid);
+
+	/* Discard/error masks */
+	iowrite32be(params->discard_mask, &regs->fmbm_rfsdm);
+	iowrite32be(params->err_mask, &regs->fmbm_rfsem);
+
+	/* Statistics counters */
+	tmp = 0;
+	if (cfg->stats_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_rstc);
+
+	/* Performance counters */
+	fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+	tmp = 0;
+	if (cfg->perf_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_rpc);
+
+	return 0;
+}
+
+static int init_bmi_tx(struct fman_port *port,
+		       struct fman_port_cfg *cfg,
+		       struct fman_port_params *params)
+{
+	struct fman_port_tx_bmi_regs __iomem *regs = &port->bmi_regs->tx;
+	uint32_t tmp;
+
+	/* Tx Configuration register */
+	tmp = 0;
+	iowrite32be(tmp, &regs->fmbm_tcfg);
+
+	/* DMA attributes */
+	tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+	if (cfg->dma_ic_stash_on)
+		tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+	if (cfg->dma_header_stash_on)
+		tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+	if (cfg->dma_sg_stash_on)
+		tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+	iowrite32be(tmp, &regs->fmbm_tda);
+
+	/* Tx FIFO parameters */
+	tmp = (cfg->tx_fifo_min_level / FMAN_PORT_BMI_FIFO_UNITS) <<
+	    BMI_TX_FIFO_MIN_FILL_SHIFT;
+	tmp |= ((uint32_t)cfg->tx_fifo_deq_pipeline_depth - 1) <<
+	    BMI_FIFO_PIPELINE_DEPTH_SHIFT;
+	tmp |= (uint32_t)(cfg->tx_fifo_low_comf_level /
+			   FMAN_PORT_BMI_FIFO_UNITS - 1);
+	iowrite32be(tmp, &regs->fmbm_tfp);
+
+	/* Frame end data */
+	tmp = (uint32_t)cfg->checksum_bytes_ignore <<
+	    BMI_FRAME_END_CS_IGNORE_SHIFT;
+	iowrite32be(tmp, &regs->fmbm_tfed);
+
+	/* Internal context parameters */
+	tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_TO_EXT_SHIFT;
+	tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_FROM_INT_SHIFT;
+	tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+	iowrite32be(tmp, &regs->fmbm_ticp);
+
+	/* Frame attributes */
+	tmp = BMI_CMD_TX_MR_DEF;
+	tmp |= BMI_CMD_ATTR_ORDER;
+	tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+	iowrite32be(tmp, &regs->fmbm_tfca);
+
+	/* Dequeue NIA + enqueue NIA */
+	iowrite32be(NIA_ENG_QMI_DEQ, &regs->fmbm_tfdne);
+	iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, &regs->fmbm_tfene);
+	if (cfg->fmbm_tfne_has_features)
+		iowrite32be(!params->dflt_fqid ?
+			    BMI_EBD_EN | NIA_BMI_AC_FETCH_ALL_FRAME :
+			    NIA_BMI_AC_FETCH_ALL_FRAME, &regs->fmbm_tfne);
+	if (!params->dflt_fqid && params->dont_release_buf) {
+		iowrite32be(0x00FFFFFF, &regs->fmbm_tcfqid);
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE,
+			    &regs->fmbm_tfene);
+		if (cfg->fmbm_tfne_has_features)
+			iowrite32be(ioread32be(&regs->fmbm_tfne) & ~BMI_EBD_EN,
+				    &regs->fmbm_tfne);
+	}
+
+	/* Confirmation/error queues */
+	if (params->dflt_fqid || !params->dont_release_buf)
+		iowrite32be(params->dflt_fqid & 0x00FFFFFF, &regs->fmbm_tcfqid);
+	iowrite32be((params->err_fqid & 0x00FFFFFF), &regs->fmbm_tefqid);
+
+	/* Statistics counters */
+	tmp = 0;
+	if (cfg->stats_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_tstc);
+
+	/* Performance counters */
+	fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+	tmp = 0;
+	if (cfg->perf_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_tpc);
+
+	return 0;
+}
+
+static int init_bmi_oh(struct fman_port *port,
+		       struct fman_port_cfg *cfg,
+		       struct fman_port_params *params)
+{
+	struct fman_port_oh_bmi_regs __iomem *regs = &port->bmi_regs->oh;
+	uint32_t tmp;
+
+	/* OP Configuration register */
+	tmp = 0;
+	if (cfg->discard_override)
+		tmp |= BMI_PORT_CFG_FDOVR;
+	iowrite32be(tmp, &regs->fmbm_ocfg);
+
+	/* DMA attributes */
+	tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+	if (cfg->dma_ic_stash_on)
+		tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+	if (cfg->dma_header_stash_on)
+		tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+	if (cfg->dma_sg_stash_on)
+		tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+	if (cfg->dma_write_optimize)
+		tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
+	iowrite32be(tmp, &regs->fmbm_oda);
+
+	/* Tx FIFO parameters */
+	tmp = ((uint32_t)cfg->tx_fifo_deq_pipeline_depth - 1) <<
+	    BMI_FIFO_PIPELINE_DEPTH_SHIFT;
+	iowrite32be(tmp, &regs->fmbm_ofp);
+
+	/* Internal context parameters */
+	tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_TO_EXT_SHIFT;
+	tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_FROM_INT_SHIFT;
+	tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+	iowrite32be(tmp, &regs->fmbm_oicp);
+
+	/* Frame attributes */
+	tmp = BMI_CMD_OP_MR_DEF;
+	tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+	if (cfg->sync_req)
+		tmp |= BMI_CMD_ATTR_SYNC;
+	if (port->type == E_FMAN_PORT_TYPE_OP)
+		tmp |= BMI_CMD_ATTR_ORDER;
+	iowrite32be(tmp, &regs->fmbm_ofca);
+
+	/* Internal buffer offset */
+	tmp = ((uint32_t)cfg->int_buf_start_margin / FMAN_PORT_IC_OFFSET_UNITS)
+	    << BMI_INT_BUF_MARG_SHIFT;
+	iowrite32be(tmp, &regs->fmbm_oim);
+
+	/* Dequeue NIA */
+	iowrite32be(NIA_ENG_QMI_DEQ, &regs->fmbm_ofdne);
+
+	/* NIA and Enqueue NIA */
+	iowrite32be(get_no_pcd_nia_bmi_ac_enc_frame(cfg),
+		    &regs->fmbm_ofne);
+	iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR,
+		    &regs->fmbm_ofene);
+
+	/* Default/error queues */
+	iowrite32be((params->dflt_fqid & 0x00FFFFFF), &regs->fmbm_ofqid);
+	iowrite32be((params->err_fqid & 0x00FFFFFF), &regs->fmbm_oefqid);
+
+	/* Discard/error masks */
+	if (port->type == E_FMAN_PORT_TYPE_OP) {
+		iowrite32be(params->discard_mask, &regs->fmbm_ofsdm);
+		iowrite32be(params->err_mask, &regs->fmbm_ofsem);
+	}
+
+	/* Statistics counters */
+	tmp = 0;
+	if (cfg->stats_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_ostc);
+
+	/* Performance counters */
+	fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+	tmp = 0;
+	if (cfg->perf_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_opc);
+
+	return 0;
+}
+
+static int init_qmi(struct fman_port *port,
+		    struct fman_port_cfg *cfg, struct fman_port_params *params)
+{
+	struct fman_port_qmi_regs __iomem *regs = port->qmi_regs;
+	uint32_t tmp;
+
+	tmp = 0;
+	if (cfg->queue_counters_enable)
+		tmp |= QMI_PORT_CFG_EN_COUNTERS;
+	iowrite32be(tmp, &regs->fmqm_pnc);
+
+	/* Rx port configuration */
+	if ((port->type == E_FMAN_PORT_TYPE_RX) ||
+	    (port->type == E_FMAN_PORT_TYPE_RX_10G)) {
+		/* Enqueue NIA */
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, &regs->fmqm_pnen);
+		return 0;
+	}
+
+	/* Continue with Tx and O/H port configuration */
+	if ((port->type == E_FMAN_PORT_TYPE_TX) ||
+	    (port->type == E_FMAN_PORT_TYPE_TX_10G)) {
+		/* Enqueue NIA */
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE,
+			    &regs->fmqm_pnen);
+		/* Dequeue NIA */
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX, &regs->fmqm_pndn);
+	} else {
+		/* Enqueue NIA */
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, &regs->fmqm_pnen);
+		/* Dequeue NIA */
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_FETCH, &regs->fmqm_pndn);
+	}
+
+	/* Dequeue Configuration register */
+	tmp = 0;
+	if (cfg->deq_high_pri)
+		tmp |= QMI_DEQ_CFG_PRI;
+
+	switch (cfg->deq_type) {
+	case E_FMAN_PORT_DEQ_BY_PRI:
+		tmp |= QMI_DEQ_CFG_TYPE1;
+		break;
+	case E_FMAN_PORT_DEQ_ACTIVE_FQ:
+		tmp |= QMI_DEQ_CFG_TYPE2;
+		break;
+	case E_FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS:
+		tmp |= QMI_DEQ_CFG_TYPE3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (cfg->qmi_deq_options_support) {
+		switch (cfg->deq_prefetch_opt) {
+		case E_FMAN_PORT_DEQ_NO_PREFETCH:
+			break;
+		case E_FMAN_PORT_DEQ_PART_PREFETCH:
+			tmp |= QMI_DEQ_CFG_PREFETCH_PARTIAL;
+			break;
+		case E_FMAN_PORT_DEQ_FULL_PREFETCH:
+			tmp |= QMI_DEQ_CFG_PREFETCH_FULL;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+	tmp |= (uint32_t)(params->deq_sp & QMI_DEQ_CFG_SP_MASK) <<
+		QMI_DEQ_CFG_SP_SHIFT;
+	tmp |= cfg->deq_byte_cnt;
+	iowrite32be(tmp, &regs->fmqm_pndc);
+
+	return 0;
+}
+
+void fman_port_defconfig(struct fman_port_cfg *cfg, enum fman_port_type type)
+{
+	cfg->dma_swap_data = E_FMAN_PORT_DMA_NO_SWAP;
+	cfg->dma_ic_stash_on = false;
+	cfg->dma_header_stash_on = false;
+	cfg->dma_sg_stash_on = false;
+	cfg->dma_write_optimize = true;
+	cfg->color = E_FMAN_PORT_COLOR_GREEN;
+	cfg->discard_override = false;
+	cfg->checksum_bytes_ignore = 0;
+	cfg->rx_cut_end_bytes = 4;
+	cfg->rx_pri_elevation = ((0x3FF + 1) * FMAN_PORT_BMI_FIFO_UNITS);
+	cfg->rx_fifo_thr = ((0x3FF + 1) * FMAN_PORT_BMI_FIFO_UNITS);
+	cfg->rx_fd_bits = 0;
+	cfg->ic_ext_offset = 0;
+	cfg->ic_int_offset = 0;
+	cfg->ic_size = 0;
+	cfg->int_buf_start_margin = 0;
+	cfg->ext_buf_start_margin = 0;
+	cfg->ext_buf_end_margin = 0;
+	cfg->tx_fifo_min_level = 0;
+	cfg->tx_fifo_low_comf_level = (5 * 1024);
+	cfg->stats_counters_enable = true;
+	cfg->perf_counters_enable = true;
+	cfg->deq_type = E_FMAN_PORT_DEQ_BY_PRI;
+
+	cfg->sync_req = true;
+	cfg->deq_prefetch_opt = E_FMAN_PORT_DEQ_FULL_PREFETCH;
+
+	if (type == E_FMAN_PORT_TYPE_TX_10G) {
+		cfg->tx_fifo_deq_pipeline_depth = 4;
+		cfg->deq_high_pri = true;
+		cfg->deq_byte_cnt = 0x1400;
+	} else {
+		if (type == E_FMAN_PORT_TYPE_OP)
+			cfg->tx_fifo_deq_pipeline_depth = 2;
+		else
+			cfg->tx_fifo_deq_pipeline_depth = 1;
+
+		cfg->deq_high_pri = false;
+		cfg->deq_byte_cnt = 0x400;
+	}
+	cfg->no_scatter_gather = DEFAULT_FMAN_SP_NO_SCATTER_GATHER;
+}
+
+int fman_port_init(struct fman_port *port,
+		   struct fman_port_cfg *cfg, struct fman_port_params *params)
+{
+	int err;
+
+	/* Init BMI registers */
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+		err = init_bmi_rx(port, cfg, params);
+		break;
+	case E_FMAN_PORT_TYPE_TX:
+	case E_FMAN_PORT_TYPE_TX_10G:
+		err = init_bmi_tx(port, cfg, params);
+		break;
+	case E_FMAN_PORT_TYPE_OP:
+		err = init_bmi_oh(port, cfg, params);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (err)
+		return err;
+
+	/* Init QMI registers */
+	err = init_qmi(port, cfg, params);
+	return err;
+
+	return 0;
+}
+
+int fman_port_enable(struct fman_port *port)
+{
+	uint32_t __iomem *bmi_cfg_reg;
+	uint32_t tmp;
+	bool rx_port;
+
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+		bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg;
+		rx_port = true;
+		break;
+	case E_FMAN_PORT_TYPE_TX:
+	case E_FMAN_PORT_TYPE_TX_10G:
+		bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg;
+		rx_port = false;
+		break;
+	case E_FMAN_PORT_TYPE_OP:
+		bmi_cfg_reg = &port->bmi_regs->oh.fmbm_ocfg;
+		rx_port = false;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Enable QMI */
+	if (!rx_port) {
+		tmp = ioread32be(&port->qmi_regs->fmqm_pnc) | QMI_PORT_CFG_EN;
+		iowrite32be(tmp, &port->qmi_regs->fmqm_pnc);
+	}
+
+	/* Enable BMI */
+	tmp = ioread32be(bmi_cfg_reg) | BMI_PORT_CFG_EN;
+	iowrite32be(tmp, bmi_cfg_reg);
+
+	return 0;
+}
+
+int fman_port_disable(const struct fman_port *port)
+{
+	uint32_t __iomem *bmi_cfg_reg, *bmi_status_reg;
+	uint32_t tmp;
+	bool rx_port, failure = false;
+	int count;
+
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+		bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg;
+		bmi_status_reg = &port->bmi_regs->rx.fmbm_rst;
+		rx_port = true;
+		break;
+	case E_FMAN_PORT_TYPE_TX:
+	case E_FMAN_PORT_TYPE_TX_10G:
+		bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg;
+		bmi_status_reg = &port->bmi_regs->tx.fmbm_tst;
+		rx_port = false;
+		break;
+	case E_FMAN_PORT_TYPE_OP:
+		bmi_cfg_reg = &port->bmi_regs->oh.fmbm_ocfg;
+		bmi_status_reg = &port->bmi_regs->oh.fmbm_ost;
+		rx_port = false;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Disable QMI */
+	if (!rx_port) {
+		tmp = ioread32be(&port->qmi_regs->fmqm_pnc) & ~QMI_PORT_CFG_EN;
+		iowrite32be(tmp, &port->qmi_regs->fmqm_pnc);
+
+		/* Wait for QMI to finish FD handling */
+		count = 100;
+		do {
+			usleep_range(10, 11);
+			tmp = ioread32be(&port->qmi_regs->fmqm_pns);
+		} while ((tmp & QMI_PORT_STATUS_DEQ_FD_BSY) && --count);
+
+		if (count == 0) {
+			/* Timeout */
+			failure = true;
+		}
+	}
+
+	/* Disable BMI */
+	tmp = ioread32be(bmi_cfg_reg) & ~BMI_PORT_CFG_EN;
+	iowrite32be(tmp, bmi_cfg_reg);
+
+	/* Wait for graceful stop end */
+	count = 500;
+	do {
+		usleep_range(10, 11);
+		tmp = ioread32be(bmi_status_reg);
+	} while ((tmp & BMI_PORT_STATUS_BSY) && --count);
+
+	if (count == 0) {
+		/* Timeout */
+		failure = true;
+	}
+
+	if (failure)
+		return -EBUSY;
+
+	return 0;
+}
+
+int fman_port_set_bpools(const struct fman_port *port,
+			 const struct fman_port_bpools *bp)
+{
+	uint32_t __iomem *bp_reg, *bp_depl_reg;
+	uint32_t tmp;
+	uint8_t i, max_bp_num;
+	bool grp_depl_used = false, rx_port;
+
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+		max_bp_num = port->ext_pools_num;
+		rx_port = true;
+		bp_reg = port->bmi_regs->rx.fmbm_ebmpi;
+		bp_depl_reg = &port->bmi_regs->rx.fmbm_mpd;
+		break;
+	case E_FMAN_PORT_TYPE_OP:
+		if (port->fm_rev_maj != 4)
+			return -EINVAL;
+		max_bp_num = FMAN_PORT_OBS_EXT_POOLS_NUM;
+		rx_port = false;
+		bp_reg = port->bmi_regs->oh.fmbm_oebmpi;
+		bp_depl_reg = &port->bmi_regs->oh.fmbm_ompd;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (rx_port) {
+		/* Check buffers are provided in ascending order */
+		for (i = 0; (i < (bp->count - 1) &&
+			     (i < FMAN_PORT_MAX_EXT_POOLS_NUM - 1)); i++) {
+			if (bp->bpool[i].size > bp->bpool[i + 1].size)
+				return -EINVAL;
+		}
+	}
+
+	/* Set up external buffers pools */
+	for (i = 0; i < bp->count; i++) {
+		tmp = BMI_EXT_BUF_POOL_VALID;
+		tmp |= ((uint32_t)bp->bpool[i].bpid <<
+			BMI_EXT_BUF_POOL_ID_SHIFT) & BMI_EXT_BUF_POOL_ID_MASK;
+
+		if (rx_port) {
+			if (bp->counters_enable)
+				tmp |= BMI_EXT_BUF_POOL_EN_COUNTER;
+
+			if (bp->bpool[i].is_backup)
+				tmp |= BMI_EXT_BUF_POOL_BACKUP;
+
+			tmp |= (uint32_t)bp->bpool[i].size;
+		}
+
+		iowrite32be(tmp, &bp_reg[i]);
+	}
+
+	/* Clear unused pools */
+	for (i = bp->count; i < max_bp_num; i++)
+		iowrite32be(0, &bp_reg[i]);
+
+	/* Pools depletion */
+	tmp = 0;
+	for (i = 0; i < FMAN_PORT_MAX_EXT_POOLS_NUM; i++) {
+		if (bp->bpool[i].grp_bp_depleted) {
+			grp_depl_used = true;
+			tmp |= 0x80000000 >> i;
+		}
+
+		if (bp->bpool[i].single_bp_depleted)
+			tmp |= 0x80 >> i;
+	}
+
+	if (grp_depl_used)
+		tmp |= ((uint32_t)bp->grp_bp_depleted_num - 1) <<
+		    BMI_POOL_DEP_NUM_OF_POOLS_SHIFT;
+
+	iowrite32be(tmp, bp_depl_reg);
+	return 0;
+}
+
+int fman_port_set_perf_cnt_params(struct fman_port *port,
+				  struct fman_port_perf_cnt_params *params)
+{
+	uint32_t __iomem *pcp_reg;
+	uint32_t tmp;
+
+	/* Obtain register address and check parameters are in range */
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+		pcp_reg = &port->bmi_regs->rx.fmbm_rpcp;
+		if ((params->queue_val == 0) ||
+		    (params->queue_val > MAX_PERFORMANCE_RX_QUEUE_COMP))
+			return -EINVAL;
+		break;
+	case E_FMAN_PORT_TYPE_TX:
+	case E_FMAN_PORT_TYPE_TX_10G:
+		pcp_reg = &port->bmi_regs->tx.fmbm_tpcp;
+		if ((params->queue_val == 0) ||
+		    (params->queue_val > MAX_PERFORMANCE_TX_QUEUE_COMP))
+			return -EINVAL;
+		break;
+	case E_FMAN_PORT_TYPE_OP:
+		pcp_reg = &port->bmi_regs->oh.fmbm_opcp;
+		if (params->queue_val != 0)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if ((params->task_val == 0) ||
+	    (params->task_val > MAX_PERFORMANCE_TASK_COMP))
+		return -EINVAL;
+	if ((params->dma_val == 0) ||
+	    (params->dma_val > MAX_PERFORMANCE_DMA_COMP))
+		return -EINVAL;
+	if ((params->fifo_val == 0) ||
+	    ((params->fifo_val / FMAN_PORT_BMI_FIFO_UNITS) >
+	     MAX_PERFORMANCE_FIFO_COMP))
+		return -EINVAL;
+	tmp = (uint32_t)(params->task_val - 1) <<
+	    BMI_PERFORMANCE_TASK_COMP_SHIFT;
+	tmp |= (uint32_t)(params->dma_val - 1) <<
+	    BMI_PERFORMANCE_DMA_COMP_SHIFT;
+	tmp |= (uint32_t)(params->fifo_val / FMAN_PORT_BMI_FIFO_UNITS - 1);
+
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+	case E_FMAN_PORT_TYPE_TX:
+	case E_FMAN_PORT_TYPE_TX_10G:
+		tmp |= (uint32_t)(params->queue_val - 1) <<
+		    BMI_PERFORMANCE_QUEUE_COMP_SHIFT;
+		break;
+	default:
+		break;
+	}
+
+	iowrite32be(tmp, pcp_reg);
+	return 0;
+}
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 05/12] fsl/fman: Add the FMan MAC FLIB headers
  2015-05-07 13:05     ` [RFC,v3 04/12] fsl/fman: Add the FMan port FLIB Madalin Bucur
@ 2015-05-07 13:05       ` Madalin Bucur
  2015-05-07 13:05         ` [RFC,v3 06/12] fsl/fman: Add the FMan MAC FLIB Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

The FMan MAC FLib provides basic API used by the drivers to
configure and control the FMan MAC hardware.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 .../net/ethernet/freescale/fman/flib/fsl_enet.h    | 275 +++++++
 .../ethernet/freescale/fman/flib/fsl_fman_dtsec.h  | 791 +++++++++++++++++++++
 .../freescale/fman/flib/fsl_fman_dtsec_mii_acc.h   | 103 +++
 .../ethernet/freescale/fman/flib/fsl_fman_memac.h  | 453 ++++++++++++
 .../freescale/fman/flib/fsl_fman_memac_mii_acc.h   |  76 ++
 .../ethernet/freescale/fman/flib/fsl_fman_tgec.h   | 409 +++++++++++
 6 files changed, 2107 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_enet.h
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec.h
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec_mii_acc.h
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac_mii_acc.h
 create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_tgec.h

diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_enet.h b/drivers/net/ethernet/freescale/fman/flib/fsl_enet.h
new file mode 100644
index 0000000..78e7d04
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_enet.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_ENET_H
+#define __FSL_ENET_H
+
+/*Ethernet MAC-PHY Interface */
+
+enum enet_interface {
+	E_ENET_IF_MII = 0x00010000,	      /* MII interface */
+	E_ENET_IF_RMII = 0x00020000,	      /* RMII interface */
+	E_ENET_IF_SMII = 0x00030000,	      /* SMII interface */
+	E_ENET_IF_GMII = 0x00040000,	      /* GMII interface */
+	E_ENET_IF_RGMII = 0x00050000,	      /* RGMII interface */
+	E_ENET_IF_TBI = 0x00060000,	      /* TBI interface */
+	E_ENET_IF_RTBI = 0x00070000,	      /* RTBI interface */
+	E_ENET_IF_SGMII = 0x00080000,	      /* SGMII interface */
+	E_ENET_IF_XGMII = 0x00090000,	      /* XGMII interface */
+	E_ENET_IF_QSGMII = 0x000a0000,	      /* QSGMII interface */
+	E_ENET_IF_XFI = 0x000b0000	      /* XFI interface */
+};
+
+/* Ethernet Speed (nominal data rate) */
+enum enet_speed {
+	E_ENET_SPEED_10 = 10,		/* 10 Mbps */
+	E_ENET_SPEED_100 = 100,		/* 100 Mbps */
+	E_ENET_SPEED_1000 = 1000,	/* 1000 Mbps = 1 Gbps */
+	E_ENET_SPEED_10000 = 10000	/* 10000 Mbps = 10 Gbps */
+};
+
+enum mac_type {
+	E_MAC_DTSEC,
+	E_MAC_TGEC,
+	E_MAC_MEMAC
+};
+
+/* Enum for inter-module interrupts registration */
+enum fman_event_modules {
+	E_FMAN_MOD_PRS,			  /* Parser event */
+	E_FMAN_MOD_KG,			  /* Keygen event */
+	E_FMAN_MOD_PLCR,		  /* Policer event */
+	E_FMAN_MOD_10G_MAC,		  /* 10G MAC event */
+	E_FMAN_MOD_1G_MAC,		  /* 1G MAC event */
+	E_FMAN_MOD_TMR,			  /* Timer event */
+	E_FMAN_MOD_FMAN_CTRL,		  /* FMAN Controller  Timer event */
+	E_FMAN_MOD_MACSEC,
+	E_FMAN_MOD_DUMMY_LAST
+};
+
+/* Enum for interrupts types */
+enum fman_intr_type {
+	E_FMAN_INTR_TYPE_ERR,
+	E_FMAN_INTR_TYPE_NORMAL
+};
+
+/* enum for defining MAC types */
+enum fman_mac_type {
+	E_FMAN_MAC_10G = 0,		  /* 10G MAC */
+	E_FMAN_MAC_1G			  /* 1G MAC */
+};
+
+enum fman_mac_exceptions {
+	E_FMAN_MAC_EX_10G_MDIO_SCAN_EVENTMDIO = 0,
+		/* 10GEC MDIO scan event interrupt */
+	E_FMAN_MAC_EX_10G_MDIO_CMD_CMPL,
+		/* 10GEC MDIO command completion interrupt */
+	E_FMAN_MAC_EX_10G_REM_FAULT,
+		/* 10GEC, mEMAC Remote fault interrupt */
+	E_FMAN_MAC_EX_10G_LOC_FAULT,
+		/* 10GEC, mEMAC Local fault interrupt */
+	E_FMAN_MAC_EX_10G_1TX_ECC_ER,
+		/* 10GEC, mEMAC Transmit frame ECC error interrupt */
+	E_FMAN_MAC_EX_10G_TX_FIFO_UNFL,
+		/* 10GEC, mEMAC Transmit FIFO underflow interrupt */
+	E_FMAN_MAC_EX_10G_TX_FIFO_OVFL,
+		/* 10GEC, mEMAC Transmit FIFO overflow interrupt */
+	E_FMAN_MAC_EX_10G_TX_ER,
+		/* 10GEC Transmit frame error interrupt */
+	E_FMAN_MAC_EX_10G_RX_FIFO_OVFL,
+		/* 10GEC, mEMAC Receive FIFO overflow interrupt */
+	E_FMAN_MAC_EX_10G_RX_ECC_ER,
+		/* 10GEC, mEMAC Receive frame ECC error interrupt */
+	E_FMAN_MAC_EX_10G_RX_JAB_FRM,
+		/* 10GEC Receive jabber frame interrupt */
+	E_FMAN_MAC_EX_10G_RX_OVRSZ_FRM,
+		/* 10GEC Receive oversized frame interrupt */
+	E_FMAN_MAC_EX_10G_RX_RUNT_FRM,
+		/* 10GEC Receive runt frame interrupt */
+	E_FMAN_MAC_EX_10G_RX_FRAG_FRM,
+		/* 10GEC Receive fragment frame interrupt */
+	E_FMAN_MAC_EX_10G_RX_LEN_ER,
+		/* 10GEC Receive payload length error interrupt */
+	E_FMAN_MAC_EX_10G_RX_CRC_ER,
+		/* 10GEC Receive CRC error interrupt */
+	E_FMAN_MAC_EX_10G_RX_ALIGN_ER,
+		/* 10GEC Receive alignment error interrupt */
+	E_FMAN_MAC_EX_1G_BAB_RX,
+		/* dTSEC Babbling receive error */
+	E_FMAN_MAC_EX_1G_RX_CTL,
+		/* dTSEC Receive control (pause frame) interrupt */
+	E_FMAN_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET,
+		/* dTSEC Graceful transmit stop complete */
+	E_FMAN_MAC_EX_1G_BAB_TX,
+		/* dTSEC Babbling transmit error */
+	E_FMAN_MAC_EX_1G_TX_CTL,
+		/* dTSEC Transmit control (pause frame) interrupt */
+	E_FMAN_MAC_EX_1G_TX_ERR,
+		/* dTSEC Transmit error */
+	E_FMAN_MAC_EX_1G_LATE_COL,
+		/* dTSEC Late collision */
+	E_FMAN_MAC_EX_1G_COL_RET_LMT,
+		/* dTSEC Collision retry limit */
+	E_FMAN_MAC_EX_1G_TX_FIFO_UNDRN,
+		/* dTSEC Transmit FIFO underrun */
+	E_FMAN_MAC_EX_1G_MAG_PCKT,
+		/* dTSEC Magic Packet detection */
+	E_FMAN_MAC_EX_1G_MII_MNG_RD_COMPLET,
+		/* dTSEC MII management read completion */
+	E_FMAN_MAC_EX_1G_MII_MNG_WR_COMPLET,
+		/* dTSEC MII management write completion */
+	E_FMAN_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET,
+		/* dTSEC Graceful receive stop complete */
+	E_FMAN_MAC_EX_1G_TX_DATA_ERR,
+		/* dTSEC Internal data error on transmit */
+	E_FMAN_MAC_EX_1G_RX_DATA_ERR,
+		/* dTSEC Internal data error on receive */
+	E_FMAN_MAC_EX_1G_1588_TS_RX_ERR,
+		/* dTSEC Time-Stamp Receive Error */
+	E_FMAN_MAC_EX_1G_RX_MIB_CNT_OVFL,
+		/* dTSEC MIB counter overflow */
+	E_FMAN_MAC_EX_TS_FIFO_ECC_ERR,
+		/* < mEMAC Time-stamp FIFO ECC error interrupt;
+		 * not supported on T4240/B4860 rev1 chips
+		 */
+};
+
+/* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC
+ * and phy or backplane;
+ * Note: 1000BaseX auto-negotiation relates only to interface between MAC
+ * and phy/backplane, SGMII phy can still synchronize with far-end phy at
+ * 10Mbps, 100Mbps or 1000Mbps
+ */
+#define ENET_IF_SGMII_BASEX 0x80000000
+
+enum enet_mode {
+	E_ENET_MODE_INVALID = 0,
+		/* Invalid Ethernet mode */
+	E_ENET_MODE_MII_10 = (E_ENET_IF_MII | E_ENET_SPEED_10),
+		/*    10 Mbps MII   */
+	E_ENET_MODE_MII_100 = (E_ENET_IF_MII | E_ENET_SPEED_100),
+		/*   100 Mbps MII   */
+	E_ENET_MODE_RMII_10 = (E_ENET_IF_RMII | E_ENET_SPEED_10),
+		/*    10 Mbps RMII  */
+	E_ENET_MODE_RMII_100 = (E_ENET_IF_RMII | E_ENET_SPEED_100),
+		/*   100 Mbps RMII  */
+	E_ENET_MODE_SMII_10 = (E_ENET_IF_SMII | E_ENET_SPEED_10),
+		/*    10 Mbps SMII  */
+	E_ENET_MODE_SMII_100 = (E_ENET_IF_SMII | E_ENET_SPEED_100),
+		/*   100 Mbps SMII  */
+	E_ENET_MODE_GMII_1000 = (E_ENET_IF_GMII | E_ENET_SPEED_1000),
+		/*  1000 Mbps GMII  */
+	E_ENET_MODE_RGMII_10 = (E_ENET_IF_RGMII | E_ENET_SPEED_10),
+		/*    10 Mbps RGMII */
+	E_ENET_MODE_RGMII_100 = (E_ENET_IF_RGMII | E_ENET_SPEED_100),
+		/*   100 Mbps RGMII */
+	E_ENET_MODE_RGMII_1000 = (E_ENET_IF_RGMII | E_ENET_SPEED_1000),
+		/*  1000 Mbps RGMII */
+	E_ENET_MODE_TBI_1000 = (E_ENET_IF_TBI | E_ENET_SPEED_1000),
+		/*  1000 Mbps TBI   */
+	E_ENET_MODE_RTBI_1000 = (E_ENET_IF_RTBI | E_ENET_SPEED_1000),
+		/*  1000 Mbps RTBI  */
+	E_ENET_MODE_SGMII_10 = (E_ENET_IF_SGMII | E_ENET_SPEED_10),
+		/* 10 Mbps SGMII with auto-negotiation between MAC and
+		 * SGMII phy according to Cisco SGMII specification
+		 */
+	E_ENET_MODE_SGMII_100 = (E_ENET_IF_SGMII | E_ENET_SPEED_100),
+		/* 100 Mbps SGMII with auto-negotiation between MAC and
+		 * SGMII phy according to Cisco SGMII specification
+		 */
+	E_ENET_MODE_SGMII_1000 = (E_ENET_IF_SGMII | E_ENET_SPEED_1000),
+		/* 1000 Mbps SGMII with auto-negotiation between MAC and
+		 * SGMII phy according to Cisco SGMII specification
+		 */
+	E_ENET_MODE_SGMII_BASEX_10 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII
+				      | E_ENET_SPEED_10),
+		/* 10 Mbps SGMII with 1000BaseX auto-negotiation between
+		 * MAC and SGMII phy or backplane
+		 */
+	E_ENET_MODE_SGMII_BASEX_100 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII
+				       | E_ENET_SPEED_100),
+		/* 100 Mbps SGMII with 1000BaseX auto-negotiation between
+		 * MAC and SGMII phy or backplane
+		 */
+	E_ENET_MODE_SGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII
+					| E_ENET_SPEED_1000),
+		/* 1000 Mbps SGMII with 1000BaseX auto-negotiation between
+		 * MAC and SGMII phy or backplane
+		 */
+	E_ENET_MODE_QSGMII_1000 = (E_ENET_IF_QSGMII | E_ENET_SPEED_1000),
+		/* 1000 Mbps QSGMII with auto-negotiation between MAC and
+		 * QSGMII phy according to Cisco QSGMII specification
+		 */
+	E_ENET_MODE_QSGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | E_ENET_IF_QSGMII
+					 | E_ENET_SPEED_1000),
+		/* 1000 Mbps QSGMII with 1000BaseX auto-negotiation between
+		 * MAC and QSGMII phy or backplane
+		 */
+	E_ENET_MODE_XGMII_10000 = (E_ENET_IF_XGMII | E_ENET_SPEED_10000),
+		/* 10000 Mbps XGMII */
+	E_ENET_MODE_XFI_10000 = (E_ENET_IF_XFI | E_ENET_SPEED_10000)
+		/* 10000 Mbps XFI */
+};
+
+enum fmam_mac_statistics_level {
+	E_FMAN_MAC_NONE_STATISTICS,	/* No statistics */
+	E_FMAN_MAC_PARTIAL_STATISTICS,	/* Only error counters are available;
+					 * Optimized for performance
+					 */
+	E_FMAN_MAC_FULL_STATISTICS	/* All counters available; Not
+					 * optimized for performance
+					 */
+};
+
+#define _MAKE_ENET_MODE(_interface, _speed) (enum enet_mode)((_interface) \
+	| (_speed))
+
+#define _ENET_INTERFACE_FROM_MODE(mode) \
+	((enum enet_interface)((mode) & 0x0FFF0000))
+
+#define _ENET_SPEED_FROM_MODE(mode) (enum enet_speed)((mode) & 0x0000FFFF)
+#define _ENET_ADDR_TO_UINT64(_enet_addr)		\
+	(uint64_t)(((uint64_t)(_enet_addr)[0] << 40) |	\
+		((uint64_t)(_enet_addr)[1] << 32) |	\
+		((uint64_t)(_enet_addr)[2] << 24) |	\
+		((uint64_t)(_enet_addr)[3] << 16) |	\
+		((uint64_t)(_enet_addr)[4] << 8) |	\
+		((uint64_t)(_enet_addr)[5]))
+
+#define _MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr)		\
+	do {								\
+		int i;							\
+		for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)	\
+			(_enet_addr)[i] =				\
+				(uint8_t)((_addr64) >> ((5 - i) * 8));	\
+	} while (0)
+
+#endif	/* __FSL_ENET_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec.h
new file mode 100644
index 0000000..ef753b3
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec.h
@@ -0,0 +1,791 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_DTSEC_H
+#define __FSL_FMAN_DTSEC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+
+/* dTSEC Init sequence
+ *To prepare dTSEC block for transfer use the following call sequence:
+ *- fman_dtsec_defconfig() - This step is optional and yet recommended. Its
+ *use is to obtain the default dTSEC configuration parameters.
+ *- Change dtsec configuration in &dtsec_cfg. This structure will be used
+ *to customize the dTSEC behavior.
+ *- fman_dtsec_init() - Applies the configuration on dTSEC hardware.  Note that
+ *dTSEC is initialized while both Tx and Rx are disabled.
+ *- fman_dtsec_set_mac_address() - Set the station address (mac address).
+ *This is used by dTSEC to match against received packets.
+ *
+ *- fman_dtsec_adjust_link() - Set the link speed and duplex parameters
+ *after the PHY establishes the link.
+ *- dtsec_enable_tx() and dtsec_enable_rx() to enable transmission and
+ *reception.
+ */
+
+/*  dTSEC Graceful stop
+ *To temporary stop dTSEC activity use fman_dtsec_stop_tx() and
+ *fman_dtsec_stop_rx(). Note that these functions request dTSEC graceful stop
+ *but return before this stop is complete.  To query for graceful stop
+ *completion use fman_dtsec_get_event() and check DTSEC_IEVENT_GTSC and
+ *DTSEC_IEVENT_GRSC bits. Alternatively the dTSEC interrupt mask can be set to
+ *enable graceful stop interrupts.
+ *To resume operation after graceful stop use fman_dtsec_start_tx() and
+ *fman_dtsec_start_rx().
+ */
+
+/* dTSEC interrupt handling
+ *
+ *This code does not provide an interrupt handler for dTSEC.  Instead this
+ *handler should be implemented and registered to the operating system by the
+ *caller.  Some primitives for accessing the event status and mask registers
+ *are provided.
+ *See "dTSEC Events" section for a list of events that dTSEC can generate.
+ */
+
+/*dTSEC Events
+ *Interrupt events cause dTSEC event bits to be set.  Software may poll the
+ *event register at any time to check for pending interrupts.  If an event
+ *occurs and its corresponding enable bit is set in the interrupt mask
+ *register, the event also causes a hardware interrupt at the PIC.
+ *To poll for event status use the fman_dtsec_get_event() function.
+ *To configure the interrupt mask use fman_dtsec_enable_interrupt() and
+ *fman_dtsec_disable_interrupt() functions.
+ *After servicing a dTSEC interrupt use fman_dtsec_ack_event to reset the
+ *serviced event bit.
+ *The following events may be signaled by dTSEC hardware:
+ *%DTSEC_IEVENT_BABR - Babbling receive error.	This bit indicates that
+ *a frame was received with length in excess of the MAC's maximum frame length
+ *register.
+ *%DTSEC_IEVENT_RXC - Receive control (pause frame) interrupt.	A pause
+ *control frame was received while Rx pause frame handling is enabled.
+ *Also see fman_dtsec_handle_rx_pause().
+ *%DTSEC_IEVENT_MSRO - MIB counter overflow.  The count for one of the MIB
+ *counters has exceeded the size of its register.
+ *%DTSEC_IEVENT_GTSC - Graceful transmit stop complete.	 Graceful stop is now
+ *complete. The transmitter is in a stopped state, in which only pause frames
+ *can be transmitted.
+ *Also see fman_dtsec_stop_tx().
+ *%DTSEC_IEVENT_BABT - Babbling transmit error.	 The transmitted frame length
+ *has exceeded the value in the MAC's Maximum Frame Length register.
+ *%DTSEC_IEVENT_TXC - Transmit control (pause frame) interrupt.	 his bit
+ *indicates that a control frame was transmitted.
+ *%DTSEC_IEVENT_TXE - Transmit error.  This bit indicates that an error
+ *occurred on the transmitted channel.	This bit is set whenever any transmit
+ *error occurs which causes the dTSEC to discard all or part of a frame
+ *(LC, CRL, XFUN).
+ *%DTSEC_IEVENT_LC - Late collision.  This bit indicates that a collision
+ *occurred beyond the collision window (slot time) in half-duplex mode.
+ *The frame is truncated with a bad CRC and the remainder of the frame
+ *is discarded.
+ *%DTSEC_IEVENT_CRL - Collision retry limit.  is bit indicates that the number
+ *of successive transmission collisions has exceeded the MAC's half-duplex
+ *register's retransmission maximum count.  The frame is discarded without
+ *being transmitted and transmission of the next frame commences.  This only
+ *occurs while in half-duplex mode.
+ *The number of retransmit attempts can be set in
+ *&dtsec_halfdup_cfg.retransmit before calling fman_dtsec_init().
+ *%DTSEC_IEVENT_XFUN - Transmit FIFO underrun.	This bit indicates that the
+ *transmit FIFO became empty before the complete frame was transmitted.
+ *The frame is truncated with a bad CRC and the remainder of the frame is
+ *discarded.
+ *%DTSEC_IEVENT_MAG - TBD
+ *%DTSEC_IEVENT_MMRD - MII management read completion.
+ *%DTSEC_IEVENT_MMWR - MII management write completion.
+ *%DTSEC_IEVENT_GRSC - Graceful receive stop complete.	It allows the user to
+ *know if the system has completed the stop and it is safe to write to receive
+ *registers (status, control or configuration registers) that are used by the
+ *system during normal operation.
+ *%DTSEC_IEVENT_TDPE - Internal data error on transmit.	 This bit indicates
+ *that the dTSEC has detected a parity error on its stored transmit data, which
+ *is likely to compromise the validity of recently transferred frames.
+ *%DTSEC_IEVENT_RDPE - Internal data error on receive.	This bit indicates that
+ *the dTSEC has detected a parity error on its stored receive data, which is
+ *likely to compromise the validity of recently transferred frames.
+ */
+/* Interrupt Mask Register (IMASK) */
+#define DTSEC_IMASK_BREN	0x80000000
+#define DTSEC_IMASK_RXCEN	0x40000000
+#define DTSEC_IMASK_MSROEN	0x04000000
+#define DTSEC_IMASK_GTSCEN	0x02000000
+#define DTSEC_IMASK_BTEN	0x01000000
+#define DTSEC_IMASK_TXCEN	0x00800000
+#define DTSEC_IMASK_TXEEN	0x00400000
+#define DTSEC_IMASK_LCEN	0x00040000
+#define DTSEC_IMASK_CRLEN	0x00020000
+#define DTSEC_IMASK_XFUNEN	0x00010000
+#define DTSEC_IMASK_ABRTEN	0x00008000
+#define DTSEC_IMASK_IFERREN	0x00004000
+#define DTSEC_IMASK_MAGEN	0x00000800
+#define DTSEC_IMASK_MMRDEN	0x00000400
+#define DTSEC_IMASK_MMWREN	0x00000200
+#define DTSEC_IMASK_GRSCEN	0x00000100
+#define DTSEC_IMASK_TDPEEN	0x00000002
+#define DTSEC_IMASK_RDPEEN	0x00000001
+
+#define DTSEC_EVENTS_MASK				\
+	((uint32_t)(DTSEC_IMASK_BREN	| \
+				DTSEC_IMASK_RXCEN   | \
+				DTSEC_IMASK_BTEN    | \
+				DTSEC_IMASK_TXCEN   | \
+				DTSEC_IMASK_TXEEN   | \
+				DTSEC_IMASK_ABRTEN  | \
+				DTSEC_IMASK_LCEN    | \
+				DTSEC_IMASK_CRLEN   | \
+				DTSEC_IMASK_XFUNEN  | \
+				DTSEC_IMASK_IFERREN | \
+				DTSEC_IMASK_MAGEN   | \
+				DTSEC_IMASK_TDPEEN  | \
+				DTSEC_IMASK_RDPEEN))
+
+/* dtsec timestamp event bits */
+#define TMR_PEMASK_TSREEN	0x00010000
+#define TMR_PEVENT_TSRE		0x00010000
+
+/* Group address bit indication */
+#define MAC_GROUP_ADDRESS	0x0000010000000000ULL
+/* size in bytes of L2 address */
+#define MAC_ADDRLEN		6
+
+#define DEFAULT_HALFDUP_ON		false
+#define DEFAULT_HALFDUP_RETRANSMIT	0xf
+#define DEFAULT_HALFDUP_COLL_WINDOW	0x37
+#define DEFAULT_HALFDUP_EXCESS_DEFER	true
+#define DEFAULT_HALFDUP_NO_BACKOFF	false
+#define DEFAULT_HALFDUP_BP_NO_BACKOFF	false
+#define DEFAULT_HALFDUP_ALT_BACKOFF_VAL	0x0A
+#define DEFAULT_HALFDUP_ALT_BACKOFF_EN	false
+#define DEFAULT_RX_DROP_BCAST		false
+#define DEFAULT_RX_SHORT_FRM		true
+#define DEFAULT_RX_LEN_CHECK		false
+#define DEFAULT_TX_PAD_CRC		true
+#define DEFAULT_TX_CRC			false
+#define DEFAULT_RX_CTRL_ACC		false
+#define DEFAULT_TX_PAUSE_TIME		0xf000
+#define DEFAULT_TBIPA			5
+#define DEFAULT_RX_PREPEND		0
+#define DEFAULT_PTP_TSU_EN		true
+#define DEFAULT_PTP_EXCEPTION_EN	true
+#define DEFAULT_PREAMBLE_LEN		7
+#define DEFAULT_RX_PREAMBLE		false
+#define DEFAULT_TX_PREAMBLE		false
+#define DEFAULT_LOOPBACK		false
+#define DEFAULT_RX_TIME_STAMP_EN	false
+#define DEFAULT_TX_TIME_STAMP_EN	false
+#define DEFAULT_RX_FLOW			true
+#define DEFAULT_TX_FLOW			true
+#define DEFAULT_RX_GROUP_HASH_EXD	false
+#define DEFAULT_TX_PAUSE_TIME_EXTD	0
+#define DEFAULT_RX_PROMISC		false
+#define DEFAULT_NON_BACK_TO_BACK_IPG1	0x40
+#define DEFAULT_NON_BACK_TO_BACK_IPG2	0x60
+#define DEFAULT_MIN_IFG_ENFORCEMENT	0x50
+#define DEFAULT_BACK_TO_BACK_IPG	0x60
+#define DEFAULT_MAXIMUM_FRAME		0x600
+#define DEFAULT_TBI_PHY_ADDR		5
+#define DEFAULT_WAKE_ON_LAN		false
+
+/* register related defines (bits, field offsets..) */
+#define DTSEC_ID1_ID			0xffff0000
+#define DTSEC_ID1_REV_MJ		0x0000FF00
+#define DTSEC_ID1_REV_MN		0x000000ff
+
+#define DTSEC_ID2_INT_REDUCED_OFF	0x00010000
+#define DTSEC_ID2_INT_NORMAL_OFF	0x00020000
+
+#define DTSEC_ECNTRL_CLRCNT		0x00004000
+#define DTSEC_ECNTRL_AUTOZ		0x00002000
+#define DTSEC_ECNTRL_STEN		0x00001000
+#define DTSEC_ECNTRL_CFG_RO		0x80000000
+#define DTSEC_ECNTRL_GMIIM		0x00000040
+#define DTSEC_ECNTRL_TBIM		0x00000020
+#define DTSEC_ECNTRL_SGMIIM		0x00000002
+#define DTSEC_ECNTRL_RPM		0x00000010
+#define DTSEC_ECNTRL_R100M		0x00000008
+#define DTSEC_ECNTRL_RMM		0x00000004
+#define DTSEC_ECNTRL_QSGMIIM		0x00000001
+
+#define DTSEC_TCTRL_THDF		0x00000800
+#define DTSEC_TCTRL_TTSE		0x00000040
+#define DTSEC_TCTRL_GTS			0x00000020
+#define DTSEC_TCTRL_TFC_PAUSE		0x00000010
+
+/* PTV offsets */
+#define PTV_PTE_OFST		16
+
+#define RCTRL_CFA		0x00008000
+#define RCTRL_GHTX		0x00000400
+#define RCTRL_RTSE		0x00000040
+#define RCTRL_GRS		0x00000020
+#define RCTRL_BC_REJ		0x00000010
+#define RCTRL_MPROM		0x00000008
+#define RCTRL_RSF		0x00000004
+#define RCTRL_UPROM		0x00000001
+#define RCTRL_PROM		(RCTRL_UPROM | RCTRL_MPROM)
+
+#define TMR_CTL_ESFDP		0x00000800
+#define TMR_CTL_ESFDE		0x00000400
+
+#define MACCFG1_SOFT_RESET	0x80000000
+#define MACCFG1_LOOPBACK	0x00000100
+#define MACCFG1_RX_FLOW		0x00000020
+#define MACCFG1_TX_FLOW		0x00000010
+#define MACCFG1_TX_EN		0x00000001
+#define MACCFG1_RX_EN		0x00000004
+
+#define MACCFG2_NIBBLE_MODE	0x00000100
+#define MACCFG2_BYTE_MODE	0x00000200
+#define MACCFG2_PRE_AM_RX_EN	0x00000080
+#define MACCFG2_PRE_AM_TX_EN	0x00000040
+#define MACCFG2_LENGTH_CHECK	0x00000010
+#define MACCFG2_MAGIC_PACKET_EN	0x00000008
+#define MACCFG2_PAD_CRC_EN	0x00000004
+#define MACCFG2_CRC_EN		0x00000002
+#define MACCFG2_FULL_DUPLEX	0x00000001
+
+#define PREAMBLE_LENGTH_SHIFT	12
+
+#define IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT	24
+#define IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT	16
+#define IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT	8
+
+#define IPGIFG_NON_BACK_TO_BACK_IPG_1	0x7F000000
+#define IPGIFG_NON_BACK_TO_BACK_IPG_2	0x007F0000
+#define IPGIFG_MIN_IFG_ENFORCEMENT	0x0000FF00
+#define IPGIFG_BACK_TO_BACK_IPG		0x0000007F
+
+#define HAFDUP_ALT_BEB			0x00080000
+#define HAFDUP_BP_NO_BACKOFF		0x00040000
+#define HAFDUP_NO_BACKOFF		0x00020000
+#define HAFDUP_EXCESS_DEFER		0x00010000
+#define HAFDUP_COLLISION_WINDOW		0x000003ff
+
+#define HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT	20
+#define HAFDUP_RETRANSMISSION_MAX_SHIFT		12
+#define HAFDUP_RETRANSMISSION_MAX		0x0000f000
+
+#define NUM_OF_HASH_REGS	8	/* Number of hash table registers */
+
+/* CAR1/2 bits */
+#define DTSEC_CAR1_TR64		0x80000000
+#define DTSEC_CAR1_TR127	0x40000000
+#define DTSEC_CAR1_TR255	0x20000000
+#define DTSEC_CAR1_TR511	0x10000000
+#define DTSEC_CAR1_TRK1		0x08000000
+#define DTSEC_CAR1_TRMAX	0x04000000
+#define DTSEC_CAR1_TRMGV	0x02000000
+
+#define DTSEC_CAR1_RBYT		0x00010000
+#define DTSEC_CAR1_RPKT		0x00008000
+#define DTSEC_CAR1_RFCS		0x00004000
+#define DTSEC_CAR1_RMCA		0x00002000
+#define DTSEC_CAR1_RBCA		0x00001000
+#define DTSEC_CAR1_RXCF		0x00000800
+#define DTSEC_CAR1_RXPF		0x00000400
+#define DTSEC_CAR1_RXUO		0x00000200
+#define DTSEC_CAR1_RALN		0x00000100
+#define DTSEC_CAR1_RFLR		0x00000080
+#define DTSEC_CAR1_RCDE		0x00000040
+#define DTSEC_CAR1_RCSE		0x00000020
+#define DTSEC_CAR1_RUND		0x00000010
+#define DTSEC_CAR1_ROVR		0x00000008
+#define DTSEC_CAR1_RFRG		0x00000004
+#define DTSEC_CAR1_RJBR		0x00000002
+#define DTSEC_CAR1_RDRP		0x00000001
+
+#define DTSEC_CAR2_TJBR		0x00080000
+#define DTSEC_CAR2_TFCS		0x00040000
+#define DTSEC_CAR2_TXCF		0x00020000
+#define DTSEC_CAR2_TOVR		0x00010000
+#define DTSEC_CAR2_TUND		0x00008000
+#define DTSEC_CAR2_TFRG		0x00004000
+#define DTSEC_CAR2_TBYT		0x00002000
+#define DTSEC_CAR2_TPKT		0x00001000
+#define DTSEC_CAR2_TMCA		0x00000800
+#define DTSEC_CAR2_TBCA		0x00000400
+#define DTSEC_CAR2_TXPF		0x00000200
+#define DTSEC_CAR2_TDFR		0x00000100
+#define DTSEC_CAR2_TEDF		0x00000080
+#define DTSEC_CAR2_TSCL		0x00000040
+#define DTSEC_CAR2_TMCL		0x00000020
+#define DTSEC_CAR2_TLCL		0x00000010
+#define DTSEC_CAR2_TXCL		0x00000008
+#define DTSEC_CAR2_TNCL		0x00000004
+#define DTSEC_CAR2_TDRP		0x00000001
+
+/* memory map */
+
+struct dtsec_regs {
+	/* dTSEC General Control and Status Registers */
+	uint32_t tsec_id;	/* 0x000 ETSEC_ID register */
+	uint32_t tsec_id2;	/* 0x004 ETSEC_ID2 register */
+	uint32_t ievent;	/* 0x008 Interrupt event register */
+	uint32_t imask;		/* 0x00C Interrupt mask register */
+	uint32_t reserved0010[1];
+	uint32_t ecntrl;	/* 0x014 E control register */
+	uint32_t ptv;		/* 0x018 Pause time value register */
+	uint32_t tbipa;		/* 0x01C TBI PHY address register */
+	uint32_t tmr_ctrl;	/* 0x020 Time-stamp Control register */
+	uint32_t tmr_pevent;	/* 0x024 Time-stamp event register */
+	uint32_t tmr_pemask;	/* 0x028 Timer event mask register */
+	uint32_t reserved002c[5];
+	uint32_t tctrl;		/* 0x040 Transmit control register */
+	uint32_t reserved0044[3];
+	uint32_t rctrl;		/* 0x050 Receive control register */
+	uint32_t reserved0054[11];
+	uint32_t igaddr[8];	/* 0x080-0x09C Individual/group address */
+	uint32_t gaddr[8];	/* 0x0A0-0x0BC Group address registers 0-7 */
+	uint32_t reserved00c0[16];
+	uint32_t maccfg1;	/* 0x100 MAC configuration #1 */
+	uint32_t maccfg2;	/* 0x104 MAC configuration #2 */
+	uint32_t ipgifg;	/* 0x108 IPG/IFG */
+	uint32_t hafdup;	/* 0x10C Half-duplex */
+	uint32_t maxfrm;	/* 0x110 Maximum frame */
+	uint32_t reserved0114[10];
+	uint32_t ifstat;	/* 0x13C Interface status */
+	uint32_t macstnaddr1;	/* 0x140 Station Address,part 1 */
+	uint32_t macstnaddr2;	/* 0x144 Station Address,part 2	 */
+	struct {
+		uint32_t exact_match1;	/* octets 1-4 */
+		uint32_t exact_match2;	/* octets 5-6 */
+	} macaddr[15];		/* 0x148-0x1BC mac exact match addresses 1-15 */
+	uint32_t reserved01c0[16];
+	/* 0x200 transmit and receive 64 byte frame counter */
+	uint32_t tr64;
+	/* 0x204 transmit and receive 65 to 127 byte frame counter */
+	uint32_t tr127;
+	/* 0x208 transmit and receive 128 to 255 byte frame counter */
+	uint32_t tr255;
+	/* 0x20C transmit and receive 256 to 511 byte frame counter */
+	uint32_t tr511;
+	/* 0x210 transmit and receive 512 to 1023 byte frame counter */
+	uint32_t tr1k;
+	/* 0x214 transmit and receive 1024 to 1518 byte frame counter */
+	uint32_t trmax;
+	/* 0x218 transmit and receive 1519 to 1522 byte good VLAN frame count*/
+	uint32_t trmgv;
+	uint32_t rbyt;		/* 0x21C receive byte counter */
+	uint32_t rpkt;		/* 0x220 receive packet counter */
+	uint32_t rfcs;		/* 0x224 receive FCS error counter */
+	/* 0x228 RMCA receive multicast packet counter */
+	uint32_t rmca;
+	uint32_t rbca;		/* 0x22C receive broadcast packet counter */
+	uint32_t rxcf;		/* 0x230 receive control frame packet counter */
+	uint32_t rxpf;		/* 0x234 receive pause frame packet counter */
+	uint32_t rxuo;		/* 0x238 receive unknown OP code counter */
+	uint32_t raln;		/* 0x23C receive alignment error counter */
+	uint32_t rflr;		/* 0x240 receive frame length error counter */
+	uint32_t rcde;		/* 0x244 receive code error counter */
+	uint32_t rcse;		/* 0x248 receive carrier sense error counter */
+	uint32_t rund;		/* 0x24C receive undersize packet counter */
+	uint32_t rovr;		/* 0x250 receive oversize packet counter */
+	uint32_t rfrg;		/* 0x254 receive fragments counter */
+	uint32_t rjbr;		/* 0x258 receive jabber counter */
+	uint32_t rdrp;		/* 0x25C receive drop */
+	uint32_t tbyt;		/* 0x260 transmit byte counter */
+	uint32_t tpkt;		/* 0x264 transmit packet counter */
+	uint32_t tmca;		/* 0x268 transmit multicast packet counter */
+	uint32_t tbca;		/* 0x26C transmit broadcast packet counter */
+	uint32_t txpf;		/* 0x270 transmit pause control frame counter */
+	uint32_t tdfr;		/* 0x274 transmit deferral packet counter */
+	/* 0x278 transmit excessive deferral packet counter */
+	uint32_t tedf;
+	/* 0x27C transmit single collision packet counter */
+	uint32_t tscl;
+	/* 0x280 transmit multiple collision packet counter */
+	uint32_t tmcl;
+	/* 0x284 transmit late collision packet counter */
+	uint32_t tlcl;
+	/* 0x288 transmit excessive collision packet counter */
+	uint32_t txcl;
+	uint32_t tncl;		/* 0x28C transmit total collision counter */
+	uint32_t reserved0290[1];
+	uint32_t tdrp;		/* 0x294 transmit drop frame counter */
+	uint32_t tjbr;		/* 0x298 transmit jabber frame counter */
+	uint32_t tfcs;		/* 0x29C transmit FCS error counter */
+	uint32_t txcf;		/* 0x2A0 transmit control frame counter */
+	uint32_t tovr;		/* 0x2A4 transmit oversize frame counter */
+	uint32_t tund;		/* 0x2A8 transmit undersize frame counter */
+	uint32_t tfrg;		/* 0x2AC transmit fragments frame counter */
+	uint32_t car1;		/* 0x2B0 carry register one register* */
+	uint32_t car2;		/* 0x2B4 carry register two register* */
+	uint32_t cam1;		/* 0x2B8 carry register one mask register */
+	uint32_t cam2;		/* 0x2BC carry register two mask register */
+	uint32_t reserved02c0[848];
+};
+
+/* struct dtsec_cfg - dTSEC configuration
+ * Transmit half-duplex flow control, under software
+ * control for 10/100-Mbps half-duplex media. If set,
+ * back pressure is applied to media by raising carrier.
+ * halfdup_retransmit:
+ * Number of retransmission attempts following a collision.
+ * If this is exceeded dTSEC aborts transmission due to
+ * excessive collisions. The standard specifies the
+ * attempt limit to be 15.
+ * halfdup_coll_window:
+ * The number of bytes of the frame during which
+ * collisions may occur. The default value of 55
+ * corresponds to the frame byte at the end of the
+ * standard 512-bit slot time window. If collisions are
+ * detected after this byte, the late collision event is
+ * asserted and transmission of current frame is aborted.
+ * rx_drop_bcast:
+ * Discard broadcast frames.  If set, all broadcast frames
+ * will be discarded by dTSEC.
+ * rx_short_frm:
+ * Accept short frames.	 If set, dTSEC will accept frames
+ * of length 14..63 bytes.
+ * rx_len_check:
+ * Length check for received frames.  If set, the MAC
+ * checks the frame's length field on receive to ensure it
+ * matches the actual data field length. This only works
+ * for received frames with length field less than 1500.
+ * No check is performed for larger frames.
+ * tx_pad_crc:
+ * Pad and append CRC.	If set, the MAC pads all
+ * transmitted short frames and appends a CRC to every
+ * frame regardless of padding requirement.
+ * tx_crc:
+ * Transmission CRC enable.  If set, the MAC appends a CRC
+ * to all frames.  If frames presented to the MAC have a
+ * valid length and contain a valid CRC, tx_crc should be
+ * reset.
+ * This field is ignored if tx_pad_crc is set.
+ * rx_ctrl_acc:
+ * Control frame accept.  If set, this overrides 802.3
+ * standard control frame behavior, and all Ethernet frames
+ * that have an ethertype of 0x8808 are treated as normal
+ * Ethernet frames and passed up to the packet interface on
+ * a DA match.	Received pause control frames are passed to
+ * the packet interface only if Rx flow control is also
+ * disabled.  See fman_dtsec_handle_rx_pause() function.
+ * tx_pause_time:
+ * Transmit pause time value.  This pause value is used as
+ * part of the pause frame to be sent when a transmit pause
+ * frame is initiated.	If set to 0 this disables
+ * transmission of pause frames.
+ * rx_preamble:
+ * Receive preamble enable.  If set, the MAC recovers the
+ * received Ethernet 7-byte preamble and passes it to the
+ * packet interface at the start of each received frame.
+ * This field should be reset for internal MAC loop-back
+ * mode.
+ * tx_preamble:	User defined preamble enable for transmitted frames.
+ * If set, a user-defined preamble must passed to the MAC
+ * and it is transmitted instead of the standard preamble.
+ * preamble_len:
+ * Length, in bytes, of the preamble field preceding each
+ * Ethernet start-of-frame delimiter byte.  The default
+ * value of 0x7 should be used in order to guarantee
+ * reliable operation with IEEE 802.3 compliant hardware.
+ * rx_prepend:
+ * Packet alignment padding length.  The specified number
+ * of bytes (1-31) of zero padding are inserted before the
+ * start of each received frame.  For Ethernet, where
+ * optional preamble extraction is enabled, the padding
+ * appears before the preamble, otherwise the padding
+ * precedes the layer 2 header.
+ *
+ * This structure contains basic dTSEC configuration and must be passed to
+ * fman_dtsec_init() function.	A default set of configuration values can be
+ * obtained by calling fman_dtsec_defconfig().
+ */
+struct dtsec_cfg {
+	bool halfdup_on;
+	bool halfdup_alt_backoff_en;
+	bool halfdup_excess_defer;
+	bool halfdup_no_backoff;
+	bool halfdup_bp_no_backoff;
+	uint8_t halfdup_alt_backoff_val;
+	uint16_t halfdup_retransmit;
+	uint16_t halfdup_coll_window;
+	bool rx_drop_bcast;
+	bool rx_short_frm;
+	bool rx_len_check;
+	bool tx_pad_crc;
+	bool tx_crc;
+	bool rx_ctrl_acc;
+	unsigned short tx_pause_time;
+	unsigned short tbipa;
+	bool ptp_tsu_en;
+	bool ptp_exception_en;
+	bool rx_preamble;
+	bool tx_preamble;
+	unsigned char preamble_len;
+	unsigned char rx_prepend;
+	bool loopback;
+	bool rx_time_stamp_en;
+	bool tx_time_stamp_en;
+	bool rx_flow;
+	bool tx_flow;
+	bool rx_group_hash_exd;
+	bool rx_promisc;
+	uint8_t tbi_phy_addr;
+	uint16_t tx_pause_time_extd;
+	uint16_t maximum_frame;
+	uint32_t non_back_to_back_ipg1;
+	uint32_t non_back_to_back_ipg2;
+	uint32_t min_ifg_enforcement;
+	uint32_t back_to_back_ipg;
+	bool wake_on_lan;
+};
+
+/*fman_dtsec_defconfig() - Get default dTSEC configuration
+ *cfg:	pointer to configuration structure.
+ *
+ *Call this function to obtain a default set of configuration values for
+ *initializing dTSEC.  The user can overwrite any of the values before calling
+ *fman_dtsec_init(), if specific configuration needs to be applied.
+ */
+void fman_dtsec_defconfig(struct dtsec_cfg *cfg);
+
+/*fman_dtsec_init() - Init dTSEC hardware block
+ *regs:		Pointer to dTSEC register block
+ *cfg:		dTSEC configuration data
+ *iface_mode:		dTSEC interface mode, the type of MAC - PHY interface.
+ *iface_speed:	1G or 10G
+ *macaddr:		MAC station address to be assigned to the device
+ *fm_rev_maj:		major rev number
+ *fm_rev_min:		minor rev number
+ *exceptions_mask:	initial exceptions mask
+ *This function initializes dTSEC and applies basic configuration.
+ *
+ *dTSEC initialization sequence:
+ *Before enabling Rx/Tx call dtsec_set_address() to set MAC address,
+ *fman_dtsec_adjust_link() to configure interface speed and duplex and finally
+ *dtsec_enable_tx()/dtsec_enable_rx() to start transmission and reception.
+ *
+ *Returns: 0 if successful, an error code otherwise.
+ */
+int fman_dtsec_init(struct dtsec_regs __iomem *regs, struct dtsec_cfg *cfg,
+		    enum enet_interface iface_mode,
+		    enum enet_speed iface_speed,
+		    uint8_t *macaddr, uint8_t fm_rev_maj,
+		    uint8_t fm_rev_min, uint32_t exception_mask);
+
+/*fman_dtsec_enable() - Enable dTSEC Tx and Tx
+ *regs:	Pointer to dTSEC register block
+ *apply_rx:	enable rx side
+ *apply_tx:	enable tx side
+ *This function resets Tx and Rx graceful stop bit and enables dTSEC Tx and Rx.
+ */
+void fman_dtsec_enable(struct dtsec_regs __iomem *regs, bool apply_rx,
+		       bool apply_tx);
+
+/*fman_dtsec_disable() - Disable dTSEC Tx and Rx
+ *regs:	Pointer to dTSEC register block
+ *apply_rx:	disable rx side
+ *apply_tx:	disable tx side
+ *This function disables Tx and Rx in dTSEC.
+ */
+void fman_dtsec_disable(struct dtsec_regs __iomem *regs, bool apply_rx,
+			bool apply_tx);
+
+/*fman_dtsec_get_revision() - Get dTSEC hardware revision
+ *regs:	  Pointer to dTSEC register block
+ *Returns dtsec_id content
+ *Call this function to obtain the dTSEC hardware version.
+ */
+uint32_t fman_dtsec_get_revision(struct dtsec_regs __iomem *regs);
+
+/*fman_dtsec_set_mac_address() - Set MAC station address
+ *regs:	  Pointer to dTSEC register block
+ *macaddr:    MAC address array
+ *This function sets MAC station address.  To enable unicast reception call
+ *this after fman_dtsec_init().	 While promiscuous mode is disabled dTSEC will
+ *match the destination address of received unicast frames against this
+ *address.
+ */
+void fman_dtsec_set_mac_address(struct dtsec_regs __iomem *regs,
+				uint8_t *macaddr);
+
+/*fman_dtsec_get_mac_address() - Query MAC station address
+ *regs:	  Pointer to dTSEC register block
+ *macaddr:    MAC address array
+ */
+void fman_dtsec_get_mac_address(struct dtsec_regs __iomem *regs,
+				uint8_t *macaddr);
+
+/*fman_dtsec_set_uc_promisc() - Sets unicast promiscuous mode
+ *regs:	Pointer to dTSEC register block
+ *enable:	Enable unicast promiscuous mode
+ *Use this function to enable/disable dTSEC L2 address filtering.  If the
+ *address filtering is disabled all unicast packets are accepted.
+ *To set dTSEC in promiscuous mode call both fman_dtsec_set_uc_promisc() and
+ *fman_dtsec_set_mc_promisc() to disable filtering for both unicast and
+ *multicast addresses.
+ */
+void fman_dtsec_set_uc_promisc(struct dtsec_regs __iomem *regs, bool enable);
+
+/*fman_dtsec_adjust_link() - Adjust dTSEC speed/duplex settings
+ *regs:	Pointer to dTSEC register block
+ *iface_mode: dTSEC interface mode
+ *speed:	Link speed
+ *full_dx:	True for full-duplex, false for half-duplex.
+ *This function configures the MAC to function and the desired rates.  Use it
+ *to configure dTSEC after fman_dtsec_init() and whenever the link speed
+ *changes (for instance following PHY auto-negociation).
+ *Returns: 0 if successful, an error code otherwise.
+ */
+int fman_dtsec_adjust_link(struct dtsec_regs __iomem *regs,
+			   enum enet_interface iface_mode,
+			   enum enet_speed speed, bool full_dx);
+
+/*fman_dtsec_set_max_frame_len() - Set max frame length
+ *regs:	Pointer to dTSEC register block
+ *length:	Max frame length.
+ *Sets maximum frame length for received and transmitted frames.  Frames that
+ *exceeds this length are truncated.
+ */
+void fman_dtsec_set_max_frame_len(struct dtsec_regs __iomem *regs,
+				  uint16_t length);
+
+/*fman_dtsec_get_max_frame_len() - Query max frame length
+ *regs:	Pointer to dTSEC register block
+ *Returns: the current value of the maximum frame length.
+ */
+uint16_t fman_dtsec_get_max_frame_len(struct dtsec_regs __iomem *regs);
+
+/*fman_dtsec_handle_rx_pause() - Configure pause frame handling
+ *regs:	Pointer to dTSEC register block
+ *en:		Enable pause frame handling in dTSEC
+ *If enabled, dTSEC will handle pause frames internally.  This must be disabled
+ *if dTSEC is set in half-duplex mode.
+ *If pause frame handling is disabled and &dtsec_cfg.rx_ctrl_acc is set, pause
+ *frames will be transferred to the packet interface just like regular Ethernet
+ *frames.
+ */
+void fman_dtsec_handle_rx_pause(struct dtsec_regs __iomem *regs, bool en);
+
+/*fman_dtsec_set_tx_pause_frames() - Configure Tx pause time
+ *regs:	Pointer to dTSEC register block
+ *time:	Time value included in pause frames
+ *Call this function to set the time value used in transmitted pause frames.
+ *If time is 0, transmission of pause frames is disabled
+ */
+void fman_dtsec_set_tx_pause_frames(struct dtsec_regs __iomem *regs,
+				    uint16_t time);
+
+/*fman_dtsec_ack_event() - Acknowledge handled events
+ *regs:	Pointer to dTSEC register block
+ *ev_mask:	Events to acknowledge
+ *After handling events signaled by dTSEC in either polling or interrupt mode,
+ *call this function to reset the associated status bits in dTSEC event
+ *register.
+ */
+void fman_dtsec_ack_event(struct dtsec_regs __iomem *regs, uint32_t ev_mask);
+
+/*fman_dtsec_get_event() - Returns currently asserted events
+ *regs:	Pointer to dTSEC register block
+ *ev_mask:	Mask of relevant events
+ *Call this function to obtain a bit-mask of events that are currently asserted
+ *in dTSEC, taken from IEVENT register.
+ *Returns: a bit-mask of events asserted in dTSEC.
+ */
+uint32_t fman_dtsec_get_event(struct dtsec_regs __iomem *regs,
+			      uint32_t ev_mask);
+
+/*fman_dtsec_get_interrupt_mask() - Returns a bit-mask of enabled interrupts
+ *regs:	  Pointer to dTSEC register block
+ *Call this function to obtain a bit-mask of enabled interrupts
+ *in dTSEC, taken from IMASK register.
+ *Returns: a bit-mask of enabled interrupts in dTSEC.
+ */
+uint32_t fman_dtsec_get_interrupt_mask(struct dtsec_regs __iomem *regs);
+
+void fman_dtsec_enable_tmr_interrupt(struct dtsec_regs __iomem *regs);
+
+void fman_dtsec_disable_tmr_interrupt(struct dtsec_regs __iomem *regs);
+
+/*fman_dtsec_disable_interrupt() - Disables interrupts for the specified events
+ *regs:	Pointer to dTSEC register block
+ *ev_mask:	Mask of relevant events
+ *Call this function to disable interrupts in dTSEC for the specified events.
+ *To enable interrupts use fman_dtsec_enable_interrupt().
+ */
+void fman_dtsec_disable_interrupt(struct dtsec_regs __iomem *regs,
+				  uint32_t ev_mask);
+
+/*fman_dtsec_enable_interrupt() - Enable interrupts for the specified events
+ *regs:	Pointer to dTSEC register block
+ *ev_mask:	Mask of relevant events
+ *Call this function to enable interrupts in dTSEC for the specified events.
+ *To disable interrupts use fman_dtsec_disable_interrupt().
+ */
+void fman_dtsec_enable_interrupt(struct dtsec_regs __iomem *regs,
+				 uint32_t ev_mask);
+
+/*fman_dtsec_set_bucket() - Enables/disables a filter bucket
+ *regs:	  Pointer to dTSEC register block
+ *bucket: Bucket index
+ *enable: true/false to enable/disable this bucket
+ *This function enables or disables the specified bucket.  Enabling a bucket
+ *associated with an address configures dTSEC to accept received packets
+ *with that destination address.
+ *Multiple addresses may be associated with the same bucket.  Disabling a
+ *bucket will affect all addresses associated with that bucket. A bucket that
+ *is enabled requires further filtering and verification in the upper layers
+ */
+void fman_dtsec_set_bucket(struct dtsec_regs __iomem *regs, int bucket,
+			   bool enable);
+
+/*fman_dtsec_set_mc_promisc() - Set multicast promiscuous mode
+ *regs:	Pointer to dTSEC register block
+ *enable:	Enable multicast promiscuous mode
+ *Call this to enable/disable L2 address filtering for multicast packets.
+ */
+void fman_dtsec_set_mc_promisc(struct dtsec_regs __iomem *regs, bool enable);
+
+/*fman_dtsec_get_clear_carry_regs() - Read and clear carry bits
+ * (CAR1-2 registers)
+ *regs:	Pointer to dTSEC register block
+ *car1:	car1 register value
+ *car2:	car2 register value
+ *When set, the carry bits signal that an overflow occurred on the
+ *corresponding counters.
+ *Note that the carry bits (CAR1-2 registers) will assert the
+ *%DTSEC_IEVENT_MSRO interrupt if unmasked (via CAM1-2 regs).
+ *Returns: true if overflow occurred, otherwise - false
+ */
+bool fman_dtsec_get_clear_carry_regs(struct dtsec_regs __iomem *regs,
+				     uint32_t *car1, uint32_t *car2);
+
+uint32_t fman_dtsec_check_and_clear_tmr_event(struct dtsec_regs __iomem *regs);
+
+void fman_dtsec_start_tx(struct dtsec_regs __iomem *regs);
+void fman_dtsec_start_rx(struct dtsec_regs __iomem *regs);
+void fman_dtsec_stop_tx(struct dtsec_regs __iomem *regs);
+void fman_dtsec_stop_rx(struct dtsec_regs __iomem *regs);
+uint32_t fman_dtsec_get_rctrl(struct dtsec_regs __iomem *regs);
+
+#endif	/* __FSL_FMAN_DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec_mii_acc.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec_mii_acc.h
new file mode 100644
index 0000000..4425910
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec_mii_acc.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_DTSEC_MII_ACC_H
+#define __FSL_FMAN_DTSEC_MII_ACC_H
+
+#include "common/general.h"
+
+/* MII Management Configuration Register */
+#define MIIMCFG_RESET_MGMT		0x80000000
+#define MIIMCFG_MGNTCLK_MASK		0x00000007
+#define MIIMCFG_MGNTCLK_SHIFT		0
+
+/* MII	Management Command Register */
+#define MIIMCOM_SCAN_CYCLE		0x00000002
+#define MIIMCOM_READ_CYCLE		0x00000001
+
+/* MII	Management Address Register */
+#define MIIMADD_PHY_ADDR_SHIFT		8
+#define MIIMADD_PHY_ADDR_MASK		0x00001f00
+
+#define MIIMADD_REG_ADDR_SHIFT		0
+#define MIIMADD_REG_ADDR_MASK		0x0000001f
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY			0x00000001
+
+/* PHY Control Register */
+#define PHY_CR_PHY_RESET    0x8000
+#define PHY_CR_LOOPBACK	    0x4000
+#define PHY_CR_SPEED0	    0x2000
+#define PHY_CR_ANE	    0x1000
+#define PHY_CR_RESET_AN	    0x0200
+#define PHY_CR_FULLDUPLEX   0x0100
+#define PHY_CR_SPEED1	    0x0040
+
+#define PHY_TBICON_SRESET   0x8000
+#define PHY_TBICON_SPEED2   0x0020
+#define PHY_TBICON_CLK_SEL  0x0020
+#define PHY_TBIANA_SGMII    0x4001
+#define PHY_TBIANA_1000X    0x01a0
+/* register map */
+
+/* MII Configuration Control Memory Map Registers */
+struct dtsec_mii_reg {
+	uint32_t reserved1[72];
+	uint32_t miimcfg;	/* MII Mgmt:configuration */
+	uint32_t miimcom;	/* MII Mgmt:command	  */
+	uint32_t miimadd;	/* MII Mgmt:address	  */
+	uint32_t miimcon;	/* MII Mgmt:control 3	  */
+	uint32_t miimstat;	/* MII Mgmt:status	  */
+	uint32_t miimind;	/* MII Mgmt:indicators	  */
+};
+
+/* dTSEC MII API */
+
+/* functions to access the mii registers for phy configuration.
+ * this functionality may not be available for all dtsecs in the system.
+ * consult the reference manual for details
+ **/
+void fman_dtsec_mii_reset(struct dtsec_mii_reg __iomem *regs);
+/* frequency is in MHz.
+ * note that dtsec clock is 1/2 of fman clock
+ **/
+void fman_dtsec_mii_init(struct dtsec_mii_reg __iomem *regs,
+			 uint16_t dtsec_freq);
+int fman_dtsec_mii_write_reg(struct dtsec_mii_reg __iomem *regs,
+			     uint8_t addr,
+			     uint8_t reg, uint16_t data, uint16_t dtsec_freq);
+
+int fman_dtsec_mii_read_reg(struct dtsec_mii_reg __iomem *regs,
+			    uint8_t addr,
+			    uint8_t reg, uint16_t *data, uint16_t dtsec_freq);
+
+#endif	/* __FSL_FMAN_DTSEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h
new file mode 100644
index 0000000..c589025
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_MEMAC_H
+#define __FSL_FMAN_MEMAC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+/* Num of additional exact match MAC adr regs */
+#define MEMAC_NUM_OF_PADDRS 7
+
+/* Control and Configuration Register (COMMAND_CONFIG) */
+/* 00 Magic Packet detection */
+#define CMD_CFG_MG		0x80000000
+/* 07 Rx low power indication */
+#define CMD_CFG_REG_LOWP_RXETY	0x01000000
+/* 08 Tx Low Power Idle Enable */
+#define CMD_CFG_TX_LOWP_ENA	0x00800000
+/* 10 Disable SFD check */
+#define CMD_CFG_SFD_ANY		0x00200000
+/* 12 Enable PFC */
+#define CMD_CFG_PFC_MODE	0x00080000
+/* 14 Payload length check disable */
+#define CMD_CFG_NO_LEN_CHK	0x00020000
+/* 15 Force idle generation */
+#define CMD_CFG_SEND_IDLE	0x00010000
+/* 18 Control frame rx enable */
+#define CMD_CFG_CNT_FRM_EN	0x00002000
+/* 19 S/W Reset, self clearing bit */
+#define CMD_CFG_SW_RESET	0x00001000
+/* 20 Enable Tx padding of frames */
+#define CMD_CFG_TX_PAD_EN	0x00000800
+/* 21 XGMII/GMII loopback enable */
+#define CMD_CFG_LOOPBACK_EN	0x00000400
+/* 22 Tx source MAC addr insertion */
+#define CMD_CFG_TX_ADDR_INS	0x00000200
+/* 23 Ignore Pause frame quanta */
+#define CMD_CFG_PAUSE_IGNORE	0x00000100
+/* 24 Terminate/frwd Pause frames */
+#define CMD_CFG_PAUSE_FWD	0x00000080
+/* 25 Terminate/frwd CRC of frames */
+#define CMD_CFG_CRC_FWD		0x00000040
+/* 26 Frame padding removal */
+#define CMD_CFG_PAD_EN		0x00000020
+/* 27 Promiscuous operation enable */
+#define CMD_CFG_PROMIS_EN	0x00000010
+/* 28 WAN mode enable */
+#define CMD_CFG_WAN_MODE	0x00000008
+/* 30 MAC receive path enable */
+#define CMD_CFG_RX_EN		0x00000002
+/* 31 MAC transmit path enable */
+#define CMD_CFG_TX_EN		0x00000001
+
+/* Transmit FIFO Sections Register (TX_FIFO_SECTIONS) */
+#define TX_FIFO_SECTIONS_TX_EMPTY_MASK			0xFFFF0000
+#define TX_FIFO_SECTIONS_TX_AVAIL_MASK			0x0000FFFF
+#define TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G		0x00400000
+#define TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G		0x00100000
+#define TX_FIFO_SECTIONS_TX_EMPTY_PFC_10G		0x00360000
+#define TX_FIFO_SECTIONS_TX_EMPTY_PFC_1G		0x00040000
+#define TX_FIFO_SECTIONS_TX_AVAIL_10G			0x00000019
+#define TX_FIFO_SECTIONS_TX_AVAIL_1G			0x00000020
+#define TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G		0x00000060
+
+#define GET_TX_EMPTY_DEFAULT_VALUE(_val)				\
+do {									\
+	_val &= ~TX_FIFO_SECTIONS_TX_EMPTY_MASK;			\
+	((_val == TX_FIFO_SECTIONS_TX_AVAIL_10G) ?			\
+			(_val |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G) :\
+			(_val |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G));\
+} while (0)
+
+#define GET_TX_EMPTY_PFC_VALUE(_val)					\
+do {									\
+	_val &= ~TX_FIFO_SECTIONS_TX_EMPTY_MASK;			\
+	((_val == TX_FIFO_SECTIONS_TX_AVAIL_10G) ?			\
+			(_val |= TX_FIFO_SECTIONS_TX_EMPTY_PFC_10G) :	\
+			(_val |= TX_FIFO_SECTIONS_TX_EMPTY_PFC_1G));	\
+} while (0)
+
+/* Interface Mode Register (IF_MODE) */
+/* 30-31 Mask on i/f mode bits */
+#define IF_MODE_MASK		0x00000003
+/* 30-31 XGMII (10G) interface */
+#define IF_MODE_XGMII		0x00000000
+/* 30-31 GMII (1G) interface */
+#define IF_MODE_GMII		0x00000002
+#define IF_MODE_RGMII		0x00000004
+#define IF_MODE_RGMII_AUTO	0x00008000
+#define IF_MODE_RGMII_1000  0x00004000	/* 10 - 1000Mbps RGMII */
+#define IF_MODE_RGMII_100   0x00000000	/* 00 - 100Mbps RGMII */
+#define IF_MODE_RGMII_10    0x00002000	/* 01 - 10Mbps RGMII */
+#define IF_MODE_RGMII_SP_MASK 0x00006000	/* Setsp mask bits */
+#define IF_MODE_RGMII_FD    0x00001000	/* Full duplex RGMII */
+#define IF_MODE_HD	    0x00000040	/* Half duplex operation */
+
+/* Hash table Control Register (HASHTABLE_CTRL) */
+#define HASH_CTRL_MCAST_SHIFT	26
+/* 23 Mcast frame rx for hash */
+#define HASH_CTRL_MCAST_EN	0x00000100
+/* 26-31 Hash table address code */
+#define HASH_CTRL_ADDR_MASK	0x0000003F
+/* MAC mcast indication */
+#define GROUP_ADDRESS		0x0000010000000000LL
+#define HASH_TABLE_SIZE		64	/* Hash tbl size */
+
+/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */
+#define MEMAC_TX_IPG_LENGTH_MASK	0x0000003F
+
+/* Statistics Configuration Register (STATN_CONFIG) */
+#define STATS_CFG_CLR		0x00000004	/* 29 Reset all counters */
+#define STATS_CFG_CLR_ON_RD	0x00000002	/* 30 Clear on read */
+/* 31 Saturate at the maximum val */
+#define STATS_CFG_SATURATE	0x00000001
+
+/* Interrupt Mask Register (IMASK) */
+/* 1 Magic pkt detect indication */
+#define MEMAC_IMASK_MGI		0x40000000
+/* 2 Timestamp FIFO ECC error evnt */
+#define MEMAC_IMASK_TSECC_ER 0x20000000
+/* 6 Transmit frame ECC error evnt */
+#define MEMAC_IMASK_TECC_ER	0x02000000
+/* 7 Receive frame ECC error evnt */
+#define MEMAC_IMASK_RECC_ER	0x01000000
+
+#define MEMAC_ALL_ERRS_IMASK					\
+		((uint32_t)(MEMAC_IMASK_TSECC_ER	|	\
+			MEMAC_IMASK_TECC_ER		|	\
+			MEMAC_IMASK_RECC_ER		|	\
+			MEMAC_IMASK_MGI))
+
+/* PCS (XG). Link sync (G) */
+#define MEMAC_IEVNT_PCS			0x80000000
+/* Auto-negotiation */
+#define MEMAC_IEVNT_AN			0x40000000
+/* Link Training/New page */
+#define MEMAC_IEVNT_LT			0x20000000
+/* Magic pkt detection */
+#define MEMAC_IEVNT_MGI			0x00004000
+/* Timestamp FIFO ECC error */
+#define MEMAC_IEVNT_TS_ECC_ER		0x00002000
+/* Rx FIFO overflow */
+#define MEMAC_IEVNT_RX_FIFO_OVFL	0x00001000
+/* Tx FIFO underflow */
+#define MEMAC_IEVNT_TX_FIFO_UNFL	0x00000800
+/* Tx FIFO overflow */
+#define MEMAC_IEVNT_TX_FIFO_OVFL	0x00000400
+/* Tx frame ECC error */
+#define MEMAC_IEVNT_TX_ECC_ER		0x00000200
+/* Rx frame ECC error */
+#define MEMAC_IEVNT_RX_ECC_ER		0x00000100
+/* Link Interruption flt */
+#define MEMAC_IEVNT_LI_FAULT		0x00000080
+/* Rx FIFO empty */
+#define MEMAC_IEVNT_RX_EMPTY		0x00000040
+/* Tx FIFO empty */
+#define MEMAC_IEVNT_TX_EMPTY		0x00000020
+/* Low Power Idle */
+#define MEMAC_IEVNT_RX_LOWP		0x00000010
+/* Phy loss of signal */
+#define MEMAC_IEVNT_PHY_LOS		0x00000004
+/* Remote fault (XGMII) */
+#define MEMAC_IEVNT_REM_FAULT		0x00000002
+/* Local fault (XGMII) */
+#define MEMAC_IEVNT_LOC_FAULT		0x00000001
+
+#define DEFAULT_PAUSE_QUANTA	0xf000
+#define DEFAULT_FRAME_LENGTH	0x600
+#define DEFAULT_TX_IPG_LENGTH	12
+
+/**
+ * memory map
+ **/
+
+struct mac_addr {
+	/* Lower 32 bits of 48-bit MAC address */
+	uint32_t mac_addr_l;
+	/* Upper 16 bits of 48-bit MAC address */
+	uint32_t mac_addr_u;
+};
+
+struct memac_regs {
+	/* General Control and Status */
+	uint32_t res0000[2];
+	/* 0x008 Ctrl and cfg */
+	uint32_t command_config;
+	/* 0x00C-0x010 MAC_ADDR_0...1 */
+	struct mac_addr mac_addr0;
+	/* 0x014 Max frame length */
+	uint32_t maxfrm;
+	uint32_t res0018[1];
+	/* Receive FIFO configuration reg */
+	uint32_t rx_fifo_sections;
+	/* Transmit FIFO configuration reg */
+	uint32_t tx_fifo_sections;
+	uint32_t res0024[2];
+	/* 0x02C Hash table control */
+	uint32_t hashtable_ctrl;
+	uint32_t res0030[4];
+	/* 0x040 Interrupt event */
+	uint32_t ievent;
+	/* 0x044 Transmitter inter-packet-gap */
+	uint32_t tx_ipg_length;
+	uint32_t res0048;
+	/* 0x04C Interrupt mask */
+	uint32_t imask;
+	uint32_t res0050;
+	/* 0x054 Pause quanta */
+	uint32_t pause_quanta[4];
+	/* 0x064 Pause quanta threshold */
+	uint32_t pause_thresh[4];
+	/* 0x074 Receive pause status */
+	uint32_t rx_pause_status;
+	uint32_t res0078[2];
+	/* 0x80-0x0B4 mac padr */
+	struct mac_addr mac_addr[MEMAC_NUM_OF_PADDRS];
+	/* 0x0B8 Low Power Wakeup Timer */
+	uint32_t lpwake_timer;
+	/* 0x0BC Transmit EEE Low Power Timer */
+	uint32_t sleep_timer;
+	uint32_t res00c0[8];
+	/* 0x0E0 Statistics configuration */
+	uint32_t statn_config;
+	uint32_t res00e4[7];
+	/* Rx Statistics Counter */
+	uint32_t reoct_l;
+	uint32_t reoct_u;
+	uint32_t roct_l;
+	uint32_t roct_u;
+	uint32_t raln_l;
+	uint32_t raln_u;
+	uint32_t rxpf_l;
+	uint32_t rxpf_u;
+	uint32_t rfrm_l;
+	uint32_t rfrm_u;
+	uint32_t rfcs_l;
+	uint32_t rfcs_u;
+	uint32_t rvlan_l;
+	uint32_t rvlan_u;
+	uint32_t rerr_l;
+	uint32_t rerr_u;
+	uint32_t ruca_l;
+	uint32_t ruca_u;
+	uint32_t rmca_l;
+	uint32_t rmca_u;
+	uint32_t rbca_l;
+	uint32_t rbca_u;
+	uint32_t rdrp_l;
+	uint32_t rdrp_u;
+	uint32_t rpkt_l;
+	uint32_t rpkt_u;
+	uint32_t rund_l;
+	uint32_t rund_u;
+	uint32_t r64_l;
+	uint32_t r64_u;
+	uint32_t r127_l;
+	uint32_t r127_u;
+	uint32_t r255_l;
+	uint32_t r255_u;
+	uint32_t r511_l;
+	uint32_t r511_u;
+	uint32_t r1023_l;
+	uint32_t r1023_u;
+	uint32_t r1518_l;
+	uint32_t r1518_u;
+	uint32_t r1519x_l;
+	uint32_t r1519x_u;
+	uint32_t rovr_l;
+	uint32_t rovr_u;
+	uint32_t rjbr_l;
+	uint32_t rjbr_u;
+	uint32_t rfrg_l;
+	uint32_t rfrg_u;
+	uint32_t rcnp_l;
+	uint32_t rcnp_u;
+	uint32_t rdrntp_l;
+	uint32_t rdrntp_u;
+	uint32_t res01d0[12];
+	/* Tx Statistics Counter */
+	uint32_t teoct_l;
+	uint32_t teoct_u;
+	uint32_t toct_l;
+	uint32_t toct_u;
+	uint32_t res0210[2];
+	uint32_t txpf_l;
+	uint32_t txpf_u;
+	uint32_t tfrm_l;
+	uint32_t tfrm_u;
+	uint32_t tfcs_l;
+	uint32_t tfcs_u;
+	uint32_t tvlan_l;
+	uint32_t tvlan_u;
+	uint32_t terr_l;
+	uint32_t terr_u;
+	uint32_t tuca_l;
+	uint32_t tuca_u;
+	uint32_t tmca_l;
+	uint32_t tmca_u;
+	uint32_t tbca_l;
+	uint32_t tbca_u;
+	uint32_t res0258[2];
+	uint32_t tpkt_l;
+	uint32_t tpkt_u;
+	uint32_t tund_l;
+	uint32_t tund_u;
+	uint32_t t64_l;
+	uint32_t t64_u;
+	uint32_t t127_l;
+	uint32_t t127_u;
+	uint32_t t255_l;
+	uint32_t t255_u;
+	uint32_t t511_l;
+	uint32_t t511_u;
+	uint32_t t1023_l;
+	uint32_t t1023_u;
+	uint32_t t1518_l;
+	uint32_t t1518_u;
+	uint32_t t1519x_l;
+	uint32_t t1519x_u;
+	uint32_t res02a8[6];
+	uint32_t tcnp_l;
+	uint32_t tcnp_u;
+	uint32_t res02c8[14];
+	/* Line Interface Control */
+	uint32_t if_mode;	/* 0x300 Interface Mode Control */
+	uint32_t if_status;	/* 0x304 Interface Status */
+	uint32_t res0308[14];
+	/* HiGig/2 */
+	uint32_t hg_config;	/* 0x340 Control and cfg */
+	uint32_t res0344[3];
+	uint32_t hg_pause_quanta;	/* 0x350 Pause quanta */
+	uint32_t res0354[3];
+	uint32_t hg_pause_thresh;	/* 0x360 Pause quanta threshold */
+	uint32_t res0364[3];
+	uint32_t hgrx_pause_status;	/* 0x370 Receive pause status */
+	uint32_t hg_fifos_status;	/* 0x374 fifos status */
+	uint32_t rhm;		/* 0x378 rx messages counter */
+	uint32_t thm;		/* 0x37C tx messages counter */
+};
+
+struct memac_cfg {
+	bool reset_on_init;
+	bool rx_error_discard;
+	bool pause_ignore;
+	bool pause_forward_enable;
+	bool no_length_check_enable;
+	bool cmd_frame_enable;
+	bool send_idle_enable;
+	bool wan_mode_enable;
+	bool promiscuous_mode_enable;
+	bool tx_addr_ins_enable;
+	bool loopback_enable;
+	bool lgth_check_nostdr;
+	bool time_stamp_enable;
+	bool pad_enable;
+	bool phy_tx_ena_on;
+	bool rx_sfd_any;
+	bool rx_pbl_fwd;
+	bool tx_pbl_fwd;
+	bool debug_mode;
+	bool wake_on_lan;
+	uint16_t max_frame_length;
+	uint16_t pause_quanta;
+	uint32_t tx_ipg_length;
+};
+
+/**
+*fman_memac_defconfig() - Get default MEMAC configuration
+*@cfg:	  pointer to configuration structure.
+ *
+*Call this function to obtain a default set of configuration values for
+*initializing MEMAC. The user can overwrite any of the values before calling
+*fman_memac_init(), if specific configuration needs to be applied.
+ */
+void fman_memac_defconfig(struct memac_cfg *cfg);
+
+int fman_memac_init(struct memac_regs __iomem *regs,
+		    struct memac_cfg *cfg,
+		    enum enet_interface enet_interface,
+		    enum enet_speed enet_speed,
+		    bool slow_10g_if,
+		    uint32_t exceptions);
+
+void fman_memac_enable(struct memac_regs __iomem *regs, bool apply_rx,
+		       bool apply_tx);
+
+void fman_memac_disable(struct memac_regs __iomem *regs, bool apply_rx,
+			bool apply_tx);
+
+void fman_memac_set_promiscuous(struct memac_regs __iomem *regs, bool val);
+
+void fman_memac_add_addr_in_paddr(struct memac_regs __iomem *regs,
+				  uint8_t *adr, uint8_t paddr_num);
+
+void fman_memac_clear_addr_in_paddr(struct memac_regs __iomem *regs,
+				    uint8_t paddr_num);
+
+void fman_memac_set_tx_pause_frames(struct memac_regs __iomem *regs,
+				    uint8_t priority, uint16_t pause_time,
+				    uint16_t thresh_time);
+
+uint16_t fman_memac_get_max_frame_len(struct memac_regs __iomem *regs);
+
+void fman_memac_set_exception(struct memac_regs __iomem *regs, uint32_t val,
+			      bool enable);
+
+void fman_memac_reset(struct memac_regs __iomem *regs);
+
+void fman_memac_set_hash_table(struct memac_regs __iomem *regs, uint32_t val);
+
+void fman_memac_set_rx_ignore_pause_frames(struct memac_regs __iomem *regs,
+					   bool enable);
+
+uint32_t fman_memac_get_event(struct memac_regs __iomem *regs,
+			      uint32_t ev_mask);
+
+void fman_memac_ack_event(struct memac_regs __iomem *regs, uint32_t ev_mask);
+
+uint32_t fman_memac_get_interrupt_mask(struct memac_regs __iomem *regs);
+
+void fman_memac_adjust_link(struct memac_regs __iomem *regs,
+			    enum enet_interface iface_mode,
+			    enum enet_speed speed, bool full_dx);
+
+#endif	/*__FSL_FMAN_MEMAC_H*/
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac_mii_acc.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac_mii_acc.h
new file mode 100644
index 0000000..ad18d6f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac_mii_acc.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_MEMAC_MII_ACC_H
+#define __FSL_FMAN_MEMAC_MII_ACC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+/* MII Management Registers */
+#define MDIO_CFG_CLK_DIV_MASK	    0x0080ff80
+#define MDIO_CFG_HOLD_MASK	    0x0000001c
+#define MDIO_CFG_ENC45		    0x00000040
+#define MDIO_CFG_READ_ERR	    0x00000002
+#define MDIO_CFG_BSY		    0x00000001
+
+#define MDIO_CTL_PHY_ADDR_SHIFT	    5
+#define MDIO_CTL_READ		    0x00008000
+
+#define MDIO_DATA_BSY		    0x80000000
+
+/*MEMAC Internal PHY Registers - SGMII */
+#define PHY_SGMII_CR_PHY_RESET		0x8000
+#define PHY_SGMII_CR_RESET_AN		0x0200
+#define PHY_SGMII_CR_DEF_VAL		0x1140
+#define PHY_SGMII_DEV_ABILITY_SGMII	0x4001
+#define PHY_SGMII_DEV_ABILITY_1000X	0x01A0
+#define PHY_SGMII_IF_MODE_AN		0x0002
+#define PHY_SGMII_IF_MODE_SGMII		0x0001
+#define PHY_SGMII_IF_MODE_1000X		0x0000
+
+/*----------------------------------------------------*/
+/* MII Configuration Control Memory Map Registers     */
+/*----------------------------------------------------*/
+struct memac_mii_access_mem_map {
+	uint32_t mdio_cfg;	/* 0x030  */
+	uint32_t mdio_ctrl;	/* 0x034  */
+	uint32_t mdio_data;	/* 0x038  */
+	uint32_t mdio_addr;	/* 0x03c  */
+};
+
+int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map __iomem
+				*mii_regs, uint8_t phy_addr, uint8_t reg,
+				uint16_t *data, enum enet_speed enet_speed);
+int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map __iomem
+				 *mii_regs, uint8_t phy_addr, uint8_t reg,
+				 uint16_t data, enum enet_speed enet_speed);
+
+#endif	/* __MAC_API_MEMAC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_tgec.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_tgec.h
new file mode 100644
index 0000000..6f8d440
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_tgec.h
@@ -0,0 +1,409 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_TGEC_H
+#define __FSL_FMAN_TGEC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+
+/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */
+#define TGEC_TX_IPG_LENGTH_MASK	0x000003ff
+
+/* Command and Configuration Register (COMMAND_CONFIG) */
+#define CMD_CFG_EN_TIMESTAMP	0x00100000
+#define CMD_CFG_TX_ADDR_INS_SEL	0x00080000
+#define CMD_CFG_NO_LEN_CHK	0x00020000
+#define CMD_CFG_SEND_IDLE	0x00010000
+#define CMD_CFG_RX_ER_DISC	0x00004000
+#define CMD_CFG_CMD_FRM_EN	0x00002000
+#define CMD_CFG_STAT_CLR	0x00001000
+#define CMD_CFG_LOOPBACK_EN	0x00000400
+#define CMD_CFG_TX_ADDR_INS	0x00000200
+#define CMD_CFG_PAUSE_IGNORE	0x00000100
+#define CMD_CFG_PAUSE_FWD	0x00000080
+#define CMD_CFG_PROMIS_EN	0x00000010
+#define CMD_CFG_WAN_MODE	0x00000008
+#define CMD_CFG_RX_EN		0x00000002
+#define CMD_CFG_TX_EN		0x00000001
+
+/* Interrupt Mask Register (IMASK) */
+#define TGEC_IMASK_MDIO_SCAN_EVENT	0x00010000
+#define TGEC_IMASK_MDIO_CMD_CMPL	0x00008000
+#define TGEC_IMASK_REM_FAULT		0x00004000
+#define TGEC_IMASK_LOC_FAULT		0x00002000
+#define TGEC_IMASK_TX_ECC_ER		0x00001000
+#define TGEC_IMASK_TX_FIFO_UNFL		0x00000800
+#define TGEC_IMASK_TX_FIFO_OVFL		0x00000400
+#define TGEC_IMASK_TX_ER			0x00000200
+#define TGEC_IMASK_RX_FIFO_OVFL		0x00000100
+#define TGEC_IMASK_RX_ECC_ER		0x00000080
+#define TGEC_IMASK_RX_JAB_FRM		0x00000040
+#define TGEC_IMASK_RX_OVRSZ_FRM		0x00000020
+#define TGEC_IMASK_RX_RUNT_FRM		0x00000010
+#define TGEC_IMASK_RX_FRAG_FRM		0x00000008
+#define TGEC_IMASK_RX_LEN_ER		0x00000004
+#define TGEC_IMASK_RX_CRC_ER		0x00000002
+#define TGEC_IMASK_RX_ALIGN_ER		0x00000001
+
+#define TGEC_EVENTS_MASK					\
+	((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT			| \
+				TGEC_IMASK_MDIO_CMD_CMPL	| \
+				TGEC_IMASK_REM_FAULT		| \
+				TGEC_IMASK_LOC_FAULT		| \
+				TGEC_IMASK_TX_ECC_ER		| \
+				TGEC_IMASK_TX_FIFO_UNFL		| \
+				TGEC_IMASK_TX_FIFO_OVFL		| \
+				TGEC_IMASK_TX_ER		| \
+				TGEC_IMASK_RX_FIFO_OVFL		| \
+				TGEC_IMASK_RX_ECC_ER		| \
+				TGEC_IMASK_RX_JAB_FRM		| \
+				TGEC_IMASK_RX_OVRSZ_FRM		| \
+				TGEC_IMASK_RX_RUNT_FRM		| \
+				TGEC_IMASK_RX_FRAG_FRM		| \
+				TGEC_IMASK_RX_LEN_ER		| \
+				TGEC_IMASK_RX_CRC_ER		| \
+				TGEC_IMASK_RX_ALIGN_ER))
+
+/* Hashtable Control Register (HASHTABLE_CTRL) */
+#define TGEC_HASH_MCAST_SHIFT	23
+#define TGEC_HASH_MCAST_EN	0x00000200
+#define TGEC_HASH_ADR_MSK	0x000001ff
+
+#define DEFAULT_WAN_MODE_ENABLE		false
+#define DEFAULT_PROMISCUOUS_MODE_ENABLE	false
+#define DEFAULT_PAUSE_FORWARD_ENABLE	false
+#define DEFAULT_PAUSE_IGNORE		false
+#define DEFAULT_TX_ADDR_INS_ENABLE	false
+#define DEFAULT_LOOPBACK_ENABLE		false
+#define DEFAULT_CMD_FRAME_ENABLE	false
+#define DEFAULT_RX_ERROR_DISCARD	false
+#define DEFAULT_SEND_IDLE_ENABLE	false
+#define DEFAULT_NO_LENGTH_CHECK_ENABLE	true
+#define DEFAULT_LGTH_CHECK_NOSTDR	false
+#define DEFAULT_TIME_STAMP_ENABLE	false
+#define DEFAULT_TX_IPG_LENGTH		12
+#define DEFAULT_MAX_FRAME_LENGTH	0x600
+#define DEFAULT_PAUSE_QUANT		0xf000
+
+/**
+ * 10G memory map
+ **/
+struct tgec_regs {
+	uint32_t tgec_id;	/* 0x000 Controller ID */
+	uint32_t reserved001[1];	/* 0x004 */
+	uint32_t command_config;	/* 0x008 Control and configuration */
+	uint32_t mac_addr_0;	/* 0x00c Lower 32 bits of the MAC adr */
+	uint32_t mac_addr_1;	/* 0x010 Upper 16 bits of the MAC adr */
+	uint32_t maxfrm;	/* 0x014 Maximum frame length */
+	uint32_t pause_quant;	/* 0x018 Pause quanta */
+	uint32_t rx_fifo_sections;	/* 0x01c  */
+	uint32_t tx_fifo_sections;	/* 0x020  */
+	uint32_t rx_fifo_almost_f_e;	/* 0x024  */
+	uint32_t tx_fifo_almost_f_e;	/* 0x028  */
+	uint32_t hashtable_ctrl;	/* 0x02c Hash table control */
+	uint32_t mdio_cfg_status;	/* 0x030  */
+	uint32_t mdio_command;	/* 0x034  */
+	uint32_t mdio_data;	/* 0x038  */
+	uint32_t mdio_regaddr;	/* 0x03c  */
+	uint32_t status;	/* 0x040  */
+	uint32_t tx_ipg_len;	/* 0x044 Transmitter inter-packet-gap */
+	uint32_t mac_addr_2;	/* 0x048 Lower 32 bits of 2nd MAC adr */
+	uint32_t mac_addr_3;	/* 0x04c Upper 16 bits of 2nd MAC adr */
+	uint32_t rx_fifo_ptr_rd;	/* 0x050  */
+	uint32_t rx_fifo_ptr_wr;	/* 0x054  */
+	uint32_t tx_fifo_ptr_rd;	/* 0x058  */
+	uint32_t tx_fifo_ptr_wr;	/* 0x05c  */
+	uint32_t imask;		/* 0x060 Interrupt mask */
+	uint32_t ievent;	/* 0x064 Interrupt event */
+	uint32_t udp_port;	/* 0x068 Defines a UDP Port number */
+	uint32_t type_1588v2;	/* 0x06c Type field for 1588v2 */
+	uint32_t reserved070[4];	/* 0x070 */
+	/*10Ge Statistics Counter */
+	uint32_t tfrm_u;	/* 80 aFramesTransmittedOK */
+	uint32_t tfrm_l;	/* 84 aFramesTransmittedOK */
+	uint32_t rfrm_u;	/* 88 aFramesReceivedOK */
+	uint32_t rfrm_l;	/* 8c aFramesReceivedOK */
+	uint32_t rfcs_u;	/* 90 aFrameCheckSequenceErrors */
+	uint32_t rfcs_l;	/* 94 aFrameCheckSequenceErrors */
+	uint32_t raln_u;	/* 98 aAlignmentErrors */
+	uint32_t raln_l;	/* 9c aAlignmentErrors */
+	uint32_t txpf_u;	/* A0 aPAUSEMACCtrlFramesTransmitted */
+	uint32_t txpf_l;	/* A4 aPAUSEMACCtrlFramesTransmitted */
+	uint32_t rxpf_u;	/* A8 aPAUSEMACCtrlFramesReceived */
+	uint32_t rxpf_l;	/* Ac aPAUSEMACCtrlFramesReceived */
+	uint32_t rlong_u;	/* B0 aFrameTooLongErrors */
+	uint32_t rlong_l;	/* B4 aFrameTooLongErrors */
+	uint32_t rflr_u;	/* B8 aInRangeLengthErrors */
+	uint32_t rflr_l;	/* Bc aInRangeLengthErrors */
+	uint32_t tvlan_u;	/* C0 VLANTransmittedOK */
+	uint32_t tvlan_l;	/* C4 VLANTransmittedOK */
+	uint32_t rvlan_u;	/* C8 VLANReceivedOK */
+	uint32_t rvlan_l;	/* Cc VLANReceivedOK */
+	uint32_t toct_u;	/* D0 if_out_octets */
+	uint32_t toct_l;	/* D4 if_out_octets */
+	uint32_t roct_u;	/* D8 if_in_octets */
+	uint32_t roct_l;	/* Dc if_in_octets */
+	uint32_t ruca_u;	/* E0 if_in_ucast_pkts */
+	uint32_t ruca_l;	/* E4 if_in_ucast_pkts */
+	uint32_t rmca_u;	/* E8 ifInMulticastPkts */
+	uint32_t rmca_l;	/* Ec ifInMulticastPkts */
+	uint32_t rbca_u;	/* F0 ifInBroadcastPkts */
+	uint32_t rbca_l;	/* F4 ifInBroadcastPkts */
+	uint32_t terr_u;	/* F8 if_out_errors */
+	uint32_t terr_l;	/* Fc if_out_errors */
+	uint32_t reserved100[2];	/* 100-108 */
+	uint32_t tuca_u;	/* 108 if_out_ucast_pkts */
+	uint32_t tuca_l;	/* 10c if_out_ucast_pkts */
+	uint32_t tmca_u;	/* 110 ifOutMulticastPkts */
+	uint32_t tmca_l;	/* 114 ifOutMulticastPkts */
+	uint32_t tbca_u;	/* 118 ifOutBroadcastPkts */
+	uint32_t tbca_l;	/* 11c ifOutBroadcastPkts */
+	uint32_t rdrp_u;	/* 120 etherStatsDropEvents */
+	uint32_t rdrp_l;	/* 124 etherStatsDropEvents */
+	uint32_t reoct_u;	/* 128 etherStatsOctets */
+	uint32_t reoct_l;	/* 12c etherStatsOctets */
+	uint32_t rpkt_u;	/* 130 etherStatsPkts */
+	uint32_t rpkt_l;	/* 134 etherStatsPkts */
+	uint32_t trund_u;	/* 138 etherStatsUndersizePkts */
+	uint32_t trund_l;	/* 13c etherStatsUndersizePkts */
+	uint32_t r64_u;		/* 140 etherStatsPkts64Octets */
+	uint32_t r64_l;		/* 144 etherStatsPkts64Octets */
+	uint32_t r127_u;	/* 148 etherStatsPkts65to127Octets */
+	uint32_t r127_l;	/* 14c etherStatsPkts65to127Octets */
+	uint32_t r255_u;	/* 150 etherStatsPkts128to255Octets */
+	uint32_t r255_l;	/* 154 etherStatsPkts128to255Octets */
+	uint32_t r511_u;	/* 158 etherStatsPkts256to511Octets */
+	uint32_t r511_l;	/* 15c etherStatsPkts256to511Octets */
+	uint32_t r1023_u;	/* 160 etherStatsPkts512to1023Octets */
+	uint32_t r1023_l;	/* 164 etherStatsPkts512to1023Octets */
+	uint32_t r1518_u;	/* 168 etherStatsPkts1024to1518Octets */
+	uint32_t r1518_l;	/* 16c etherStatsPkts1024to1518Octets */
+	uint32_t r1519x_u;	/* 170 etherStatsPkts1519toX */
+	uint32_t r1519x_l;	/* 174 etherStatsPkts1519toX */
+	uint32_t trovr_u;	/* 178 etherStatsOversizePkts */
+	uint32_t trovr_l;	/* 17c etherStatsOversizePkts */
+	uint32_t trjbr_u;	/* 180 etherStatsJabbers */
+	uint32_t trjbr_l;	/* 184 etherStatsJabbers */
+	uint32_t trfrg_u;	/* 188 etherStatsFragments */
+	uint32_t trfrg_l;	/* 18C etherStatsFragments */
+	uint32_t rerr_u;	/* 190 if_in_errors */
+	uint32_t rerr_l;	/* 194 if_in_errors */
+};
+
+/**
+*struct tgec_cfg - TGEC configuration
+ *
+*@rx_error_discard:    Receive Erroneous Frame Discard Enable. When set to 1
+*	    any frame received with an error is discarded in the
+*	    Core and not forwarded to the Client interface.
+*	    When set to 0 (Reset value), erroneous Frames are
+*	    forwarded to the Client interface with ff_rx_err
+*	    asserted.
+*@pause_ignore:	   Ignore Pause Frame Quanta. If set to 1 received pause
+*	    frames are ignored by the MAC. When set to 0
+*	    (Reset value) the transmit process is stopped for the
+*	    amount of time specified in the pause quanta received
+*	    within a pause frame.
+*@pause_forward_enable:
+*	    Terminate / Forward Pause Frames. If set to 1 pause
+*	    frames are forwarded to the user application. When set
+*	    to 0 (Reset value) pause frames are terminated and
+*	    discarded within the MAC.
+*@no_length_check_enable:
+*	    Payload Length Check Disable. When set to 0
+*	    (Reset value), the Core checks the frame's payload
+*	    length with the Frame Length/Type field, when set to 1
+*	    the payload length check is disabled.
+*@cmd_frame_enable:    Enables reception of all command frames. When set to 1
+*	    all Command Frames are accepted, when set to 0
+*	    (Reset Value) only Pause Frames are accepted and all
+*	    other Command Frames are rejected.
+*@send_idle_enable:    Force Idle Generation. When set to 1, the MAC
+*	    permanently sends XGMII Idle sequences even when faults
+*	    are received.
+*@wan_mode_enable:    WAN Mode Enable. Sets WAN mode (1) or LAN mode
+*	    (0, default) of operation.
+*@promiscuous_mode_enable:
+*	    Enables MAC promiscuous operation. When set to 1, all
+*	    frames are received without any MAC address filtering,
+*	    when set to 0 (Reset value) Unicast Frames with a
+*	    destination address not matching the Core MAC Address
+*	    (MAC Address programmed in Registers MAC_ADDR_0 and
+*	    MAC_ADDR_1 or the MAC address programmed in Registers
+*	    MAC_ADDR_2 and MAC_ADDR_3) are rejected.
+*@tx_addr_ins_enable:	 Set Source MAC Address on Transmit. If set to 1 the
+*	    MAC overwrites the source MAC address received from the
+*	    Client Interface with one of the MAC addresses. If set
+*	    to 0 (Reset value), the source MAC address from the
+*	    Client Interface is transmitted unmodified to the line.
+*@loopback_enable:    PHY Interface Loopback. When set to 1, the signal
+*	    loop_ena is set to '1', when set to 0 (Reset value)
+*	    the signal loop_ena is set to 0.
+*@lgth_check_nostdr:	The Core interprets the Length/Type field differently
+*	    depending on the value of this Bit
+*@time_stamp_enable:	This bit selects between enabling and disabling the
+*	    IEEE 1588 functionality. 1: IEEE 1588 is enabled
+*	    0: IEEE 1588 is disabled
+*@max_frame_length:    Maximum supported received frame length.
+*	    The 10GEC MAC supports reception of any frame size up
+*	    to 16,352 bytes (0x3FE0). Typical settings are
+*	    0x05EE (1,518 bytes) for standard frames.
+*	    Default setting is 0x0600 (1,536 bytes).
+*	    Received frames that exceed this stated maximum
+*	    are truncated.
+*@pause_quant:	  Pause quanta value used with transmitted pause frames.
+*	    Each quanta represents a 512 bit-times.
+*@tx_ipg_length:    Transmit Inter-Packet-Gap (IPG) value. A 6-bit value:
+*	    Depending on LAN or WAN mode of operation the value has
+*	    the following meaning: - LAN Mode: Number of octets in
+*	    steps of 4. Valid values are 8, 12, 16, ... 100. DIC is
+*	    fully supported (see 10.6.1 page 49) for any setting. A
+*	    default of 12 (reset value) must be set to conform to
+*	    IEEE802.3ae. Warning: When set to 8, PCS layers may not
+*	    be able to perform clock rate compensation. - WAN Mode:
+*	    Stretch factor. Valid values are 4..15. The stretch
+*	    factor is calculated as (value+1)*8. A default of 12
+*	    (reset value) must be set to conform to IEEE 802.3ae
+*	    (i.e. 13*8=104). A larger value shrinks the IPG
+*	    (increasing bandwidth).
+ *
+*This structure contains basic TGEC configuration and must be passed to
+*fman_tgec_init() function.  A default set of configuration values can be
+*obtained by calling fman_tgec_defconfig().
+ */
+struct tgec_cfg {
+	bool rx_error_discard;
+	bool pause_ignore;
+	bool pause_forward_enable;
+	bool no_length_check_enable;
+	bool cmd_frame_enable;
+	bool send_idle_enable;
+	bool wan_mode_enable;
+	bool promiscuous_mode_enable;
+	bool tx_addr_ins_enable;
+	bool loopback_enable;
+	bool lgth_check_nostdr;
+	bool time_stamp_enable;
+	uint16_t max_frame_length;
+	uint16_t pause_quant;
+	uint32_t tx_ipg_length;
+	bool skip_fman11_workaround;
+};
+
+void fman_tgec_defconfig(struct tgec_cfg *cfg);
+
+/**
+*fman_tgec_init() - Init tgec hardware block
+*@regs:	       Pointer to tgec register block
+*@cfg:	      tgec configuration data
+*@exceptions_mask:    initial exceptions mask
+ *
+*This function initializes the tgec controller and applies its
+*basic configuration.
+ *
+*Returns: 0 if successful, an error code otherwise.
+ */
+
+int fman_tgec_init(struct tgec_regs __iomem *regs, struct tgec_cfg *cfg,
+		   uint32_t exception_mask);
+
+void fman_tgec_enable(struct tgec_regs __iomem *regs, bool apply_rx,
+		      bool apply_tx);
+
+void fman_tgec_disable(struct tgec_regs __iomem *regs, bool apply_rx,
+		       bool apply_tx);
+
+uint32_t fman_tgec_get_revision(struct tgec_regs __iomem *regs);
+
+void fman_tgec_set_mac_address(struct tgec_regs __iomem *regs,
+			       uint8_t *macaddr);
+
+void fman_tgec_set_promiscuous(struct tgec_regs __iomem *regs, bool val);
+
+/**
+*fman_tgec_set_hash_table() - Sets the Hashtable Control Register
+*@regs:	   Pointer to TGEC register block
+*@value:    Value to be written in Hashtable Control Register
+ */
+void fman_tgec_set_hash_table(struct tgec_regs __iomem *regs, uint32_t value);
+
+/**
+*fman_tgec_set_tx_pause_frames() - Sets the Pause Quanta Register
+*@regs:	   Pointer to TGEC register block
+*@pause_time:	 Pause quanta value used with transmitted pause frames.
+*	Each quanta represents a 512 bit-times
+ */
+void fman_tgec_set_tx_pause_frames(struct tgec_regs __iomem *regs,
+				   uint16_t pause_time);
+
+/**
+*fman_tgec_set_rx_ignore_pause_frames() - Changes the policy WRT pause frames
+*@regs:	   Pointer to TGEC register block
+*@en:	     Ignore/Respond to pause frame quanta
+ *
+*Sets the value of PAUSE_IGNORE field in the COMMAND_CONFIG Register
+*0 - MAC stops transmit process for the duration specified
+*in the Pause frame quanta of a received Pause frame.
+*1 - MAC ignores received Pause frames.
+ */
+void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs __iomem *regs,
+					  bool en);
+
+uint32_t fman_tgec_get_event(struct tgec_regs __iomem *regs, uint32_t ev_mask);
+
+void fman_tgec_ack_event(struct tgec_regs __iomem *regs, uint32_t ev_mask);
+
+uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs __iomem *regs);
+
+void fman_tgec_enable_interrupt(struct tgec_regs __iomem *regs,
+				uint32_t ev_mask);
+
+void fman_tgec_disable_interrupt(struct tgec_regs __iomem *regs,
+				 uint32_t ev_mask);
+
+/**
+*fman_tgec_get_max_frame_len() - Returns the maximum frame length value
+*@regs:	   Pointer to TGEC register block
+ */
+uint16_t fman_tgec_get_max_frame_len(struct tgec_regs __iomem *regs);
+
+/**
+*fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007() - Initialize the
+*main tgec configuration parameters
+*@regs:	   Pointer to TGEC register block
+ *
+*TODO
+ */
+void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs
+							  __iomem *regs);
+
+#endif	/* __FSL_FMAN_TGEC_H */
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 06/12] fsl/fman: Add the FMan MAC FLIB
  2015-05-07 13:05       ` [RFC,v3 05/12] fsl/fman: Add the FMan MAC FLIB headers Madalin Bucur
@ 2015-05-07 13:05         ` Madalin Bucur
  2015-05-07 13:05           ` [RFC,v3 07/12] fsl/fman: Add FMan MURAM support Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

The FMan MAC FLib provides basic API used by the drivers to
configure and control the FMan MAC hardware.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 drivers/net/ethernet/freescale/fman/Makefile       |   1 +
 drivers/net/ethernet/freescale/fman/mac/Makefile   |   5 +
 .../net/ethernet/freescale/fman/mac/fman_crc32.c   | 116 +++++
 .../net/ethernet/freescale/fman/mac/fman_crc32.h   |  39 ++
 .../net/ethernet/freescale/fman/mac/fman_dtsec.c   | 571 +++++++++++++++++++++
 .../freescale/fman/mac/fman_dtsec_mii_acc.c        | 168 ++++++
 .../net/ethernet/freescale/fman/mac/fman_memac.c   | 365 +++++++++++++
 .../freescale/fman/mac/fman_memac_mii_acc.c        | 217 ++++++++
 .../net/ethernet/freescale/fman/mac/fman_tgec.c    | 217 ++++++++
 9 files changed, 1699 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/Makefile
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_crc32.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_crc32.h
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_memac.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_tgec.c

diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index a9ae0aa..534d1ed 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -5,3 +5,4 @@ obj-y		+= fsl_fman.o
 fsl_fman-objs			:= fman.o
 
 obj-y	+= port/
+obj-y	+= mac/
diff --git a/drivers/net/ethernet/freescale/fman/mac/Makefile b/drivers/net/ethernet/freescale/fman/mac/Makefile
new file mode 100644
index 0000000..80b7048
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_FSL_FMAN_MAC)	+= fsl_fman_mac.o
+
+fsl_fman_mac-objs		:= fman_dtsec.o fman_dtsec_mii_acc.o	\
+				   fman_memac.o fman_tgec.o		\
+				   fman_crc32.o fman_memac_mii_acc.o
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_crc32.c b/drivers/net/ethernet/freescale/fman/mac/fman_crc32.c
new file mode 100644
index 0000000..1536d12
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_crc32.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fman_crc32.h"
+#include "common/general.h"
+
+/* precomputed CRC values for address hashing */
+static const uint32_t crc_tbl[256] = {
+	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+	0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+	0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+	0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+/* Get the mirrored value of a byte size number. (0x11010011 --> 0x11001011) */
+static inline uint8_t get_mirror8(uint8_t n)
+{
+	uint8_t mirror[16] = {
+		0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
+		0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
+	};
+	return (uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4])));
+}
+
+static inline uint32_t get_mirror32(uint32_t n)
+{
+	return ((uint32_t)get_mirror8((uint8_t)(n)) << 24) |
+	    ((uint32_t)get_mirror8((uint8_t)(n >> 8)) << 16) |
+	    ((uint32_t)get_mirror8((uint8_t)(n >> 16)) << 8) |
+	    ((uint32_t)get_mirror8((uint8_t)(n >> 24)));
+}
+
+uint32_t get_mac_addr_crc(uint64_t _addr)
+{
+	uint32_t i;
+	uint8_t data;
+	uint32_t crc;
+
+	/* CRC calculation */
+	crc = 0xffffffff;
+	for (i = 0; i < 6; i++) {
+		data = (uint8_t)(_addr >> ((5 - i) * 8));
+		crc = crc ^ data;
+		crc = crc_tbl[crc & 0xff] ^ (crc >> 8);
+	}
+
+	crc = get_mirror32(crc);
+	return crc;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_crc32.h b/drivers/net/ethernet/freescale/fman/mac/fman_crc32.h
new file mode 100644
index 0000000..eac30f3
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_crc32.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FMAN_CRC32_H
+#define __FMAN_CRC32_H
+
+#include "common/general.h"
+
+uint32_t get_mac_addr_crc(uint64_t _addr);
+
+#endif	/* __FMAN_CRC32_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c
new file mode 100644
index 0000000..290a037
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c
@@ -0,0 +1,571 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_fman_dtsec.h"
+
+void fman_dtsec_stop_rx(struct dtsec_regs __iomem *regs)
+{
+	/* Assert the graceful stop bit */
+	iowrite32be(ioread32be(&regs->rctrl) | RCTRL_GRS, &regs->rctrl);
+}
+
+void fman_dtsec_stop_tx(struct dtsec_regs __iomem *regs)
+{
+	/* Assert the graceful stop bit */
+	iowrite32be(ioread32be(&regs->tctrl) | DTSEC_TCTRL_GTS, &regs->tctrl);
+}
+
+void fman_dtsec_start_tx(struct dtsec_regs __iomem *regs)
+{
+	/* clear the graceful stop bit */
+	iowrite32be(ioread32be(&regs->tctrl) & ~DTSEC_TCTRL_GTS, &regs->tctrl);
+}
+
+void fman_dtsec_start_rx(struct dtsec_regs __iomem *regs)
+{
+	/* clear the graceful stop bit */
+	iowrite32be(ioread32be(&regs->rctrl) & ~RCTRL_GRS, &regs->rctrl);
+}
+
+void fman_dtsec_defconfig(struct dtsec_cfg *cfg)
+{
+	cfg->halfdup_on = DEFAULT_HALFDUP_ON;
+	cfg->halfdup_retransmit = DEFAULT_HALFDUP_RETRANSMIT;
+	cfg->halfdup_coll_window = DEFAULT_HALFDUP_COLL_WINDOW;
+	cfg->halfdup_excess_defer = DEFAULT_HALFDUP_EXCESS_DEFER;
+	cfg->halfdup_no_backoff = DEFAULT_HALFDUP_NO_BACKOFF;
+	cfg->halfdup_bp_no_backoff = DEFAULT_HALFDUP_BP_NO_BACKOFF;
+	cfg->halfdup_alt_backoff_val = DEFAULT_HALFDUP_ALT_BACKOFF_VAL;
+	cfg->halfdup_alt_backoff_en = DEFAULT_HALFDUP_ALT_BACKOFF_EN;
+	cfg->rx_drop_bcast = DEFAULT_RX_DROP_BCAST;
+	cfg->rx_short_frm = DEFAULT_RX_SHORT_FRM;
+	cfg->rx_len_check = DEFAULT_RX_LEN_CHECK;
+	cfg->tx_pad_crc = DEFAULT_TX_PAD_CRC;
+	cfg->tx_crc = DEFAULT_TX_CRC;
+	cfg->rx_ctrl_acc = DEFAULT_RX_CTRL_ACC;
+	cfg->tx_pause_time = DEFAULT_TX_PAUSE_TIME;
+	/* PHY address 0 is reserved (DPAA RM) */
+	cfg->tbipa = DEFAULT_TBIPA;
+	cfg->rx_prepend = DEFAULT_RX_PREPEND;
+	cfg->ptp_tsu_en = DEFAULT_PTP_TSU_EN;
+	cfg->ptp_exception_en = DEFAULT_PTP_EXCEPTION_EN;
+	cfg->preamble_len = DEFAULT_PREAMBLE_LEN;
+	cfg->rx_preamble = DEFAULT_RX_PREAMBLE;
+	cfg->tx_preamble = DEFAULT_TX_PREAMBLE;
+	cfg->loopback = DEFAULT_LOOPBACK;
+	cfg->rx_time_stamp_en = DEFAULT_RX_TIME_STAMP_EN;
+	cfg->tx_time_stamp_en = DEFAULT_TX_TIME_STAMP_EN;
+	cfg->rx_flow = DEFAULT_RX_FLOW;
+	cfg->tx_flow = DEFAULT_TX_FLOW;
+	cfg->rx_group_hash_exd = DEFAULT_RX_GROUP_HASH_EXD;
+	cfg->tx_pause_time_extd = DEFAULT_TX_PAUSE_TIME_EXTD;
+	cfg->rx_promisc = DEFAULT_RX_PROMISC;
+	cfg->non_back_to_back_ipg1 = DEFAULT_NON_BACK_TO_BACK_IPG1;
+	cfg->non_back_to_back_ipg2 = DEFAULT_NON_BACK_TO_BACK_IPG2;
+	cfg->min_ifg_enforcement = DEFAULT_MIN_IFG_ENFORCEMENT;
+	cfg->back_to_back_ipg = DEFAULT_BACK_TO_BACK_IPG;
+	cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME;
+	cfg->tbi_phy_addr = DEFAULT_TBI_PHY_ADDR;
+	cfg->wake_on_lan = DEFAULT_WAKE_ON_LAN;
+}
+
+int fman_dtsec_init(struct dtsec_regs __iomem *regs, struct dtsec_cfg *cfg,
+		    enum enet_interface iface_mode,
+		    enum enet_speed iface_speed,
+		    uint8_t *macaddr,
+		    uint8_t __maybe_unused fm_rev_maj,
+		    uint8_t __maybe_unused fm_rev_min, uint32_t exception_mask)
+{
+	bool is_rgmii, is_sgmii, is_qsgmii;
+	int i;
+	uint32_t tmp;
+
+	/* let's start with a soft reset */
+	iowrite32be(MACCFG1_SOFT_RESET, &regs->maccfg1);
+	iowrite32be(0, &regs->maccfg1);
+
+	/*dtsec_id2*/
+	tmp = ioread32be(&regs->tsec_id2);
+
+	/* check RGMII support */
+	if (iface_mode == E_ENET_IF_RGMII || iface_mode == E_ENET_IF_RMII)
+		if (tmp & DTSEC_ID2_INT_REDUCED_OFF)
+			return -EINVAL;
+
+	if (iface_mode == E_ENET_IF_SGMII || iface_mode == E_ENET_IF_MII)
+		if (tmp & DTSEC_ID2_INT_REDUCED_OFF)
+			return -EINVAL;
+
+	/*ECNTRL*/
+
+	is_rgmii = (bool)((iface_mode == E_ENET_IF_RGMII) ? true : false);
+	is_sgmii = (bool)((iface_mode == E_ENET_IF_SGMII) ? true : false);
+	is_qsgmii = (bool)((iface_mode == E_ENET_IF_QSGMII) ? true : false);
+
+	tmp = 0;
+	if (is_rgmii || iface_mode == E_ENET_IF_GMII)
+		tmp |= DTSEC_ECNTRL_GMIIM;
+	if (is_sgmii)
+		tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM);
+	if (is_qsgmii)
+		tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM |
+			DTSEC_ECNTRL_QSGMIIM);
+	if (is_rgmii)
+		tmp |= DTSEC_ECNTRL_RPM;
+	if (iface_speed == E_ENET_SPEED_100)
+		tmp |= DTSEC_ECNTRL_R100M;
+
+	iowrite32be(tmp, &regs->ecntrl);
+	/*ECNTRL*/
+
+	/*TCTRL*/
+	tmp = 0;
+	if (cfg->halfdup_on)
+		tmp |= DTSEC_TCTRL_THDF;
+	if (cfg->tx_time_stamp_en)
+		tmp |= DTSEC_TCTRL_TTSE;
+
+	iowrite32be(tmp, &regs->tctrl);
+
+	/*TCTRL*/
+
+	/*PTV*/
+	tmp = 0;
+
+#ifdef FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1
+	if ((fm_rev_maj == 1) && (fm_rev_min == 0))
+		cfg->tx_pause_time += 2;
+#endif /* FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 */
+
+	if (cfg->tx_pause_time)
+		tmp |= cfg->tx_pause_time;
+	if (cfg->tx_pause_time_extd)
+		tmp |= cfg->tx_pause_time_extd << PTV_PTE_OFST;
+	iowrite32be(tmp, &regs->ptv);
+
+	/*RCTRL*/
+	tmp = 0;
+	tmp |= ((uint32_t)(cfg->rx_prepend & 0x0000001f)) << 16;
+	if (cfg->rx_ctrl_acc)
+		tmp |= RCTRL_CFA;
+	if (cfg->rx_group_hash_exd)
+		tmp |= RCTRL_GHTX;
+	if (cfg->rx_time_stamp_en)
+		tmp |= RCTRL_RTSE;
+	if (cfg->rx_drop_bcast)
+		tmp |= RCTRL_BC_REJ;
+	if (cfg->rx_short_frm)
+		tmp |= RCTRL_RSF;
+	if (cfg->rx_promisc)
+		tmp |= RCTRL_PROM;
+
+	iowrite32be(tmp, &regs->rctrl);
+	/*RCTRL*/
+
+	/*Assign a Phy Address to the TBI (TBIPA).
+	 *Done also in cases where TBI is not selected to avoid conflict with
+	 *the external PHY's Physical address
+	 */
+	iowrite32be(cfg->tbipa, &regs->tbipa);
+
+	/*TMR_CTL*/
+	iowrite32be(0, &regs->tmr_ctrl);
+
+	if (cfg->ptp_tsu_en) {
+		tmp = 0;
+		tmp |= TMR_PEVENT_TSRE;
+		iowrite32be(tmp, &regs->tmr_pevent);
+
+		if (cfg->ptp_exception_en) {
+			tmp = 0;
+			tmp |= TMR_PEMASK_TSREEN;
+			iowrite32be(tmp, &regs->tmr_pemask);
+		}
+	}
+
+	/*MACCFG1*/
+	tmp = 0;
+	if (cfg->loopback)
+		tmp |= MACCFG1_LOOPBACK;
+	if (cfg->rx_flow)
+		tmp |= MACCFG1_RX_FLOW;
+	if (cfg->tx_flow)
+		tmp |= MACCFG1_TX_FLOW;
+	iowrite32be(tmp, &regs->maccfg1);
+
+	/*MACCFG1*/
+
+	/*MACCFG2*/
+	tmp = 0;
+
+	if (iface_speed < E_ENET_SPEED_1000)
+		tmp |= MACCFG2_NIBBLE_MODE;
+	else if (iface_speed == E_ENET_SPEED_1000)
+		tmp |= MACCFG2_BYTE_MODE;
+
+	tmp |= ((uint32_t)cfg->preamble_len & 0x0000000f)
+	    << PREAMBLE_LENGTH_SHIFT;
+
+	if (cfg->rx_preamble)
+		tmp |= MACCFG2_PRE_AM_RX_EN;
+	if (cfg->tx_preamble)
+		tmp |= MACCFG2_PRE_AM_TX_EN;
+	if (cfg->rx_len_check)
+		tmp |= MACCFG2_LENGTH_CHECK;
+	if (cfg->tx_pad_crc)
+		tmp |= MACCFG2_PAD_CRC_EN;
+	if (cfg->tx_crc)
+		tmp |= MACCFG2_CRC_EN;
+	if (!cfg->halfdup_on)
+		tmp |= MACCFG2_FULL_DUPLEX;
+	iowrite32be(tmp, &regs->maccfg2);
+
+	/*MACCFG2*/
+
+	/*IPGIFG*/
+	tmp = (((cfg->non_back_to_back_ipg1 <<
+		 IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT)
+		& IPGIFG_NON_BACK_TO_BACK_IPG_1)
+	       | ((cfg->non_back_to_back_ipg2 <<
+		   IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT)
+		 & IPGIFG_NON_BACK_TO_BACK_IPG_2)
+	       | ((cfg->min_ifg_enforcement << IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT)
+		 & IPGIFG_MIN_IFG_ENFORCEMENT)
+	       | (cfg->back_to_back_ipg & IPGIFG_BACK_TO_BACK_IPG));
+	iowrite32be(tmp, &regs->ipgifg);
+
+	/*IPGIFG*/
+
+	/*HAFDUP*/
+	tmp = 0;
+
+	if (cfg->halfdup_alt_backoff_en)
+		tmp = (uint32_t)(HAFDUP_ALT_BEB |
+				  ((cfg->halfdup_alt_backoff_val & 0x0000000f)
+				   << HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT));
+	if (cfg->halfdup_bp_no_backoff)
+		tmp |= HAFDUP_BP_NO_BACKOFF;
+	if (cfg->halfdup_no_backoff)
+		tmp |= HAFDUP_NO_BACKOFF;
+	if (cfg->halfdup_excess_defer)
+		tmp |= HAFDUP_EXCESS_DEFER;
+	tmp |= ((cfg->halfdup_retransmit << HAFDUP_RETRANSMISSION_MAX_SHIFT)
+		& HAFDUP_RETRANSMISSION_MAX);
+	tmp |= (cfg->halfdup_coll_window & HAFDUP_COLLISION_WINDOW);
+
+	iowrite32be(tmp, &regs->hafdup);
+	/*HAFDUP*/
+
+	/*MAXFRM*/
+	/* Initialize MAXFRM */
+	iowrite32be(cfg->maximum_frame, &regs->maxfrm);
+
+	/*MAXFRM*/
+
+	/*CAM1*/
+	iowrite32be(0xffffffff, &regs->cam1);
+	iowrite32be(0xffffffff, &regs->cam2);
+
+	/*IMASK*/
+	iowrite32be(exception_mask, &regs->imask);
+	/*IMASK*/
+
+	/*IEVENT*/
+	iowrite32be(0xffffffff, &regs->ievent);
+
+	/*MACSTNADDR1/2*/
+
+	tmp = (uint32_t)((macaddr[5] << 24) |
+			  (macaddr[4] << 16) | (macaddr[3] << 8) | macaddr[2]);
+	iowrite32be(tmp, &regs->macstnaddr1);
+
+	tmp = (uint32_t)((macaddr[1] << 24) | (macaddr[0] << 16));
+	iowrite32be(tmp, &regs->macstnaddr2);
+
+	/*MACSTNADDR1/2*/
+
+	/*HASH*/
+	for (i = 0; i < NUM_OF_HASH_REGS; i++) {
+		/* Initialize IADDRx */
+		iowrite32be(0, &regs->igaddr[i]);
+		/* Initialize GADDRx */
+		iowrite32be(0, &regs->gaddr[i]);
+	}
+
+	return 0;
+}
+
+uint16_t fman_dtsec_get_max_frame_len(struct dtsec_regs __iomem *regs)
+{
+	return (uint16_t)ioread32be(&regs->maxfrm);
+}
+
+void fman_dtsec_set_max_frame_len(struct dtsec_regs __iomem *regs,
+				  uint16_t length)
+{
+	iowrite32be(length, &regs->maxfrm);
+}
+
+void fman_dtsec_set_mac_address(struct dtsec_regs __iomem *regs, uint8_t *adr)
+{
+	uint32_t tmp;
+
+	tmp = (uint32_t)((adr[5] << 24) |
+			  (adr[4] << 16) | (adr[3] << 8) | adr[2]);
+	iowrite32be(tmp, &regs->macstnaddr1);
+
+	tmp = (uint32_t)((adr[1] << 24) | (adr[0] << 16));
+	iowrite32be(tmp, &regs->macstnaddr2);
+}
+
+void fman_dtsec_get_mac_address(struct dtsec_regs __iomem *regs,
+				uint8_t *macaddr)
+{
+	uint32_t tmp1, tmp2;
+
+	tmp1 = ioread32be(&regs->macstnaddr1);
+	tmp2 = ioread32be(&regs->macstnaddr2);
+
+	macaddr[0] = (uint8_t)((tmp2 & 0x00ff0000) >> 16);
+	macaddr[1] = (uint8_t)((tmp2 & 0xff000000) >> 24);
+	macaddr[2] = (uint8_t)(tmp1 & 0x000000ff);
+	macaddr[3] = (uint8_t)((tmp1 & 0x0000ff00) >> 8);
+	macaddr[4] = (uint8_t)((tmp1 & 0x00ff0000) >> 16);
+	macaddr[5] = (uint8_t)((tmp1 & 0xff000000) >> 24);
+}
+
+void fman_dtsec_set_bucket(struct dtsec_regs __iomem *regs, int bucket,
+			   bool enable)
+{
+	int reg_idx = (bucket >> 5) & 0xf;
+	int bit_idx = bucket & 0x1f;
+	uint32_t bit_mask = 0x80000000 >> bit_idx;
+	uint32_t __iomem *reg;
+
+	if (reg_idx > 7)
+		reg = &regs->gaddr[reg_idx - 8];
+	else
+		reg = &regs->igaddr[reg_idx];
+
+	if (enable)
+		iowrite32be(ioread32be(reg) | bit_mask, reg);
+	else
+		iowrite32be(ioread32be(reg) & (~bit_mask), reg);
+}
+
+int fman_dtsec_adjust_link(struct dtsec_regs __iomem *regs,
+			   enum enet_interface __maybe_unused iface_mode,
+			   enum enet_speed speed, bool full_dx)
+{
+	uint32_t tmp;
+
+	if ((speed == E_ENET_SPEED_1000) && !full_dx)
+		return -EINVAL;
+
+	tmp = ioread32be(&regs->maccfg2);
+	if (!full_dx)
+		tmp &= ~MACCFG2_FULL_DUPLEX;
+	else
+		tmp |= MACCFG2_FULL_DUPLEX;
+
+	tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE);
+	if (speed < E_ENET_SPEED_1000)
+		tmp |= MACCFG2_NIBBLE_MODE;
+	else if (speed == E_ENET_SPEED_1000)
+		tmp |= MACCFG2_BYTE_MODE;
+	iowrite32be(tmp, &regs->maccfg2);
+
+	tmp = ioread32be(&regs->ecntrl);
+	if (speed == E_ENET_SPEED_100)
+		tmp |= DTSEC_ECNTRL_R100M;
+	else
+		tmp &= ~DTSEC_ECNTRL_R100M;
+	iowrite32be(tmp, &regs->ecntrl);
+
+	return 0;
+}
+
+void fman_dtsec_set_uc_promisc(struct dtsec_regs __iomem *regs, bool enable)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->rctrl);
+
+	if (enable)
+		tmp |= RCTRL_UPROM;
+	else
+		tmp &= ~RCTRL_UPROM;
+
+	iowrite32be(tmp, &regs->rctrl);
+}
+
+void fman_dtsec_set_mc_promisc(struct dtsec_regs __iomem *regs, bool enable)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->rctrl);
+
+	if (enable)
+		tmp |= RCTRL_MPROM;
+	else
+		tmp &= ~RCTRL_MPROM;
+
+	iowrite32be(tmp, &regs->rctrl);
+}
+
+void fman_dtsec_enable(struct dtsec_regs __iomem *regs, bool apply_rx,
+		       bool apply_tx)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->maccfg1);
+
+	if (apply_rx)
+		tmp |= MACCFG1_RX_EN;
+
+	if (apply_tx)
+		tmp |= MACCFG1_TX_EN;
+
+	iowrite32be(tmp, &regs->maccfg1);
+}
+
+void fman_dtsec_disable(struct dtsec_regs __iomem *regs, bool apply_rx,
+			bool apply_tx)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->maccfg1);
+
+	if (apply_rx)
+		tmp &= ~MACCFG1_RX_EN;
+
+	if (apply_tx)
+		tmp &= ~MACCFG1_TX_EN;
+
+	iowrite32be(tmp, &regs->maccfg1);
+}
+
+void fman_dtsec_set_tx_pause_frames(struct dtsec_regs __iomem *regs,
+				    uint16_t time)
+{
+	uint32_t ptv = 0;
+
+	/* fixme: don't enable tx pause for half-duplex */
+
+	if (time) {
+		ptv = ioread32be(&regs->ptv);
+		ptv &= 0xffff0000;
+		ptv |= time & 0x0000ffff;
+		iowrite32be(ptv, &regs->ptv);
+
+		/* trigger the transmission of a flow-control pause frame */
+		iowrite32be(ioread32be(&regs->maccfg1) | MACCFG1_TX_FLOW,
+			    &regs->maccfg1);
+	} else
+		iowrite32be(ioread32be(&regs->maccfg1) & ~MACCFG1_TX_FLOW,
+			    &regs->maccfg1);
+}
+
+void fman_dtsec_handle_rx_pause(struct dtsec_regs __iomem *regs, bool en)
+{
+	uint32_t tmp;
+
+	/* todo: check if mac is set to full-duplex */
+
+	tmp = ioread32be(&regs->maccfg1);
+	if (en)
+		tmp |= MACCFG1_RX_FLOW;
+	else
+		tmp &= ~MACCFG1_RX_FLOW;
+	iowrite32be(tmp, &regs->maccfg1);
+}
+
+uint32_t fman_dtsec_get_rctrl(struct dtsec_regs __iomem *regs)
+{
+	return ioread32be(&regs->rctrl);
+}
+
+uint32_t fman_dtsec_get_revision(struct dtsec_regs __iomem *regs)
+{
+	return ioread32be(&regs->tsec_id);
+}
+
+uint32_t fman_dtsec_get_event(struct dtsec_regs __iomem *regs,
+			      uint32_t ev_mask)
+{
+	return ioread32be(&regs->ievent) & ev_mask;
+}
+
+void fman_dtsec_ack_event(struct dtsec_regs __iomem *regs, uint32_t ev_mask)
+{
+	iowrite32be(ev_mask, &regs->ievent);
+}
+
+uint32_t fman_dtsec_get_interrupt_mask(struct dtsec_regs __iomem *regs)
+{
+	return ioread32be(&regs->imask);
+}
+
+uint32_t fman_dtsec_check_and_clear_tmr_event(struct dtsec_regs __iomem *regs)
+{
+	uint32_t event;
+
+	event = ioread32be(&regs->tmr_pevent);
+	event &= ioread32be(&regs->tmr_pemask);
+
+	if (event)
+		iowrite32be(event, &regs->tmr_pevent);
+	return event;
+}
+
+void fman_dtsec_enable_tmr_interrupt(struct dtsec_regs __iomem *regs)
+{
+	iowrite32be(ioread32be(&regs->tmr_pemask) | TMR_PEMASK_TSREEN,
+		    &regs->tmr_pemask);
+}
+
+void fman_dtsec_disable_tmr_interrupt(struct dtsec_regs __iomem *regs)
+{
+	iowrite32be(ioread32be(&regs->tmr_pemask) & ~TMR_PEMASK_TSREEN,
+		    &regs->tmr_pemask);
+}
+
+void fman_dtsec_enable_interrupt(struct dtsec_regs __iomem *regs,
+				 uint32_t ev_mask)
+{
+	iowrite32be(ioread32be(&regs->imask) | ev_mask, &regs->imask);
+}
+
+void fman_dtsec_disable_interrupt(struct dtsec_regs __iomem *regs,
+				  uint32_t ev_mask)
+{
+	iowrite32be(ioread32be(&regs->imask) & ~ev_mask, &regs->imask);
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c
new file mode 100644
index 0000000..c393938
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "common/general.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+/*dtsec_mii_get_div() - calculates the value of the dtsec mii divider
+ *@dtsec_freq:		dtsec clock frequency (in Mhz)
+ *This function calculates the dtsec mii clock divider that determines
+ *the MII MDC clock. MII MDC clock will be set to work in the range
+ *of 1.5 to 2.5Mhz
+ *The output of this function is the value of MIIMCFG[MgmtClk] which
+ *implicitly determines the divider value.
+ *Note: the dTSEC system clock is equal to 1/2 of the FMan clock.
+ *The table below which reflects dtsec_mii_get_div() functionality
+ *shows the relations among dtsec_freq, MgmtClk, actual divider
+ *and the MII frequency:
+ *dtsec freq   MgmtClk	   div	      MII freq Mhz
+ *[0.....80]	 1	(1/4)(1/8)    [0   to 2.5]
+ *[81...120]	 2	(1/6)(1/8)    [1.6 to 2.5]
+ *[121..160]	 3	(1/8)(1/8)    [1.8 to 2.5]
+ *[161..200]	 4	(1/10)(1/8)   [2.0 to 2.5]
+ *[201..280]	 5	(1/14)(1/8)   [1.8 to 2.5]
+ *[281..400]	 6	(1/20)(1/8)   [1.1 to 2.5]
+ *[401..560]	 7	(1/28)(1/8)   [1.8 to 2.5]
+ *[560..frq]	 7	(1/28)(1/8)   [frq/224]
+ *Returns: the MIIMCFG[MgmtClk] appropriate value
+ */
+
+static uint8_t dtsec_mii_get_div(uint16_t dtsec_freq)
+{
+	uint16_t mgmt_clk;
+
+	if (dtsec_freq < 80)
+		mgmt_clk = 1;
+	else if (dtsec_freq < 120)
+		mgmt_clk = 2;
+	else if (dtsec_freq < 160)
+		mgmt_clk = 3;
+	else if (dtsec_freq < 200)
+		mgmt_clk = 4;
+	else if (dtsec_freq < 280)
+		mgmt_clk = 5;
+	else if (dtsec_freq < 400)
+		mgmt_clk = 6;
+	else
+		mgmt_clk = 7;
+
+	return (uint8_t)mgmt_clk;
+}
+
+void fman_dtsec_mii_reset(struct dtsec_mii_reg __iomem *regs)
+{
+	/* Reset the management interface */
+	iowrite32be(ioread32be(&regs->miimcfg) | MIIMCFG_RESET_MGMT,
+		    &regs->miimcfg);
+	iowrite32be(ioread32be(&regs->miimcfg) & ~MIIMCFG_RESET_MGMT,
+		    &regs->miimcfg);
+}
+
+int fman_dtsec_mii_write_reg(struct dtsec_mii_reg __iomem *regs, uint8_t addr,
+			     uint8_t reg, uint16_t data, uint16_t dtsec_freq)
+{
+	uint32_t tmp;
+
+	/* Setup the MII Mgmt clock speed */
+	iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), &regs->miimcfg);
+	/* Memory barrier */
+	wmb();
+
+	/* Stop the MII management read cycle */
+	iowrite32be(0, &regs->miimcom);
+	/* Dummy read to make sure MIIMCOM is written */
+	tmp = ioread32be(&regs->miimcom);
+	/* Memory barrier */
+	wmb();
+
+	/* Setting up MII Management Address Register */
+	tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg);
+	iowrite32be(tmp, &regs->miimadd);
+	/* Memory barrier */
+	wmb();
+
+	/* Setting up MII Management Control Register with data */
+	iowrite32be((uint32_t)data, &regs->miimcon);
+	/* Dummy read to make sure MIIMCON is written */
+	tmp = ioread32be(&regs->miimcon);
+	/* Memory barrier */
+	wmb();
+
+	/* Wait until MII management write is complete */
+	/* todo: a timeout could be useful here */
+	while ((ioread32be(&regs->miimind)) & MIIMIND_BUSY)
+		; /* busy wait */
+
+	return 0;
+}
+
+int fman_dtsec_mii_read_reg(struct dtsec_mii_reg __iomem *regs, uint8_t addr,
+			    uint8_t reg, uint16_t *data, uint16_t dtsec_freq)
+{
+	uint32_t tmp;
+
+	/* Setup the MII Mgmt clock speed */
+	iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), &regs->miimcfg);
+	/* Memory barrier */
+	wmb();
+
+	/* Setting up the MII Management Address Register */
+	tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg);
+	iowrite32be(tmp, &regs->miimadd);
+	/* Memory barrier */
+	wmb();
+
+	/* Perform an MII management read cycle */
+	iowrite32be(MIIMCOM_READ_CYCLE, &regs->miimcom);
+	/* Dummy read to make sure MIIMCOM is written */
+	tmp = ioread32be(&regs->miimcom);
+	/* Memory barrier */
+	wmb();
+
+	/* Wait until MII management read is complete */
+	/* todo: a timeout could be useful here */
+	while ((ioread32be(&regs->miimind)) & MIIMIND_BUSY)
+		; /* busy wait */
+
+	/* Read MII management status  */
+	*data = (uint16_t)ioread32be(&regs->miimstat);
+	/* Memory barrier */
+	wmb();
+
+	iowrite32be(0, &regs->miimcom);
+	/* Dummy read to make sure MIIMCOM is written */
+	tmp = ioread32be(&regs->miimcom);
+
+	if (*data == 0xffff)
+		return -ENXIO;
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_memac.c b/drivers/net/ethernet/freescale/fman/mac/fman_memac.c
new file mode 100644
index 0000000..e0bac5a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_memac.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_fman_memac.h"
+
+uint32_t fman_memac_get_event(struct memac_regs __iomem *regs, uint32_t ev_mask)
+{
+	return ioread32be(&regs->ievent) & ev_mask;
+}
+
+uint32_t fman_memac_get_interrupt_mask(struct memac_regs __iomem *regs)
+{
+	return ioread32be(&regs->imask);
+}
+
+void fman_memac_ack_event(struct memac_regs __iomem *regs, uint32_t ev_mask)
+{
+	iowrite32be(ev_mask, &regs->ievent);
+}
+
+void fman_memac_set_promiscuous(struct memac_regs __iomem *regs, bool val)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->command_config);
+
+	if (val)
+		tmp |= CMD_CFG_PROMIS_EN;
+	else
+		tmp &= ~CMD_CFG_PROMIS_EN;
+
+	iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_memac_clear_addr_in_paddr(struct memac_regs __iomem *regs,
+				    uint8_t paddr_num)
+{
+	if (paddr_num == 0) {
+		iowrite32be(0, &regs->mac_addr0.mac_addr_l);
+		iowrite32be(0, &regs->mac_addr0.mac_addr_u);
+	} else {
+		iowrite32be(0x0, &regs->mac_addr[paddr_num - 1].mac_addr_l);
+		iowrite32be(0x0, &regs->mac_addr[paddr_num - 1].mac_addr_u);
+	}
+}
+
+void fman_memac_add_addr_in_paddr(struct memac_regs __iomem *regs,
+				  uint8_t *adr, uint8_t paddr_num)
+{
+	uint32_t tmp0, tmp1;
+
+	tmp0 = (uint32_t)(adr[0] | adr[1] << 8 | adr[2] << 16 | adr[3] << 24);
+	tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
+
+	if (paddr_num == 0) {
+		iowrite32be(tmp0, &regs->mac_addr0.mac_addr_l);
+		iowrite32be(tmp1, &regs->mac_addr0.mac_addr_u);
+	} else {
+		iowrite32be(tmp0, &regs->mac_addr[paddr_num - 1].mac_addr_l);
+		iowrite32be(tmp1, &regs->mac_addr[paddr_num - 1].mac_addr_u);
+	}
+}
+
+void fman_memac_enable(struct memac_regs __iomem *regs, bool apply_rx,
+		       bool apply_tx)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->command_config);
+
+	if (apply_rx)
+		tmp |= CMD_CFG_RX_EN;
+
+	if (apply_tx)
+		tmp |= CMD_CFG_TX_EN;
+
+	iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_memac_disable(struct memac_regs __iomem *regs, bool apply_rx,
+			bool apply_tx)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->command_config);
+
+	if (apply_rx)
+		tmp &= ~CMD_CFG_RX_EN;
+
+	if (apply_tx)
+		tmp &= ~CMD_CFG_TX_EN;
+
+	iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_memac_reset(struct memac_regs __iomem *regs)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->command_config);
+
+	tmp |= CMD_CFG_SW_RESET;
+
+	iowrite32be(tmp, &regs->command_config);
+
+	while (ioread32be(&regs->command_config) & CMD_CFG_SW_RESET)
+		;
+}
+
+int fman_memac_init(struct memac_regs __iomem *regs,
+		    struct memac_cfg *cfg,
+		    enum enet_interface enet_interface,
+		    enum enet_speed enet_speed,
+		    bool slow_10g_if,
+		    uint32_t exceptions)
+{
+	uint32_t tmp;
+
+	/* Config */
+	tmp = 0;
+	if (cfg->wan_mode_enable)
+		tmp |= CMD_CFG_WAN_MODE;
+	if (cfg->promiscuous_mode_enable)
+		tmp |= CMD_CFG_PROMIS_EN;
+	if (cfg->pause_forward_enable)
+		tmp |= CMD_CFG_PAUSE_FWD;
+	if (cfg->pause_ignore)
+		tmp |= CMD_CFG_PAUSE_IGNORE;
+	if (cfg->tx_addr_ins_enable)
+		tmp |= CMD_CFG_TX_ADDR_INS;
+	if (cfg->loopback_enable)
+		tmp |= CMD_CFG_LOOPBACK_EN;
+	if (cfg->cmd_frame_enable)
+		tmp |= CMD_CFG_CNT_FRM_EN;
+	if (cfg->send_idle_enable)
+		tmp |= CMD_CFG_SEND_IDLE;
+	if (cfg->no_length_check_enable)
+		tmp |= CMD_CFG_NO_LEN_CHK;
+	if (cfg->rx_sfd_any)
+		tmp |= CMD_CFG_SFD_ANY;
+	if (cfg->pad_enable)
+		tmp |= CMD_CFG_TX_PAD_EN;
+	if (cfg->wake_on_lan)
+		tmp |= CMD_CFG_MG;
+
+	tmp |= CMD_CFG_CRC_FWD;
+
+	iowrite32be(tmp, &regs->command_config);
+
+	/* Max Frame Length */
+	iowrite32be((uint32_t)cfg->max_frame_length, &regs->maxfrm);
+
+	/* Pause Time */
+	iowrite32be((uint32_t)cfg->pause_quanta, &regs->pause_quanta[0]);
+	iowrite32be((uint32_t)0, &regs->pause_thresh[0]);
+
+	/* IF_MODE */
+	tmp = 0;
+	switch (enet_interface) {
+	case E_ENET_IF_XGMII:
+	case E_ENET_IF_XFI:
+		tmp |= IF_MODE_XGMII;
+		break;
+	default:
+		tmp |= IF_MODE_GMII;
+		if (enet_interface == E_ENET_IF_RGMII && !cfg->loopback_enable)
+			tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO;
+	}
+	iowrite32be(tmp, &regs->if_mode);
+
+	/* TX_FIFO_SECTIONS */
+	tmp = 0;
+	if (enet_interface == E_ENET_IF_XGMII ||
+	    enet_interface == E_ENET_IF_XFI) {
+		if (slow_10g_if) {
+			tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G |
+				TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);
+		} else {
+			tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G |
+				TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);
+		}
+	} else {
+		tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G |
+			TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G);
+	}
+	iowrite32be(tmp, &regs->tx_fifo_sections);
+
+	/* clear all pending events and set-up interrupts */
+	fman_memac_ack_event(regs, 0xffffffff);
+	fman_memac_set_exception(regs, exceptions, true);
+
+	return 0;
+}
+
+void fman_memac_set_exception(struct memac_regs __iomem *regs, uint32_t val,
+			      bool enable)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->imask);
+	if (enable)
+		tmp |= val;
+	else
+		tmp &= ~val;
+
+	iowrite32be(tmp, &regs->imask);
+}
+
+void fman_memac_set_hash_table(struct memac_regs __iomem *regs, uint32_t val)
+{
+	iowrite32be(val, &regs->hashtable_ctrl);
+}
+
+uint16_t fman_memac_get_max_frame_len(struct memac_regs __iomem *regs)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->maxfrm);
+
+	return (uint16_t)tmp;
+}
+
+void fman_memac_set_tx_pause_frames(struct memac_regs __iomem *regs,
+				    uint8_t priority,
+				    uint16_t pause_time, uint16_t thresh_time)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->tx_fifo_sections);
+
+	GET_TX_EMPTY_DEFAULT_VALUE(tmp);
+	iowrite32be(tmp, &regs->tx_fifo_sections);
+
+	tmp = ioread32be(&regs->command_config);
+	tmp &= ~CMD_CFG_PFC_MODE;
+	priority = 0;
+
+	iowrite32be(tmp, &regs->command_config);
+
+	tmp = ioread32be(&regs->pause_quanta[priority / 2]);
+	if (priority % 2)
+		tmp &= 0x0000FFFF;
+	else
+		tmp &= 0xFFFF0000;
+	tmp |= ((uint32_t)pause_time << (16 * (priority % 2)));
+	iowrite32be(tmp, &regs->pause_quanta[priority / 2]);
+
+	tmp = ioread32be(&regs->pause_thresh[priority / 2]);
+	if (priority % 2)
+		tmp &= 0x0000FFFF;
+	else
+		tmp &= 0xFFFF0000;
+	tmp |= ((uint32_t)thresh_time << (16 * (priority % 2)));
+	iowrite32be(tmp, &regs->pause_thresh[priority / 2]);
+}
+
+void fman_memac_set_rx_ignore_pause_frames(struct memac_regs __iomem *regs,
+					   bool enable)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->command_config);
+	if (enable)
+		tmp |= CMD_CFG_PAUSE_IGNORE;
+	else
+		tmp &= ~CMD_CFG_PAUSE_IGNORE;
+
+	iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_memac_adjust_link(struct memac_regs __iomem *regs,
+			    enum enet_interface iface_mode,
+			    enum enet_speed speed, bool full_dx)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->if_mode);
+
+	if (full_dx)
+		tmp &= ~IF_MODE_HD;
+	else
+		tmp |= IF_MODE_HD;
+
+	if (iface_mode == E_ENET_IF_RGMII) {
+		/* Configure RGMII in manual mode */
+		tmp &= ~IF_MODE_RGMII_AUTO;
+		tmp &= ~IF_MODE_RGMII_SP_MASK;
+
+		if (full_dx)
+			tmp |= IF_MODE_RGMII_FD;
+		else
+			tmp &= ~IF_MODE_RGMII_FD;
+
+		switch (speed) {
+		case E_ENET_SPEED_1000:
+			tmp |= IF_MODE_RGMII_1000;
+			break;
+		case E_ENET_SPEED_100:
+			tmp |= IF_MODE_RGMII_100;
+			break;
+		case E_ENET_SPEED_10:
+			tmp |= IF_MODE_RGMII_10;
+			break;
+		default:
+			break;
+		}
+	}
+
+	iowrite32be(tmp, &regs->if_mode);
+}
+
+void fman_memac_defconfig(struct memac_cfg *cfg)
+{
+	cfg->reset_on_init = false;
+	cfg->wan_mode_enable = false;
+	cfg->promiscuous_mode_enable = false;
+	cfg->pause_forward_enable = false;
+	cfg->pause_ignore = false;
+	cfg->tx_addr_ins_enable = false;
+	cfg->loopback_enable = false;
+	cfg->cmd_frame_enable = false;
+	cfg->rx_error_discard = false;
+	cfg->send_idle_enable = false;
+	cfg->no_length_check_enable = true;
+	cfg->lgth_check_nostdr = false;
+	cfg->time_stamp_enable = false;
+	cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;
+	cfg->max_frame_length = DEFAULT_FRAME_LENGTH;
+	cfg->pause_quanta = DEFAULT_PAUSE_QUANTA;
+	cfg->pad_enable = true;
+	cfg->phy_tx_ena_on = false;
+	cfg->rx_sfd_any = false;
+	cfg->rx_pbl_fwd = false;
+	cfg->tx_pbl_fwd = false;
+	cfg->debug_mode = false;
+	cfg->wake_on_lan = false;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c
new file mode 100644
index 0000000..7addd6d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_fman_memac_mii_acc.h"
+
+static void write_phy_reg_10g(struct memac_mii_access_mem_map __iomem *mii_regs,
+			      uint8_t phy_addr, uint8_t reg, uint16_t data)
+{
+	uint32_t tmp_reg;
+
+	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+	/* Leave only MDIO_CLK_DIV bits set on */
+	tmp_reg &= MDIO_CFG_CLK_DIV_MASK;
+	/* Set maximum MDIO_HOLD value to allow phy to see
+	 * change of data signal
+	 **/
+	tmp_reg |= MDIO_CFG_HOLD_MASK;
+	/* Add 10G interface mode */
+	tmp_reg |= MDIO_CFG_ENC45;
+	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+	/* Wait for command completion */
+	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+		udelay(1);
+
+	/* Specify phy and register to be accessed */
+	iowrite32be(phy_addr, &mii_regs->mdio_ctrl);
+	iowrite32be(reg, &mii_regs->mdio_addr);
+	/* memory barrier */
+	wmb();
+
+	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+		udelay(1);
+
+	/* Write data */
+	iowrite32be(data, &mii_regs->mdio_data);
+	/* memory barrier */
+	wmb();
+
+	/* Wait for write transaction end */
+	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+		udelay(1);
+}
+
+static uint32_t read_phy_reg_10g(struct memac_mii_access_mem_map __iomem
+				 *mii_regs, uint8_t phy_addr, uint8_t reg,
+				 uint16_t *data)
+{
+	uint32_t tmp_reg;
+
+	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+	/* Leave only MDIO_CLK_DIV bits set on */
+	tmp_reg &= MDIO_CFG_CLK_DIV_MASK;
+	/* Set maximum MDIO_HOLD value to allow phy to see
+	 * change of data signal
+	 **/
+	tmp_reg |= MDIO_CFG_HOLD_MASK;
+	/* Add 10G interface mode */
+	tmp_reg |= MDIO_CFG_ENC45;
+	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+	/* Wait for command completion */
+	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+		udelay(1);
+
+	/* Specify phy and register to be accessed */
+	iowrite32be(phy_addr, &mii_regs->mdio_ctrl);
+	iowrite32be(reg, &mii_regs->mdio_addr);
+	/* memory barrier */
+	wmb();
+
+	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+		udelay(1);
+
+	/* Read cycle */
+	tmp_reg = phy_addr;
+	tmp_reg |= MDIO_CTL_READ;
+	iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
+	/* memory barrier */
+	wmb();
+
+	/* Wait for data to be available */
+	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+		udelay(1);
+
+	*data = (uint16_t)ioread32be(&mii_regs->mdio_data);
+
+	/* Check if there was an error */
+	return ioread32be(&mii_regs->mdio_cfg);
+}
+
+static void write_phy_reg_1g(struct memac_mii_access_mem_map __iomem *mii_regs,
+			     uint8_t phy_addr, uint8_t reg, uint16_t data)
+{
+	uint32_t tmp_reg;
+
+	/* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
+	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+	tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
+	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+	/* Wait for command completion */
+	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+		udelay(1);
+
+	/* Write transaction */
+	tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT);
+	tmp_reg |= reg;
+	iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
+
+	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+		udelay(1);
+
+	iowrite32be(data, &mii_regs->mdio_data);
+
+	/* memory barrier */
+	wmb();
+
+	/* Wait for write transaction to end */
+	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+		udelay(1);
+}
+
+static uint32_t read_phy_reg_1g(struct memac_mii_access_mem_map __iomem
+				*mii_regs, uint8_t phy_addr, uint8_t reg,
+				uint16_t *data)
+{
+	uint32_t tmp_reg;
+
+	/* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
+	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+	tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
+	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+	/* Wait for command completion */
+	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+		udelay(1);
+
+	/* Read transaction */
+	tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT);
+	tmp_reg |= reg;
+	tmp_reg |= MDIO_CTL_READ;
+	iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
+
+	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+		udelay(1);
+
+	/* Wait for data to be available */
+	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+		udelay(1);
+
+	*data = (uint16_t)ioread32be(&mii_regs->mdio_data);
+
+	/* Check error */
+	return ioread32be(&mii_regs->mdio_cfg);
+}
+
+int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map __iomem
+				 *mii_regs, uint8_t phy_addr, uint8_t reg,
+				 uint16_t data, enum enet_speed enet_speed)
+{
+	/* Figure out interface type - 10G vs 1G.
+	 * In 10G interface both phy_addr and devAddr present.
+	 **/
+	if (enet_speed == E_ENET_SPEED_10000)
+		write_phy_reg_10g(mii_regs, phy_addr, reg, data);
+	else
+		write_phy_reg_1g(mii_regs, phy_addr, reg, data);
+
+	return 0;
+}
+
+int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map __iomem
+				*mii_regs, uint8_t phy_addr, uint8_t reg,
+				uint16_t *data, enum enet_speed enet_speed)
+{
+	uint32_t ans;
+	/* Figure out interface type - 10G vs 1G.
+	 * In 10G interface both phy_addr and devAddr present.
+	 **/
+	if (enet_speed == E_ENET_SPEED_10000)
+		ans = read_phy_reg_10g(mii_regs, phy_addr, reg, data);
+	else
+		ans = read_phy_reg_1g(mii_regs, phy_addr, reg, data);
+
+	if (ans & MDIO_CFG_READ_ERR)
+		return -EINVAL;
+	return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_tgec.c b/drivers/net/ethernet/freescale/fman/mac/fman_tgec.c
new file mode 100644
index 0000000..11bcc1a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_tgec.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_fman_tgec.h"
+
+void fman_tgec_set_mac_address(struct tgec_regs __iomem *regs, uint8_t *adr)
+{
+	uint32_t tmp0, tmp1;
+
+	tmp0 = (uint32_t)(adr[0] | adr[1] << 8 | adr[2] << 16 | adr[3] << 24);
+	tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
+	iowrite32be(tmp0, &regs->mac_addr_0);
+	iowrite32be(tmp1, &regs->mac_addr_1);
+}
+
+void fman_tgec_enable(struct tgec_regs __iomem *regs, bool apply_rx,
+		      bool apply_tx)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->command_config);
+	if (apply_rx)
+		tmp |= CMD_CFG_RX_EN;
+	if (apply_tx)
+		tmp |= CMD_CFG_TX_EN;
+	iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_tgec_disable(struct tgec_regs __iomem *regs, bool apply_rx,
+		       bool apply_tx)
+{
+	uint32_t tmp_reg_32;
+
+	tmp_reg_32 = ioread32be(&regs->command_config);
+	if (apply_rx)
+		tmp_reg_32 &= ~CMD_CFG_RX_EN;
+	if (apply_tx)
+		tmp_reg_32 &= ~CMD_CFG_TX_EN;
+	iowrite32be(tmp_reg_32, &regs->command_config);
+}
+
+void fman_tgec_set_promiscuous(struct tgec_regs __iomem *regs, bool val)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->command_config);
+	if (val)
+		tmp |= CMD_CFG_PROMIS_EN;
+	else
+		tmp &= ~CMD_CFG_PROMIS_EN;
+	iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_tgec_set_hash_table(struct tgec_regs __iomem *regs, uint32_t value)
+{
+	iowrite32be(value, &regs->hashtable_ctrl);
+}
+
+void fman_tgec_set_tx_pause_frames(struct tgec_regs __iomem *regs,
+				   uint16_t pause_time)
+{
+	iowrite32be((uint32_t)pause_time, &regs->pause_quant);
+}
+
+void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs __iomem *regs,
+					  bool en)
+{
+	uint32_t tmp;
+
+	tmp = ioread32be(&regs->command_config);
+	if (en)
+		tmp |= CMD_CFG_PAUSE_IGNORE;
+	else
+		tmp &= ~CMD_CFG_PAUSE_IGNORE;
+	iowrite32be(tmp, &regs->command_config);
+}
+
+uint32_t fman_tgec_get_event(struct tgec_regs __iomem *regs, uint32_t ev_mask)
+{
+	return ioread32be(&regs->ievent) & ev_mask;
+}
+
+void fman_tgec_ack_event(struct tgec_regs __iomem *regs, uint32_t ev_mask)
+{
+	iowrite32be(ev_mask, &regs->ievent);
+}
+
+uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs __iomem *regs)
+{
+	return ioread32be(&regs->imask);
+}
+
+uint32_t fman_tgec_get_revision(struct tgec_regs __iomem *regs)
+{
+	return ioread32be(&regs->tgec_id);
+}
+
+void fman_tgec_enable_interrupt(struct tgec_regs __iomem *regs,
+				uint32_t ev_mask)
+{
+	iowrite32be(ioread32be(&regs->imask) | ev_mask, &regs->imask);
+}
+
+void fman_tgec_disable_interrupt(struct tgec_regs __iomem *regs,
+				 uint32_t ev_mask)
+{
+	iowrite32be(ioread32be(&regs->imask) & ~ev_mask, &regs->imask);
+}
+
+uint16_t fman_tgec_get_max_frame_len(struct tgec_regs __iomem *regs)
+{
+	return (uint16_t)ioread32be(&regs->maxfrm);
+}
+
+void fman_tgec_defconfig(struct tgec_cfg *cfg)
+{
+	cfg->wan_mode_enable = DEFAULT_WAN_MODE_ENABLE;
+	cfg->promiscuous_mode_enable = DEFAULT_PROMISCUOUS_MODE_ENABLE;
+	cfg->pause_forward_enable = DEFAULT_PAUSE_FORWARD_ENABLE;
+	cfg->pause_ignore = DEFAULT_PAUSE_IGNORE;
+	cfg->tx_addr_ins_enable = DEFAULT_TX_ADDR_INS_ENABLE;
+	cfg->loopback_enable = DEFAULT_LOOPBACK_ENABLE;
+	cfg->cmd_frame_enable = DEFAULT_CMD_FRAME_ENABLE;
+	cfg->rx_error_discard = DEFAULT_RX_ERROR_DISCARD;
+	cfg->send_idle_enable = DEFAULT_SEND_IDLE_ENABLE;
+	cfg->no_length_check_enable = DEFAULT_NO_LENGTH_CHECK_ENABLE;
+	cfg->lgth_check_nostdr = DEFAULT_LGTH_CHECK_NOSTDR;
+	cfg->time_stamp_enable = DEFAULT_TIME_STAMP_ENABLE;
+	cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;
+	cfg->max_frame_length = DEFAULT_MAX_FRAME_LENGTH;
+	cfg->pause_quant = DEFAULT_PAUSE_QUANT;
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+	cfg->skip_fman11_workaround = false;
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+}
+
+int fman_tgec_init(struct tgec_regs __iomem *regs, struct tgec_cfg *cfg,
+		   uint32_t exception_mask)
+{
+	uint32_t tmp;
+
+	/* Config */
+	tmp = 0x40;		/* CRC forward */
+	if (cfg->wan_mode_enable)
+		tmp |= CMD_CFG_WAN_MODE;
+	if (cfg->promiscuous_mode_enable)
+		tmp |= CMD_CFG_PROMIS_EN;
+	if (cfg->pause_forward_enable)
+		tmp |= CMD_CFG_PAUSE_FWD;
+	if (cfg->pause_ignore)
+		tmp |= CMD_CFG_PAUSE_IGNORE;
+	if (cfg->tx_addr_ins_enable)
+		tmp |= CMD_CFG_TX_ADDR_INS;
+	if (cfg->loopback_enable)
+		tmp |= CMD_CFG_LOOPBACK_EN;
+	if (cfg->cmd_frame_enable)
+		tmp |= CMD_CFG_CMD_FRM_EN;
+	if (cfg->rx_error_discard)
+		tmp |= CMD_CFG_RX_ER_DISC;
+	if (cfg->send_idle_enable)
+		tmp |= CMD_CFG_SEND_IDLE;
+	if (cfg->no_length_check_enable)
+		tmp |= CMD_CFG_NO_LEN_CHK;
+	if (cfg->time_stamp_enable)
+		tmp |= CMD_CFG_EN_TIMESTAMP;
+	iowrite32be(tmp, &regs->command_config);
+
+	/* Max Frame Length */
+	iowrite32be((uint32_t)cfg->max_frame_length, &regs->maxfrm);
+	/* Pause Time */
+	iowrite32be(cfg->pause_quant, &regs->pause_quant);
+
+	/* clear all pending events and set-up interrupts */
+	fman_tgec_ack_event(regs, 0xffffffff);
+	fman_tgec_enable_interrupt(regs, exception_mask);
+
+	return 0;
+}
+
+void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs
+							  __iomem *regs)
+{
+	uint32_t tmp;
+
+	/* restore the default tx ipg Length */
+	tmp = (ioread32be(&regs->tx_ipg_len) & ~TGEC_TX_IPG_LENGTH_MASK) | 12;
+
+	iowrite32be(tmp, &regs->tx_ipg_len);
+}
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 07/12] fsl/fman: Add FMan MURAM support
  2015-05-07 13:05         ` [RFC,v3 06/12] fsl/fman: Add the FMan MAC FLIB Madalin Bucur
@ 2015-05-07 13:05           ` Madalin Bucur
  2015-05-07 13:05             ` [RFC,v3 08/12] fsl/fman: Add Frame Manager support Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

Add Frame Manager Multi-User RAM support.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 drivers/net/ethernet/freescale/fman/Kconfig        |   1 +
 drivers/net/ethernet/freescale/fman/Makefile       |   6 +-
 drivers/net/ethernet/freescale/fman/fm_muram.c     | 114 +++++++++++++++++++++
 .../net/ethernet/freescale/fman/inc/fm_muram_ext.h |  89 ++++++++++++++++
 4 files changed, 208 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/ethernet/freescale/fman/fm_muram.c
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_muram_ext.h

diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
index af42c3a..825a0d5 100644
--- a/drivers/net/ethernet/freescale/fman/Kconfig
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -1,6 +1,7 @@
 config FSL_FMAN
 	bool "FMan support"
 	depends on FSL_SOC || COMPILE_TEST
+	select GENERIC_ALLOCATOR
 	default n
 	help
 		Freescale Data-Path Acceleration Architecture Frame Manager
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index 534d1ed..55c91bd 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -1,8 +1,10 @@
-subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib
+subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib \
+				     -I$(srctree)/drivers/net/ethernet/freescale/fman/inc \
+				     -I$(srctree)/drivers/net/ethernet/freescale/fman
 
 obj-y		+= fsl_fman.o
 
-fsl_fman-objs			:= fman.o
+fsl_fman-objs	:= fman.o fm_muram.o
 
 obj-y	+= port/
 obj-y	+= mac/
diff --git a/drivers/net/ethernet/freescale/fman/fm_muram.c b/drivers/net/ethernet/freescale/fman/fm_muram.c
new file mode 100644
index 0000000..2bca725
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm_muram.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM MURAM ... */
+#include "fm_muram_ext.h"
+
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/genalloc.h>
+
+struct muram_info {
+	struct gen_pool *pool;
+	void __iomem *vbase;
+	uint64_t size;
+	phys_addr_t pbase;
+};
+
+struct muram_info *fm_muram_init(phys_addr_t base, uint64_t size)
+{
+	struct muram_info *p_muram;
+	void __iomem *vaddr;
+	int ret;
+
+	p_muram = kzalloc(sizeof(*p_muram), GFP_KERNEL);
+	if (!p_muram)
+		return NULL;
+
+	p_muram->pool = gen_pool_create(ilog2(64), -1);
+	if (!p_muram->pool) {
+		pr_err("%s(): MURAM pool create failed\n", __func__);
+		return NULL;
+	}
+
+	vaddr = ioremap(base, size);
+	if (!vaddr) {
+		pr_err("%s(): MURAM ioremap failed\n", __func__);
+		return NULL;
+	}
+
+	ret = gen_pool_add_virt(p_muram->pool, (unsigned long)vaddr,
+				base, size, -1);
+	if (ret < 0) {
+		pr_err("%s(): MURAM pool add failed\n", __func__);
+		iounmap(vaddr);
+		return NULL;
+	}
+
+	p_muram->vbase = vaddr;
+	p_muram->pbase = base;
+	return p_muram;
+}
+
+void fm_muram_free(struct muram_info *p_muram)
+{
+	/* Destroy pool */
+	gen_pool_destroy(p_muram->pool);
+	/* Unmap memory */
+	iounmap(p_muram->vbase);
+	/* Free pointer */
+	kfree(p_muram);
+}
+
+void fm_muram_clear(struct muram_info *p_muram)
+{
+	memset_io(p_muram->vbase, 0, p_muram->size);
+}
+
+unsigned long fm_muram_alloc(struct muram_info *p_muram, uint32_t size)
+{
+	unsigned long vaddr;
+
+	vaddr = gen_pool_alloc(p_muram->pool, size);
+	if (!vaddr)
+		return 0;
+
+	return vaddr;
+}
+
+void fm_muram_free_mem(struct muram_info *p_muram, unsigned long addr,
+		       uint32_t size)
+{
+	gen_pool_free(p_muram->pool, addr, size);
+}
+
diff --git a/drivers/net/ethernet/freescale/fman/inc/fm_muram_ext.h b/drivers/net/ethernet/freescale/fman/inc/fm_muram_ext.h
new file mode 100644
index 0000000..48c066a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/fm_muram_ext.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* File          fm_muram_ext.h
+ * Description   FM MURAM Application Programming Interface.
+ */
+#ifndef __FM_MURAM_EXT
+#define __FM_MURAM_EXT
+
+#include "linux/types.h"
+
+/* Structure for FM MURAM information */
+struct muram_info;
+
+/* FM MURAM initialization API functions, definitions and enums */
+
+/* Function	fm_muram_init
+ * Description	Creates partition in the MURAM.
+ *		The routine returns a pointer to the MURAM partition.
+ *		This pointer must be passed as first parameter to all other
+ *		FM-MURAM function calls.
+ *		No actual initialization or configuration of FM_MURAM hardware
+ *		is done by this routine.
+ * Param[in]	base - Pointer to base of memory mapped FM-MURAM.
+ * Param[in]	size - Size of the FM-MURAM partition.
+ * Return	pointer to FM-MURAM object, or NULL for Failure.
+ */
+struct muram_info *fm_muram_init(phys_addr_t base, uint64_t size);
+
+/* Function	fm_muram_free
+ * Description	Frees all resources that were assigned to FM-MURAM module.
+ *		Calling this routine invalidates the pointer.
+ * Param[in]	p_muram - FM-MURAM module pointer.
+ */
+void fm_muram_free(struct muram_info *p_muram);
+
+/* Function	fm_muram_clear
+ * Description	Set zeros to MURAM memory
+ * Param[in]	p_muram - FM-MURAM module pointer.
+ */
+void fm_muram_clear(struct muram_info *p_muram);
+
+/* Function	fm_muram_alloc
+ * Description	Allocate some memory from FM-MURAM partition.
+ * Param[in]	p_muram   - FM-MURAM module pointer.
+ * Param[in]	size      - size of the memory to be allocated.
+ * Return	address of the allocated memory; NULL otherwise.
+ */
+unsigned long fm_muram_alloc(struct muram_info *p_muram, uint32_t size);
+
+/* Function	fm_muram_free_mem
+ * Description	Free an allocated memory from FM-MURAM partition.
+ * Param[in]	p_muram   - FM-MURAM module pointer.
+ * Param[in]	addr      - address to be freed.
+ * Param[in]	size      - size of the memory to be freed.
+ */
+void fm_muram_free_mem(struct muram_info *p_muram, unsigned long addr,
+		       uint32_t size);
+
+#endif /* __FM_MURAM_EXT */
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 08/12] fsl/fman: Add Frame Manager support
  2015-05-07 13:05           ` [RFC,v3 07/12] fsl/fman: Add FMan MURAM support Madalin Bucur
@ 2015-05-07 13:05             ` Madalin Bucur
  2015-05-07 13:05               ` [RFC,v3 09/12] fsl/fman: Add FMan MAC support Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

Add Frame Manger Driver support.
This patch adds The FMan configuration, initialization and
runtime control routines.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 drivers/net/ethernet/freescale/fman/Kconfig        |   37 +
 drivers/net/ethernet/freescale/fman/Makefile       |    2 +-
 drivers/net/ethernet/freescale/fman/fm.c           | 1515 ++++++++++++++++++++
 drivers/net/ethernet/freescale/fman/fm.h           |  486 +++++++
 drivers/net/ethernet/freescale/fman/fm_common.h    |  331 +++++
 drivers/net/ethernet/freescale/fman/fm_drv.c       |  856 +++++++++++
 drivers/net/ethernet/freescale/fman/fm_drv.h       |  121 ++
 drivers/net/ethernet/freescale/fman/inc/dpaa_ext.h |  253 ++++
 .../freescale/fman/inc/dpaa_integration_ext.h      |  120 ++
 drivers/net/ethernet/freescale/fman/inc/enet_ext.h |  199 +++
 drivers/net/ethernet/freescale/fman/inc/fm_ext.h   |  657 +++++++++
 .../net/ethernet/freescale/fman/inc/fsl_fman_drv.h |   94 ++
 drivers/net/ethernet/freescale/fman/inc/net_ext.h  |  534 +++++++
 drivers/net/ethernet/freescale/fman/inc/service.h  |   90 ++
 14 files changed, 5294 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/freescale/fman/fm.c
 create mode 100644 drivers/net/ethernet/freescale/fman/fm.h
 create mode 100644 drivers/net/ethernet/freescale/fman/fm_common.h
 create mode 100644 drivers/net/ethernet/freescale/fman/fm_drv.c
 create mode 100644 drivers/net/ethernet/freescale/fman/fm_drv.h
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/dpaa_ext.h
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/dpaa_integration_ext.h
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/enet_ext.h
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_ext.h
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/net_ext.h
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/service.h

diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
index 825a0d5..d7de35f 100644
--- a/drivers/net/ethernet/freescale/fman/Kconfig
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -7,3 +7,40 @@ config FSL_FMAN
 		Freescale Data-Path Acceleration Architecture Frame Manager
 		(FMan) support
 
+if FSL_FMAN
+
+config FSL_FM_MAX_FRAME_SIZE
+	int "Maximum L2 frame size"
+	depends on FSL_FMAN
+	range 64 9600
+	default "1522"
+	help
+		Configure this in relation to the maximum possible MTU of your
+		network configuration. In particular, one would need to
+		increase this value in order to use jumbo frames.
+		FSL_FM_MAX_FRAME_SIZE must accommodate the Ethernet FCS
+		(4 bytes) and one ETH+VLAN header (18 bytes), to a total of
+		22 bytes in excess of the desired L3 MTU.
+
+		Note that having too large a FSL_FM_MAX_FRAME_SIZE (much larger
+		than the actual MTU) may lead to buffer exhaustion, especially
+		in the case of badly fragmented datagrams on the Rx path.
+		Conversely, having a FSL_FM_MAX_FRAME_SIZE smaller than the
+		actual MTU will lead to frames being dropped.
+
+config FSL_FM_RX_EXTRA_HEADROOM
+	int "Add extra headroom at beginning of data buffers"
+	depends on FSL_FMAN
+	range 16 384
+	default "64"
+	help
+		Configure this to tell the Frame Manager to reserve some extra
+		space at the beginning of a data buffer on the receive path,
+		before Internal Context fields are copied. This is in addition
+		to the private data area already reserved for driver internal
+		use. The provided value must be a multiple of 16.
+
+		This option does not affect in any way the layout of
+		transmitted buffers.
+
+endif	# FSL_FMAN
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index 55c91bd..f61d3a6 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -4,7 +4,7 @@ subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib \
 
 obj-y		+= fsl_fman.o
 
-fsl_fman-objs	:= fman.o fm_muram.o
+fsl_fman-objs	:= fman.o fm_muram.o fm.o fm_drv.o
 
 obj-y	+= port/
 obj-y	+= mac/
diff --git a/drivers/net/ethernet/freescale/fman/fm.c b/drivers/net/ethernet/freescale/fman/fm.c
new file mode 100644
index 0000000..fbe4c16
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm.c
@@ -0,0 +1,1515 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM driver routines implementation. */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+
+#include "fm_common.h"
+#include "fm.h"
+#include "fm_muram_ext.h"
+#include <asm/mpc85xx.h>
+#include "fsl_fman.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/* static functions */
+
+static struct fm_intg_t *fill_intg_params(uint8_t major, uint8_t minor,
+					  struct fm_params_t *p_fm_param)
+{
+	struct fm_intg_t *intg;
+
+	intg = kzalloc(sizeof(*intg), GFP_KERNEL);
+	if (!intg)
+		return NULL;
+
+	/* P1023 - Major 4
+	 * P4080 - Major 2
+	 * P2041/P3041/P5020/P5040 - Major 3
+	 * Tx/Bx - Major 6
+	 */
+
+	switch (major) {
+	case FM_IP_BLOCK_P2_P3_P5:
+		intg->fm_muram_size		= 160 * 1024;
+		intg->fm_iram_size		= 64 * 1024;
+		intg->fm_num_of_ctrl		= 2;
+
+		intg->dma_thresh_max_commq	= 31;
+		intg->dma_thresh_max_buf	= 127;
+
+		intg->qmi_max_num_of_tnums	= 64;
+		intg->qmi_def_tnums_thresh	= 48;
+
+		intg->bmi_max_num_of_tasks	= 128;
+		intg->bmi_max_num_of_dmas	= 32;
+		intg->port_max_weight		= 16;
+
+		intg->fm_port_num_of_cg		= 256;
+
+		intg->num_of_rx_ports		= 6;
+		break;
+
+	case FM_IP_BLOCK_P4:
+
+		intg->fm_muram_size		= 160 * 1024;
+		intg->fm_iram_size		= 64 * 1024;
+		intg->fm_num_of_ctrl		= 2;
+
+		intg->dma_thresh_max_commq	= 31;
+		intg->dma_thresh_max_buf	= 127;
+
+		intg->qmi_max_num_of_tnums	= 64;
+		intg->qmi_def_tnums_thresh	= 48;
+
+		intg->bmi_max_num_of_tasks	= 128;
+		intg->bmi_max_num_of_dmas	= 32;
+		intg->port_max_weight		= 16;
+
+		intg->fm_port_num_of_cg		= 256;
+
+		intg->num_of_rx_ports		= 5;
+		break;
+
+	case FM_IP_BLOCK_P1:
+
+		intg->fm_muram_size		= 64 * 1024;
+		intg->fm_iram_size		= 32 * 1024;
+		intg->fm_num_of_ctrl		= 2;
+
+		intg->dma_thresh_max_commq	= 15;
+		intg->dma_thresh_max_buf	= 7;
+
+		intg->qmi_max_num_of_tnums	= 15;
+
+		intg->bmi_max_num_of_tasks	= 64;
+		intg->bmi_max_num_of_dmas	= 16;
+		intg->port_max_weight		= 4;
+
+		intg->fm_port_num_of_cg		= 32;
+
+		intg->num_of_rx_ports		= 2;
+		break;
+
+	case FM_IP_BLOCK_B_T:
+		intg->dma_thresh_max_commq	= 83;
+		intg->dma_thresh_max_buf	= 127;
+
+		intg->qmi_max_num_of_tnums	= 64;
+		intg->qmi_def_tnums_thresh	= 32;
+
+		intg->port_max_weight		= 16;
+		intg->fm_port_num_of_cg		= 256;
+
+		/* FManV3L */
+		if (minor == 1 || minor == 4) {
+			intg->fm_muram_size		= 192 * 1024;
+			intg->fm_num_of_ctrl		= 2;
+
+			intg->bmi_max_num_of_tasks	= 64;
+			intg->bmi_max_num_of_dmas	= 32;
+
+			intg->num_of_rx_ports		= 5;
+			
+			if (minor == 1)
+				intg->fm_iram_size	= 32 * 1024;
+			else
+				intg->fm_iram_size	= 64 * 1024;
+		}
+		/* FManV3H */
+		else if (minor == 0 || minor == 2 || minor == 3) {
+			intg->fm_muram_size		= 384 * 1024;
+			intg->fm_iram_size		= 64 * 1024;
+			intg->fm_num_of_ctrl		= 4;
+
+			intg->bmi_max_num_of_tasks	= 128;
+			intg->bmi_max_num_of_dmas	= 84;
+
+			intg->num_of_rx_ports		= 8;
+		} else {
+			pr_err("Unsupported FManv3 version\n");
+			kfree(intg);
+			return NULL;
+		}
+
+		break;
+	default:
+		pr_err("Unsupported FMan version\n");
+		kfree(intg);
+		return NULL;
+	}
+
+	intg->bmi_max_fifo_size = intg->fm_muram_size;
+
+	return intg;
+}
+
+/* Checks if p_fm driver parameters were initialized
+ * returns 0 if success else returns error code
+ */
+static int is_init_done(struct fman_cfg *p_fm_drv_parameters)
+{
+	if (!p_fm_drv_parameters)
+		return 0;
+	return -ENOSYS;
+}
+
+static void free_init_resources(struct fm_t *p_fm)
+{
+	if (p_fm->cam_base_addr)
+		fm_muram_free_mem(p_fm->p_muram, p_fm->cam_base_addr,
+				  p_fm->cam_size);
+	if (p_fm->fifo_base_addr)
+		fm_muram_free_mem(p_fm->p_muram, p_fm->fifo_base_addr,
+				  p_fm->fifo_size);
+}
+
+static bool is_fman_ctrl_code_loaded(struct fm_t *p_fm)
+{
+	struct fm_iram_regs_t __iomem *p_iram;
+
+	p_iram = (struct fm_iram_regs_t __iomem *)UINT_TO_PTR(p_fm->base_addr +
+						       FM_MM_IMEM);
+
+	return (bool)!!(GET_UINT32(p_iram->iready) & IRAM_READY);
+}
+
+static int check_fm_parameters(struct fm_t *p_fm)
+{
+	if (is_fman_ctrl_code_loaded(p_fm) && !p_fm->reset_on_init) {
+		pr_err("Old FMan CTRL code is loaded; FM must be reset!\n");
+		return -EDOM;
+	}
+	if (p_fm->p_fm_state_struct->rev_info.major_rev < 6) {
+		if (!p_fm->p_fm_drv_param->dma_axi_dbg_num_of_beats ||
+		    (p_fm->p_fm_drv_param->dma_axi_dbg_num_of_beats >
+			DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS)) {
+			pr_err("axiDbgNumOfBeats has to be in the range 1 - %d\n",
+			       DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS);
+			return -EDOM;
+		}
+	}
+	if (p_fm->p_fm_drv_param->dma_cam_num_of_entries %
+	    DMA_CAM_UNITS) {
+		pr_err("dma_cam_num_of_entries has to be divisble by %d\n",
+		       DMA_CAM_UNITS);
+		return -EDOM;
+	}
+	if (p_fm->p_fm_drv_param->dma_comm_qtsh_asrt_emer >
+	    p_fm->intg->dma_thresh_max_commq) {
+		pr_err("dma_comm_qtsh_asrt_emer can not be larger than %d\n",
+		       p_fm->intg->dma_thresh_max_commq);
+		return -EDOM;
+	}
+	if (p_fm->p_fm_drv_param->dma_comm_qtsh_clr_emer >
+	    p_fm->intg->dma_thresh_max_commq) {
+		pr_err("dma_comm_qtsh_clr_emer can not be larger than %d\n",
+		       p_fm->intg->dma_thresh_max_commq);
+		return -EDOM;
+	}
+	if (p_fm->p_fm_drv_param->dma_comm_qtsh_clr_emer >=
+	    p_fm->p_fm_drv_param->dma_comm_qtsh_asrt_emer) {
+		pr_err("dma_comm_qtsh_clr_emer must be smaller than dma_comm_qtsh_asrt_emer\n");
+		return -EDOM;
+	}
+	if (p_fm->p_fm_state_struct->rev_info.major_rev < 6) {
+		if (p_fm->p_fm_drv_param->dma_read_buf_tsh_asrt_emer >
+		    p_fm->intg->dma_thresh_max_buf) {
+			pr_err("dma_read_buf_tsh_asrt_emer can not be larger than %d\n",
+			       p_fm->intg->dma_thresh_max_buf);
+			return -EDOM;
+		}
+		if (p_fm->p_fm_drv_param->dma_read_buf_tsh_clr_emer >
+		      p_fm->intg->dma_thresh_max_buf) {
+			pr_err("dma_read_buf_tsh_clr_emer can not be larger than %d\n",
+			       p_fm->intg->dma_thresh_max_buf);
+			return -EDOM;
+		}
+		if (p_fm->p_fm_drv_param->dma_read_buf_tsh_clr_emer >=
+		      p_fm->p_fm_drv_param->dma_read_buf_tsh_asrt_emer) {
+			pr_err("dma_read_buf_tsh_clr_emer must be < dma_read_buf_tsh_asrt_emer\n");
+			return -EDOM;
+		}
+		if (p_fm->p_fm_drv_param->dma_write_buf_tsh_asrt_emer >
+		      p_fm->intg->dma_thresh_max_buf) {
+			pr_err("dma_write_buf_tsh_asrt_emer can not be larger than %d\n",
+			       p_fm->intg->dma_thresh_max_buf);
+			return -EDOM;
+		}
+		if (p_fm->p_fm_drv_param->dma_write_buf_tsh_clr_emer >
+		      p_fm->intg->dma_thresh_max_buf) {
+			pr_err("dma_write_buf_tsh_clr_emer can not be larger than %d\n",
+			       p_fm->intg->dma_thresh_max_buf);
+			return -EDOM;
+		}
+		if (p_fm->p_fm_drv_param->dma_write_buf_tsh_clr_emer >=
+		      p_fm->p_fm_drv_param->dma_write_buf_tsh_asrt_emer) {
+			pr_err("dma_write_buf_tsh_clr_emer has to be less than dma_write_buf_tsh_asrt_emer\n");
+			return -EDOM;
+		}
+	} else {
+		if ((p_fm->p_fm_drv_param->dma_dbg_cnt_mode ==
+				E_FMAN_DMA_DBG_CNT_INT_READ_EM) ||
+			(p_fm->p_fm_drv_param->dma_dbg_cnt_mode ==
+				E_FMAN_DMA_DBG_CNT_INT_WRITE_EM) ||
+			(p_fm->p_fm_drv_param->dma_dbg_cnt_mode ==
+				E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT)) {
+			pr_err("dma_dbg_cnt_mode value not supported by this integration.\n");
+			return -EDOM;
+		}
+		if ((p_fm->p_fm_drv_param->dma_emergency_bus_select ==
+		       FM_DMA_MURAM_READ_EMERGENCY) ||
+		      (p_fm->p_fm_drv_param->dma_emergency_bus_select ==
+		       FM_DMA_MURAM_WRITE_EMERGENCY)) {
+			pr_err("emergencyBusSelect value not supported by this integration.\n");
+			return -EDOM;
+		}
+		if (p_fm->p_fm_drv_param->dma_stop_on_bus_error) {
+			pr_err("dma_stop_on_bus_error not supported by this integration.\n");
+			return -EDOM;
+		}
+#ifdef FM_AID_MODE_NO_TNUM_SW005
+		if (p_fm->p_fm_state_struct->rev_info.major_rev >= 6 &&
+		    p_fm->p_fm_drv_param->dma_aid_mode !=
+		    E_FMAN_DMA_AID_OUT_PORT_ID) {
+			pr_err("dma_aid_mode not supported by this integration.\n");
+			return -EDOM;
+		}
+#endif /* FM_AID_MODE_NO_TNUM_SW005 */
+		if (p_fm->p_fm_drv_param->dma_axi_dbg_num_of_beats) {
+			pr_err("dma_axi_dbg_num_of_beats not supported by this integration.\n");
+			return -EDOM;
+		}
+	}
+
+	if (!p_fm->p_fm_state_struct->fm_clk_freq) {
+		pr_err("fm_clk_freq must be set.\n");
+		return -EDOM;
+	}
+	if (USEC_TO_CLK
+	    (p_fm->p_fm_drv_param->dma_watchdog,
+	     p_fm->p_fm_state_struct->fm_clk_freq) > DMA_MAX_WATCHDOG) {
+		pr_err("dma_watchdog depends on FM clock. dma_watchdog(in microseconds)*clk (in Mhz), may not exceed 0x08%x\n",
+		       DMA_MAX_WATCHDOG);
+		return -EDOM;
+	}
+	if (p_fm->p_fm_state_struct->total_fifo_size % BMI_FIFO_UNITS) {
+		pr_err("total_fifo_size number has to be divisible by %d\n",
+		       BMI_FIFO_UNITS);
+	}
+	if (!p_fm->p_fm_state_struct->total_fifo_size ||
+	    (p_fm->p_fm_state_struct->total_fifo_size >
+	       p_fm->intg->bmi_max_fifo_size)) {
+		pr_err("total_fifo_size (curr - %d) has to be in the range 256 - %d\n",
+		       p_fm->p_fm_state_struct->total_fifo_size,
+		       p_fm->intg->bmi_max_fifo_size);
+		return -EDOM;
+	}
+	if (!p_fm->p_fm_state_struct->total_num_of_tasks ||
+	    (p_fm->p_fm_state_struct->total_num_of_tasks >
+	       p_fm->intg->bmi_max_num_of_tasks)) {
+		pr_err("total_num_of_tasks number has to be in the range 1 - %d\n",
+		       p_fm->intg->bmi_max_num_of_tasks);
+		return -EDOM;
+	}
+
+#ifdef FM_HAS_TOTAL_DMAS
+	if ((p_fm->p_fm_state_struct->rev_info.major_rev < 6) &&
+	    (!p_fm->p_fm_state_struct->max_num_of_open_dmas ||
+	     (p_fm->p_fm_state_struct->max_num_of_open_dmas >
+		p_fm->intg->bmi_max_num_of_dmas))) {
+		pr_err("max_num_of_open_dmas number has to be in the range 1 - %d\n",
+		       p_fm->intg->bmi_max_num_of_dmas);
+		return -EDOM;
+	}
+#endif /* FM_HAS_TOTAL_DMAS */
+
+	if (p_fm->p_fm_drv_param->disp_limit_tsh > FPM_MAX_DISP_LIMIT) {
+		pr_err("disp_limit_tsh can't be greater than %d\n",
+		       FPM_MAX_DISP_LIMIT);
+		return -EDOM;
+	}
+	if (!p_fm->f_exception) {
+		pr_err("Exceptions callback not provided\n");
+		return -EDOM;
+	}
+	if (!p_fm->f_bus_error) {
+		pr_err("Exceptions callback not provided\n");
+		return -EDOM;
+	}
+#ifdef FM_NO_WATCHDOG
+	if ((p_fm->p_fm_state_struct->rev_info.major_rev == 2) &&
+	    (p_fm->p_fm_drv_param->dma_watchdog)) {
+		pr_err("watchdog!\n");
+		return -ENOSYS;
+	}
+#endif /* FM_NO_WATCHDOG */
+
+#ifdef FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008
+	if ((p_fm->p_fm_state_struct->rev_info.major_rev < 6) &&
+	    (p_fm->p_fm_state_struct->rev_info.major_rev != 4) &&
+	    (p_fm->p_fm_drv_param->halt_on_unrecov_ecc_err)) {
+		pr_err("HaltOnEccError!\n");
+		return -ENOSYS;
+	}
+#endif /* FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 */
+
+#ifdef FM_NO_TNUM_AGING
+	if ((p_fm->p_fm_state_struct->rev_info.major_rev != 4) &&
+	    (p_fm->p_fm_state_struct->rev_info.major_rev < 6))
+		if (p_fm->p_fm_drv_param->tnum_aging_period) {
+			pr_err("Tnum aging!\n");
+			return -ENOSYS;
+		}
+#endif /* FM_NO_TNUM_AGING */
+
+	/* check that user did not set revision-dependent exceptions */
+#ifdef FM_NO_DISPATCH_RAM_ECC
+	if ((p_fm->p_fm_state_struct->rev_info.major_rev != 4) &&
+	    (p_fm->p_fm_state_struct->rev_info.major_rev < 6))
+		if (p_fm->user_set_exceptions & FM_EX_BMI_DISPATCH_RAM_ECC) {
+			pr_err("exception FM_EX_BMI_DISPATCH_RAM_ECC!\n");
+			return -ENOSYS;
+		}
+#endif /* FM_NO_DISPATCH_RAM_ECC */
+
+#ifdef FM_QMI_NO_ECC_EXCEPTIONS
+	if (p_fm->p_fm_state_struct->rev_info.major_rev == 4)
+		if (p_fm->user_set_exceptions &
+		    (FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC)) {
+			pr_err("exception FM_EX_QMI_SINGLE_ECC/FM_EX_QMI_DOUBLE_ECC!\n");
+			return -ENOSYS;
+		}
+#endif /* FM_QMI_NO_ECC_EXCEPTIONS */
+
+#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION
+	if (p_fm->p_fm_state_struct->rev_info.major_rev >= 6)
+		if (p_fm->user_set_exceptions & FM_EX_QMI_SINGLE_ECC) {
+			pr_err("exception FM_EX_QMI_SINGLE_ECC!\n");
+			return -ENOSYS;
+		}
+#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */
+
+	return 0;
+}
+
+static void bmi_err_event(struct fm_t *p_fm)
+{
+	uint32_t event;
+	struct fman_bmi_regs __iomem *bmi_rg = p_fm->p_fm_bmi_regs;
+
+	event = fman_get_bmi_err_event(bmi_rg);
+
+	if (event & BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_BMI_STORAGE_PROFILE_ECC);
+	if (event & BMI_ERR_INTR_EN_LIST_RAM_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_BMI_LIST_RAM_ECC);
+	if (event & BMI_ERR_INTR_EN_STATISTICS_RAM_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_BMI_STATISTICS_RAM_ECC);
+	if (event & BMI_ERR_INTR_EN_DISPATCH_RAM_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_BMI_DISPATCH_RAM_ECC);
+}
+
+static void qmi_err_event(struct fm_t *p_fm)
+{
+	uint32_t event;
+	struct fman_qmi_regs __iomem *qmi_rg = p_fm->p_fm_qmi_regs;
+
+	event = fman_get_qmi_err_event(qmi_rg);
+
+	if (event & QMI_ERR_INTR_EN_DOUBLE_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_QMI_DOUBLE_ECC);
+	if (event & QMI_ERR_INTR_EN_DEQ_FROM_DEF)
+		p_fm->f_exception(p_fm->h_app,
+				  FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID);
+}
+
+static void dma_err_event(struct fm_t *p_fm)
+{
+	uint32_t status;
+	struct fman_dma_regs __iomem *dma_rg = p_fm->p_fm_dma_regs;
+
+	status = fman_get_dma_err_event(dma_rg);
+
+	if (status & DMA_STATUS_FM_SPDAT_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_DMA_SINGLE_PORT_ECC);
+	if (status & DMA_STATUS_READ_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_DMA_READ_ECC);
+	if (status & DMA_STATUS_SYSTEM_WRITE_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_DMA_SYSTEM_WRITE_ECC);
+	if (status & DMA_STATUS_FM_WRITE_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_DMA_FM_WRITE_ECC);
+}
+
+static void fpm_err_event(struct fm_t *p_fm)
+{
+	uint32_t event;
+	struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+	event = fman_get_fpm_err_event(fpm_rg);
+
+	if ((event & FPM_EV_MASK_DOUBLE_ECC) &&
+	    (event & FPM_EV_MASK_DOUBLE_ECC_EN))
+		p_fm->f_exception(p_fm->h_app, FM_EX_FPM_DOUBLE_ECC);
+	if ((event & FPM_EV_MASK_STALL) && (event & FPM_EV_MASK_STALL_EN))
+		p_fm->f_exception(p_fm->h_app, FM_EX_FPM_STALL_ON_TASKS);
+	if ((event & FPM_EV_MASK_SINGLE_ECC) &&
+	    (event & FPM_EV_MASK_SINGLE_ECC_EN))
+		p_fm->f_exception(p_fm->h_app, FM_EX_FPM_SINGLE_ECC);
+}
+
+static void muram_err_intr(struct fm_t *p_fm)
+{
+	uint32_t event;
+	struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+	event = fman_get_muram_err_event(fpm_rg);
+
+	if (event & FPM_RAM_MURAM_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_MURAM_ECC);
+}
+
+static void iram_err_intr(struct fm_t *p_fm)
+{
+	uint32_t event;
+	struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+	event = fman_get_iram_err_event(fpm_rg);
+
+	if (event & FPM_RAM_IRAM_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_IRAM_ECC);
+}
+
+static void qmi_event(struct fm_t *p_fm)
+{
+	uint32_t event;
+	struct fman_qmi_regs __iomem *qmi_rg = p_fm->p_fm_qmi_regs;
+
+	event = fman_get_qmi_event(qmi_rg);
+
+	if (event & QMI_INTR_EN_SINGLE_ECC)
+		p_fm->f_exception(p_fm->h_app, FM_EX_QMI_SINGLE_ECC);
+}
+
+static void unimplemented_isr(void __maybe_unused *h_src_arg)
+{
+	pr_err("Unimplemented ISR!\n");
+}
+
+static void enable_time_stamp(struct fm_t *p_fm)
+{
+	struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+	ASSERT(p_fm->p_fm_state_struct);
+	ASSERT(p_fm->p_fm_state_struct->count1_micro_bit);
+
+	fman_enable_time_stamp(fpm_rg,
+			       p_fm->p_fm_state_struct->count1_micro_bit,
+			       p_fm->p_fm_state_struct->fm_clk_freq);
+
+	p_fm->p_fm_state_struct->enabled_time_stamp = true;
+}
+
+static int clear_iram(struct fm_t *p_fm)
+{
+	struct fm_iram_regs_t __iomem *p_iram;
+	int i;
+
+	p_iram = (struct fm_iram_regs_t __iomem *)UINT_TO_PTR(p_fm->base_addr +
+						       FM_MM_IMEM);
+
+	/* Enable the auto-increment */
+	WRITE_UINT32(p_iram->iadd, IRAM_IADD_AIE);
+	while (GET_UINT32(p_iram->iadd) != IRAM_IADD_AIE)
+		;
+
+	for (i = 0; i < (p_fm->intg->fm_iram_size / 4); i++)
+		WRITE_UINT32(p_iram->idata, 0xffffffff);
+
+	WRITE_UINT32(p_iram->iadd, p_fm->intg->fm_iram_size - 4);
+	/* Memory barrier */
+	mb();
+	while (GET_UINT32(p_iram->idata) != 0xffffffff)
+		;
+
+	return 0;
+}
+
+static int load_fman_ctrl_code(struct fm_t *p_fm)
+{
+	struct fm_iram_regs_t __iomem *p_iram;
+	int i;
+	uint32_t tmp;
+	uint8_t comp_to_16;
+
+	p_iram = (struct fm_iram_regs_t __iomem *)UINT_TO_PTR(p_fm->base_addr +
+						       FM_MM_IMEM);
+
+	/* Enable the auto-increment */
+	WRITE_UINT32(p_iram->iadd, IRAM_IADD_AIE);
+	while (GET_UINT32(p_iram->iadd) != IRAM_IADD_AIE)
+		;
+
+	for (i = 0; i < (p_fm->firmware.size / 4); i++)
+		WRITE_UINT32(p_iram->idata, p_fm->firmware.p_code[i]);
+
+	comp_to_16 = (uint8_t)(p_fm->firmware.size % 16);
+	if (comp_to_16)
+		for (i = 0; i < ((16 - comp_to_16) / 4); i++)
+			WRITE_UINT32(p_iram->idata, 0xffffffff);
+
+	WRITE_UINT32(p_iram->iadd, p_fm->firmware.size - 4);
+	while (GET_UINT32(p_iram->iadd) != (p_fm->firmware.size - 4))
+		;
+
+	/* verify that writing has completed */
+	while (GET_UINT32(p_iram->idata) !=
+	       p_fm->firmware.p_code[(p_fm->firmware.size / 4) - 1])
+		;
+
+	if (p_fm->fw_verify) {
+		WRITE_UINT32(p_iram->iadd, IRAM_IADD_AIE);
+		while (GET_UINT32(p_iram->iadd) != IRAM_IADD_AIE)
+			;
+		for (i = 0; i < (p_fm->firmware.size / 4); i++) {
+			tmp = GET_UINT32(p_iram->idata);
+			if (tmp != p_fm->firmware.p_code[i]) {
+				pr_err("UCode write error : write 0x%x, read 0x%x\n",
+				       p_fm->firmware.p_code[i], tmp);
+				return -EIO;
+			}
+		}
+		WRITE_UINT32(p_iram->iadd, 0x0);
+	}
+
+	/* Enable patch from IRAM */
+	WRITE_UINT32(p_iram->iready, IRAM_READY);
+	usleep_range(1000, 1001);
+
+	pr_debug("FMan-Controller code (ver %d.%d.%d) loaded to IRAM.\n",
+		 ((uint16_t *)p_fm->firmware.p_code)[2],
+		 ((uint8_t *)p_fm->firmware.p_code)[6],
+		 ((uint8_t *)p_fm->firmware.p_code)[7]);
+
+	return 0;
+}
+
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+static int fw_not_reset_erratum_bugzilla6173wa(struct fm_t *p_fm)
+{
+	struct fm_iram_regs_t __iomem *p_iram =
+	    (struct fm_iram_regs_t __iomem *)UINT_TO_PTR(p_fm->base_addr +
+							 FM_MM_IMEM);
+	uint32_t tmp_reg;
+	uint32_t saved_spliodn[63];
+
+	/* write to IRAM first location the debug instruction */
+	WRITE_UINT32(p_iram->iadd, 0);
+	while (GET_UINT32(p_iram->iadd) != 0)
+		;
+
+	WRITE_UINT32(p_iram->idata, FM_FW_DEBUG_INSTRUCTION);
+
+	WRITE_UINT32(p_iram->iadd, 0);
+	while (GET_UINT32(p_iram->iadd) != 0)
+		;
+	while (GET_UINT32(p_iram->idata) != FM_FW_DEBUG_INSTRUCTION)
+		;
+
+	/* Enable patch from IRAM */
+	WRITE_UINT32(p_iram->iready, IRAM_READY);
+	/* Memory barrier */
+	mb();
+	usleep_range(100, 101);
+
+	memcpy_fromio((void *)saved_spliodn,
+		      (void __iomem *)p_fm->p_fm_bmi_regs->fmbm_spliodn,
+		      63 * sizeof(uint32_t));
+
+	/* reset FMAN */
+	WRITE_UINT32(p_fm->p_fm_fpm_regs->fm_rstc, FPM_RSTC_FM_RESET);
+	/* Memory barrier */
+	mb();
+	usleep_range(100, 101);
+
+	/* verify breakpoint debug status register */
+	tmp_reg =
+	    GET_UINT32(*(uint32_t __iomem *)
+		       UINT_TO_PTR(p_fm->base_addr +
+				   FM_DEBUG_STATUS_REGISTER_OFFSET));
+	if (!tmp_reg) {
+		pr_err("Invalid debug status register value is '0'\n");
+		return -ENOSYS;
+	}
+
+	/* Load FMan-Controller code to IRAM */
+
+	if (clear_iram(p_fm) != 0)
+		return -ENOSYS;
+	if (p_fm->firmware.p_code && (load_fman_ctrl_code(p_fm) != 0))
+		return -ENOSYS;
+	usleep_range(100, 101);
+
+	/* reset FMAN again to start the microcode */
+	WRITE_UINT32(p_fm->p_fm_fpm_regs->fm_rstc, FPM_RSTC_FM_RESET);
+	/* Memory barrier */
+	mb();
+	usleep_range(100, 101);
+	memcpy_toio((void __iomem *)p_fm->p_fm_bmi_regs->fmbm_spliodn,
+		    (void *)saved_spliodn, 63 * sizeof(uint32_t));
+
+	if (fman_is_qmi_halt_not_busy_state(p_fm->p_fm_qmi_regs)) {
+		fman_resume(p_fm->p_fm_fpm_regs);
+		/* Memory barrier */
+		mb();
+		usleep_range(100, 101);
+	}
+
+	return 0;
+}
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+/*       Inter-Module functions         */
+
+void fm_register_intr(void *h_fm, enum fm_event_modules module,
+		      uint8_t mod_id, enum fm_intr_type intr_type,
+		      void (*f_isr)(void *h_src_arg), void *h_src_arg)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	int event = 0;
+
+	GET_FM_MODULE_EVENT(p_fm, module, mod_id, intr_type, event);
+	ASSERT(event < FM_EV_DUMMY_LAST);
+
+	/* register in local FM structure */
+	p_fm->intr_mng[event].f_isr = f_isr;
+	p_fm->intr_mng[event].h_src_handle = h_src_arg;
+}
+
+void fm_unregister_intr(void *h_fm, enum fm_event_modules module,
+			uint8_t mod_id, enum fm_intr_type intr_type)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	int event = 0;
+
+	GET_FM_MODULE_EVENT(p_fm, module, mod_id, intr_type, event);
+	ASSERT(event < FM_EV_DUMMY_LAST);
+
+	p_fm->intr_mng[event].f_isr = unimplemented_isr;
+	p_fm->intr_mng[event].h_src_handle = NULL;
+}
+
+uint8_t fm_get_id(void *h_fm)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+	return p_fm->p_fm_state_struct->fm_id;
+}
+
+uint16_t fm_get_clock_freq(void *h_fm)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+	/* for multicore environment: this depends on the
+	 * fact that fm_clk_freq was properly initialized at "init".
+	 */
+	return p_fm->p_fm_state_struct->fm_clk_freq;
+}
+
+uint32_t fm_get_bmi_max_fifo_size(void *h_fm)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+	return p_fm->intg->bmi_max_fifo_size;
+}
+
+static int init_fm_dma(struct fm_t *p_fm)
+{
+	int err;
+
+	err = (int)fman_dma_init(p_fm->p_fm_dma_regs,
+				     p_fm->p_fm_drv_param);
+	if (err != 0)
+		return err;
+
+	/* Allocate MURAM for CAM */
+	p_fm->cam_size = (uint32_t)(p_fm->p_fm_drv_param->
+					dma_cam_num_of_entries *
+					DMA_CAM_SIZEOF_ENTRY);
+	p_fm->cam_base_addr = fm_muram_alloc(p_fm->p_muram, p_fm->cam_size);
+	if (!p_fm->cam_base_addr) {
+		pr_err("MURAM alloc for DMA CAM failed\n");
+		return -ENOMEM;
+	}
+
+	memset_io(UINT_TO_PTR(p_fm->cam_base_addr),
+		  0,
+		  (uint32_t)(p_fm->p_fm_drv_param->dma_cam_num_of_entries *
+			      DMA_CAM_SIZEOF_ENTRY));
+
+	if (p_fm->p_fm_state_struct->rev_info.major_rev == 2) {
+		fm_muram_free_mem(p_fm->p_muram, p_fm->cam_base_addr,
+				  p_fm->cam_size);
+
+		p_fm->cam_size = p_fm->p_fm_drv_param->
+					dma_cam_num_of_entries * 72 + 128;
+		p_fm->cam_base_addr = fm_muram_alloc(p_fm->p_muram, (uint32_t)
+						     p_fm->cam_size);
+		if (!p_fm->cam_base_addr) {
+			pr_err("MURAM alloc for DMA CAM failed\n");
+			return -ENOMEM;
+		}
+
+		memset_io(UINT_TO_PTR(p_fm->cam_base_addr),
+			  0,
+			  (uint32_t)(p_fm->p_fm_drv_param->
+				      dma_cam_num_of_entries * 72 + 128));
+
+		switch (p_fm->p_fm_drv_param->dma_cam_num_of_entries) {
+		case (8):
+			WRITE_UINT32(*(uint32_t __iomem *)p_fm->cam_base_addr,
+				     0xff000000);
+			break;
+		case (16):
+			WRITE_UINT32(*(uint32_t __iomem *)p_fm->cam_base_addr,
+				     0xffff0000);
+			break;
+		case (24):
+			WRITE_UINT32(*(uint32_t __iomem *)p_fm->cam_base_addr,
+				     0xffffff00);
+			break;
+		case (32):
+			WRITE_UINT32(*(uint32_t __iomem *)p_fm->cam_base_addr,
+				     0xffffffff);
+			break;
+		default:
+			pr_err("wrong dma_cam_num_of_entries\n");
+			return -EDOM;
+		}
+	}
+
+	p_fm->p_fm_drv_param->cam_base_addr =
+	    (uint32_t)(virt_to_phys(UINT_TO_PTR(p_fm->cam_base_addr)) -
+			p_fm->fm_muram_phys_base_addr);
+
+	return 0;
+}
+
+static int init_fm_fpm(struct fm_t *p_fm)
+{
+	return (int)fman_fpm_init(p_fm->p_fm_fpm_regs,
+				  p_fm->p_fm_drv_param);
+}
+
+static int init_fm_bmi(struct fm_t *p_fm)
+{
+	return (int)fman_bmi_init(p_fm->p_fm_bmi_regs,
+				  p_fm->p_fm_drv_param);
+}
+
+static int init_fm_qmi(struct fm_t *p_fm)
+{
+	return (int)fman_qmi_init(p_fm->p_fm_qmi_regs,
+				  p_fm->p_fm_drv_param);
+}
+
+/*                      API Init unit functions                              */
+
+void *fm_config(struct fm_params_t *p_fm_param)
+{
+	struct fm_t *p_fm;
+	uintptr_t base_addr;
+
+	if (!((p_fm_param->firmware.p_code && p_fm_param->firmware.size) ||
+	      (!p_fm_param->firmware.p_code && !p_fm_param->firmware.size)))
+		return NULL;
+
+	base_addr = p_fm_param->base_addr;
+
+	/* Allocate FM structure */
+	p_fm = kzalloc(sizeof(*p_fm), GFP_KERNEL);
+	if (!p_fm)
+		return NULL;
+
+	p_fm->p_fm_state_struct = kzalloc(sizeof(*p_fm->p_fm_state_struct),
+						 GFP_KERNEL);
+	if (!p_fm->p_fm_state_struct) {
+		kfree(p_fm);
+		pr_err("FM Status structure\n");
+		return NULL;
+	}
+
+	/* Initialize FM parameters which will be kept by the driver */
+	p_fm->p_fm_state_struct->fm_id = p_fm_param->fm_id;
+
+	/* Allocate the FM driver's parameters structure */
+	p_fm->p_fm_drv_param = kzalloc(sizeof(*p_fm->p_fm_drv_param),
+						 GFP_KERNEL);
+	if (!p_fm->p_fm_drv_param) {
+		kfree(p_fm->p_fm_state_struct);
+		kfree(p_fm);
+		pr_err("FM driver parameters\n");
+		return NULL;
+	}
+
+	/* Initialize FM parameters which will be kept by the driver */
+	p_fm->p_fm_state_struct->fm_id = p_fm_param->fm_id;
+	p_fm->p_muram = p_fm_param->p_muram;
+	p_fm->h_app = p_fm_param->h_app;
+	p_fm->p_fm_state_struct->fm_clk_freq = p_fm_param->fm_clk_freq;
+	p_fm->f_exception = p_fm_param->f_exception;
+	p_fm->f_bus_error = p_fm_param->f_bus_error;
+	p_fm->p_fm_fpm_regs =
+	    (struct fman_fpm_regs __iomem *)UINT_TO_PTR(base_addr + FM_MM_FPM);
+	p_fm->p_fm_bmi_regs =
+	    (struct fman_bmi_regs __iomem *)UINT_TO_PTR(base_addr + FM_MM_BMI);
+	p_fm->p_fm_qmi_regs =
+	    (struct fman_qmi_regs __iomem *)UINT_TO_PTR(base_addr + FM_MM_QMI);
+	p_fm->p_fm_dma_regs =
+	    (struct fman_dma_regs __iomem *)UINT_TO_PTR(base_addr + FM_MM_DMA);
+	p_fm->p_fm_regs = (struct fman_regs __iomem *)
+			   UINT_TO_PTR(base_addr + FM_MM_BMI);
+	p_fm->base_addr = base_addr;
+
+	p_fm->spinlock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+	if (!p_fm->spinlock) {
+		kfree(p_fm->p_fm_drv_param);
+		kfree(p_fm->p_fm_state_struct);
+		kfree(p_fm);
+		pr_err("can't allocate spinlock!\n");
+		return NULL;
+	}
+
+	spin_lock_init(p_fm->spinlock);
+	fman_defconfig(p_fm->p_fm_drv_param);
+
+/* overide macros dependent parameters */
+#ifdef FM_PEDANTIC_DMA
+	if (p_fm->p_fm_state_struct->rev_info.major_rev == 4) {
+		p_fm->p_fm_drv_param->pedantic_dma = true;
+		p_fm->p_fm_drv_param->dma_aid_override = true;
+	}
+#endif /* FM_PEDANTIC_DMA */
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+	if (p_fm->p_fm_state_struct->rev_info.major_rev != 4)
+		p_fm->p_fm_drv_param->qmi_deq_option_support = true;
+#endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+	p_fm->p_fm_state_struct->rams_ecc_enable = false;
+	p_fm->p_fm_state_struct->extra_fifo_pool_size = 0;
+	p_fm->p_fm_state_struct->exceptions = DEFAULT_exceptions;
+	p_fm->reset_on_init = DEFAULT_RESET_ON_INIT;
+	p_fm->fw_verify = DEFAULT_VERIFY_UCODE;
+	p_fm->firmware.size = p_fm_param->firmware.size;
+	if (p_fm->firmware.size) {
+		p_fm->firmware.p_code = kmalloc(p_fm->firmware.size,
+						GFP_KERNEL);
+		if (!p_fm->firmware.p_code) {
+			kfree(p_fm->spinlock);
+			kfree(p_fm->p_fm_state_struct);
+			kfree(p_fm->p_fm_drv_param);
+			kfree(p_fm);
+			pr_err("FM firmware code\n");
+			return NULL;
+		}
+		memcpy(p_fm->firmware.p_code,
+		       p_fm_param->firmware.p_code, p_fm->firmware.size);
+	}
+	/* read revision */
+	/* Chip dependent, will be configured in Init */
+	fman_get_revision(p_fm->p_fm_fpm_regs,
+			  &p_fm->p_fm_state_struct->rev_info.major_rev,
+			  &p_fm->p_fm_state_struct->rev_info.minor_rev);
+
+	p_fm->intg =
+		fill_intg_params(p_fm->p_fm_state_struct->rev_info.major_rev,
+				 p_fm->p_fm_state_struct->rev_info.minor_rev,
+				 p_fm_param);
+	if (!p_fm->intg) {
+			kfree(p_fm->firmware.p_code);
+			kfree(p_fm->spinlock);
+			kfree(p_fm->p_fm_state_struct);
+			kfree(p_fm->p_fm_drv_param);
+			kfree(p_fm);
+			return NULL;
+	}
+
+#ifdef FM_AID_MODE_NO_TNUM_SW005
+	if (p_fm->p_fm_state_struct->rev_info.major_rev >= 6)
+		p_fm->p_fm_drv_param->dma_aid_mode = FM_DMA_AID_OUT_PORT_ID;
+#endif /* FM_AID_MODE_NO_TNUM_SW005 */
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+	if (p_fm->p_fm_state_struct->rev_info.major_rev != 4)
+		p_fm->p_fm_drv_param->qmi_def_tnums_thresh =
+		    p_fm->intg->qmi_def_tnums_thresh;
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+	p_fm->p_fm_state_struct->total_fifo_size = 0;
+	p_fm->p_fm_state_struct->total_num_of_tasks =
+	(u8)DFLT_TOTAL_NUM_OF_TASKS(
+		p_fm->p_fm_state_struct->rev_info.major_rev,
+		p_fm->p_fm_state_struct->rev_info.minor_rev,
+		p_fm->intg->bmi_max_num_of_tasks);
+#ifdef FM_HAS_TOTAL_DMAS
+	if (p_fm->p_fm_state_struct->rev_info.major_rev < 6)
+		p_fm->p_fm_state_struct->max_num_of_open_dmas =
+		p_fm->intg->bmi_max_num_of_dmas;
+#endif /* FM_HAS_TOTAL_DMAS */
+	if (p_fm->p_fm_state_struct->rev_info.major_rev < 6) {
+		p_fm->p_fm_drv_param->dma_comm_qtsh_clr_emer =
+		(u8)DFLT_DMA_COMM_Q_LOW(p_fm->p_fm_state_struct->rev_info.
+				    major_rev,
+				    p_fm->intg->dma_thresh_max_commq);
+
+		p_fm->p_fm_drv_param->dma_comm_qtsh_asrt_emer =
+		(u8)DFLT_DMA_COMM_Q_HIGH(p_fm->p_fm_state_struct->rev_info.
+				     major_rev,
+				     p_fm->intg->dma_thresh_max_commq);
+
+		p_fm->p_fm_drv_param->dma_cam_num_of_entries =
+		DFLT_DMA_CAM_NUM_OF_ENTRIES(p_fm->p_fm_state_struct->
+					    rev_info.major_rev);
+		p_fm->p_fm_drv_param->dma_read_buf_tsh_clr_emer =
+		(u8)DFLT_DMA_READ_INT_BUF_LOW(p_fm->intg->dma_thresh_max_buf);
+
+		p_fm->p_fm_drv_param->dma_read_buf_tsh_asrt_emer =
+		(u8)DFLT_DMA_READ_INT_BUF_HIGH(p_fm->intg->dma_thresh_max_buf);
+
+		p_fm->p_fm_drv_param->dma_write_buf_tsh_clr_emer =
+		(u8)DFLT_DMA_WRITE_INT_BUF_LOW(p_fm->intg->dma_thresh_max_buf);
+
+		p_fm->p_fm_drv_param->dma_write_buf_tsh_asrt_emer =
+		(u8)DFLT_DMA_WRITE_INT_BUF_HIGH(p_fm->intg->dma_thresh_max_buf);
+
+		p_fm->p_fm_drv_param->dma_axi_dbg_num_of_beats =
+		DEFAULT_AXI_DBG_NUM_OF_BEATS;
+		}
+
+#ifdef FM_NO_TNUM_AGING
+	p_fm->p_fm_drv_param->tnum_aging_period = 0;
+#endif /* FM_NO_TNUM_AGING */
+	p_fm->tnum_aging_period = p_fm->p_fm_drv_param->tnum_aging_period;
+
+	return p_fm;
+}
+
+/*     fm_init
+ *
+ *  Initializes the FM module
+ *
+ * @Param[in]     h_fm - FM module descriptor
+ *
+ * @Return        0 on success; Error code otherwise.
+ */
+int fm_init(void *h_fm)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	struct fman_cfg *p_fm_drv_param = NULL;
+	int err = 0;
+	int i;
+	struct fm_revision_info_t rev_info;
+	struct fman_rg fman_rg;
+	int ret, ret_err;
+
+	ret = is_init_done(p_fm->p_fm_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	fman_rg.bmi_rg = p_fm->p_fm_bmi_regs;
+	fman_rg.qmi_rg = p_fm->p_fm_qmi_regs;
+	fman_rg.fpm_rg = p_fm->p_fm_fpm_regs;
+	fman_rg.dma_rg = p_fm->p_fm_dma_regs;
+
+	p_fm->p_fm_state_struct->count1_micro_bit = FM_TIMESTAMP_1_USEC_BIT;
+	p_fm->p_fm_drv_param->num_of_fman_ctrl_evnt_regs =
+	    FM_NUM_OF_FMAN_CTRL_EVENT_REGS;
+
+	/* if user didn't configured total_fifo_size -
+	 * (total_fifo_size=0) we configure default
+	 * according to chip. otherwise, we use user's configuration.
+	 */
+	if (p_fm->p_fm_state_struct->total_fifo_size == 0)
+		p_fm->p_fm_state_struct->total_fifo_size =
+		DFLT_TOTAL_FIFO_SIZE(
+				p_fm->p_fm_state_struct->rev_info.major_rev,
+				p_fm->p_fm_state_struct->rev_info.minor_rev);
+
+	ret_err = check_fm_parameters(p_fm);
+	if (ret_err)
+		return ret_err;
+
+	p_fm_drv_param = p_fm->p_fm_drv_param;
+
+	fm_get_revision(p_fm, &rev_info);
+
+	/* clear revision-dependent non existing exception */
+#ifdef FM_NO_DISPATCH_RAM_ECC
+	if ((rev_info.major_rev != 4) && (rev_info.major_rev < 6))
+		p_fm->p_fm_state_struct->exceptions &=
+		    ~FM_EX_BMI_DISPATCH_RAM_ECC;
+#endif /* FM_NO_DISPATCH_RAM_ECC */
+
+#ifdef FM_QMI_NO_ECC_EXCEPTIONS
+	if (rev_info.major_rev == 4)
+		p_fm->p_fm_state_struct->exceptions &=
+		    ~(FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC);
+#endif /* FM_QMI_NO_ECC_EXCEPTIONS */
+
+#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION
+	if (rev_info.major_rev >= 6)
+		p_fm->p_fm_state_struct->exceptions &= ~FM_EX_QMI_SINGLE_ECC;
+#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */
+
+	fm_muram_clear(p_fm->p_muram);
+
+	/* clear CPG */
+	memset_io(UINT_TO_PTR(p_fm->base_addr + FM_MM_CGP), 0,
+		  p_fm->intg->fm_port_num_of_cg);
+
+	/* add to the default exceptions the user's definitions */
+	p_fm->p_fm_state_struct->exceptions |= p_fm->user_set_exceptions;
+
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+	if (p_fm->p_fm_state_struct->rev_info.major_rev < 6 &&
+	    p_fm->p_fm_state_struct->rev_info.major_rev != 4 &&
+	    p_fm->reset_on_init) {
+		err = fw_not_reset_erratum_bugzilla6173wa(p_fm);
+		if (err != 0)
+			return err;
+	} else {
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+		/* Reset the FM if required. */
+		if (p_fm->reset_on_init) {
+			u32 svr = mfspr(SPRN_SVR);
+
+			if (((SVR_SOC_VER(svr) == SVR_T4240 &&
+			      SVR_REV(svr) > 0x10)) ||
+				((SVR_SOC_VER(svr) == SVR_T4160 &&
+				  SVR_REV(svr) > 0x10)) ||
+				((SVR_SOC_VER(svr) == SVR_T4080 &&
+				  SVR_REV(svr) > 0x10)) ||
+				(SVR_SOC_VER(svr) == SVR_T2080) ||
+				(SVR_SOC_VER(svr) == SVR_T2081)) {
+				pr_debug("Hack: No FM reset!\n");
+			} else {
+				WRITE_UINT32(p_fm->p_fm_fpm_regs->fm_rstc,
+					     FPM_RSTC_FM_RESET);
+				/* Memory barrier */
+				mb();
+				usleep_range(100, 101);
+			}
+
+			if (fman_is_qmi_halt_not_busy_state(
+				p_fm->p_fm_qmi_regs)) {
+				fman_resume(p_fm->p_fm_fpm_regs);
+				usleep_range(100, 101);
+			}
+		}
+
+		/* Load FMan-Controller code to IRAM */
+
+		if (clear_iram(p_fm) != 0)
+			return -ENOSYS;
+		if (p_fm->firmware.p_code && (load_fman_ctrl_code(p_fm) != 0))
+			return -ENOSYS;
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+	}
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+	/* General FM driver initialization */
+	p_fm->fm_muram_phys_base_addr =
+	    (uint64_t)(virt_to_phys
+			(UINT_TO_PTR(p_fm->base_addr + FM_MM_MURAM)));
+
+	for (i = 0; i < FM_EV_DUMMY_LAST; i++)
+		p_fm->intr_mng[i].f_isr = unimplemented_isr;
+
+	p_fm_drv_param->exceptions = p_fm->p_fm_state_struct->exceptions;
+
+	/* Init DMA Registers */
+
+	err = init_fm_dma(p_fm);
+	if (err != 0) {
+		free_init_resources(p_fm);
+		return err;
+	}
+
+	/* Init FPM Registers */
+
+	err = init_fm_fpm(p_fm);
+	if (err != 0) {
+		free_init_resources(p_fm);
+		return err;
+	}
+
+	/* define common resources */
+	/* allocate MURAM for FIFO according to total size */
+	p_fm->fifo_base_addr = fm_muram_alloc(p_fm->p_muram,
+					      p_fm->p_fm_state_struct->
+					      total_fifo_size);
+	if (!p_fm->fifo_base_addr) {
+		free_init_resources(p_fm);
+		pr_err("MURAM alloc for BMI FIFO failed\n");
+		return -ENOMEM;
+	}
+
+	p_fm_drv_param->fifo_base_addr =
+	    (uint32_t)(virt_to_phys(UINT_TO_PTR(p_fm->fifo_base_addr)) -
+			p_fm->fm_muram_phys_base_addr);
+
+	p_fm_drv_param->total_fifo_size = p_fm->p_fm_state_struct->
+					     total_fifo_size;
+	p_fm_drv_param->total_num_of_tasks =
+	    p_fm->p_fm_state_struct->total_num_of_tasks;
+	p_fm_drv_param->clk_freq = p_fm->p_fm_state_struct->fm_clk_freq;
+
+	/* Init BMI Registers */
+
+	err = init_fm_bmi(p_fm);
+	if (err != 0) {
+		free_init_resources(p_fm);
+		return err;
+	}
+
+	/* Init QMI Registers */
+
+	err = init_fm_qmi(p_fm);
+	if (err != 0) {
+		free_init_resources(p_fm);
+		return err;
+	}
+
+	err = (int)fman_enable(&fman_rg, p_fm_drv_param);
+	if (err != 0)
+		return err;	/* FIXME */
+
+	enable_time_stamp(p_fm);
+
+	kfree(p_fm->firmware.p_code);
+	p_fm->firmware.p_code = NULL;
+
+	kfree(p_fm->p_fm_drv_param);
+	p_fm->p_fm_drv_param = NULL;
+
+	return 0;
+}
+
+/* fm_free
+ * Frees all resources that were assigned to FM module.
+ * Calling this routine invalidates the descriptor.
+ * h_fm - FM module descriptor
+ *Return        0 on success; Error code otherwise.
+ */
+int fm_free(void *h_fm)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	struct fman_rg fman_rg;
+
+	fman_rg.bmi_rg = p_fm->p_fm_bmi_regs;
+	fman_rg.qmi_rg = p_fm->p_fm_qmi_regs;
+	fman_rg.fpm_rg = p_fm->p_fm_fpm_regs;
+	fman_rg.dma_rg = p_fm->p_fm_dma_regs;
+
+	fman_free_resources(&fman_rg);
+
+	kfree(p_fm->spinlock);
+
+	if (p_fm->p_fm_drv_param) {
+		kfree(p_fm->firmware.p_code);
+		kfree(p_fm->p_fm_drv_param);
+		p_fm->p_fm_drv_param = NULL;
+	}
+
+	free_init_resources(p_fm);
+
+	kfree(p_fm->p_fm_state_struct);
+
+	kfree(p_fm);
+
+	return 0;
+}
+
+/*       API Advanced Init unit functions        */
+
+int fm_cfg_reset_on_init(void *h_fm, bool enable)
+{
+	int ret;
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+	ret = is_init_done(p_fm->p_fm_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_fm->reset_on_init = enable;
+
+	return 0;
+}
+
+int fm_cfg_total_fifo_size(void *h_fm, uint32_t total_fifo_size)
+{
+	int ret;
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+	ret = is_init_done(p_fm->p_fm_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_fm->p_fm_state_struct->total_fifo_size = total_fifo_size;
+
+	return 0;
+}
+
+int fm_cfg_dma_aid_override(void *h_fm, bool aid_override)
+{
+	int ret;
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+	ret = is_init_done(p_fm->p_fm_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_fm->p_fm_drv_param->dma_aid_override = aid_override;
+
+	return 0;
+}
+
+/*       API Run-time Control uint functions        */
+
+void fm_event_isr(void *h_fm)
+{
+#define FM_M_CALL_MAC_ISR(_id)    \
+	(p_fm->intr_mng[(enum fm_inter_module_event)(FM_EV_MAC0 + _id)]. \
+	f_isr(p_fm->intr_mng[(enum fm_inter_module_event)(FM_EV_MAC0 + _id)] \
+	.h_src_handle))
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	uint32_t pending;
+	int ret;
+	struct fman_fpm_regs __iomem *fpm_rg;
+
+	ret = is_init_done(p_fm->p_fm_drv_param);
+	if (ret)
+		return;
+
+	fpm_rg = p_fm->p_fm_fpm_regs;
+
+	/* normal interrupts */
+	pending = fman_get_normal_pending(fpm_rg);
+	if (!pending)
+		return;
+
+	if (pending & INTR_EN_QMI)
+		qmi_event(p_fm);
+	if (pending & INTR_EN_PRS)
+		p_fm->intr_mng[FM_EV_PRS].f_isr(p_fm->intr_mng[FM_EV_PRS].
+						 h_src_handle);
+	if (pending & INTR_EN_TMR)
+		p_fm->intr_mng[FM_EV_TMR].f_isr(p_fm->intr_mng[FM_EV_TMR].
+						 h_src_handle);
+
+	/* MAC events may belong to different partitions */
+	if (pending & INTR_EN_MAC0)
+		FM_M_CALL_MAC_ISR(0);
+	if (pending & INTR_EN_MAC1)
+		FM_M_CALL_MAC_ISR(1);
+	if (pending & INTR_EN_MAC2)
+		FM_M_CALL_MAC_ISR(2);
+	if (pending & INTR_EN_MAC3)
+		FM_M_CALL_MAC_ISR(3);
+	if (pending & INTR_EN_MAC4)
+		FM_M_CALL_MAC_ISR(4);
+	if (pending & INTR_EN_MAC5)
+		FM_M_CALL_MAC_ISR(5);
+	if (pending & INTR_EN_MAC6)
+		FM_M_CALL_MAC_ISR(6);
+	if (pending & INTR_EN_MAC7)
+		FM_M_CALL_MAC_ISR(7);
+	if (pending & INTR_EN_MAC8)
+		FM_M_CALL_MAC_ISR(8);
+	if (pending & INTR_EN_MAC9)
+		FM_M_CALL_MAC_ISR(9);
+}
+
+int fm_error_isr(void *h_fm)
+{
+#define FM_M_CALL_MAC_ERR_ISR(_id) \
+	(p_fm->intr_mng[(enum fm_inter_module_event)(FM_EV_ERR_MAC0 + _id)]. \
+	f_isr(p_fm->intr_mng[(enum fm_inter_module_event)\
+	(FM_EV_ERR_MAC0 + _id)].h_src_handle))
+
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	uint32_t pending;
+	struct fman_fpm_regs __iomem *fpm_rg;
+	int ret;
+
+	ret = is_init_done(p_fm->p_fm_drv_param);
+	if (ret)
+		return ret;
+
+	fpm_rg = p_fm->p_fm_fpm_regs;
+
+	/* error interrupts */
+	pending = fman_get_fpm_error_interrupts(fpm_rg);
+	if (!pending)
+		return -ENOSYS;
+
+	if (pending & ERR_INTR_EN_BMI)
+		bmi_err_event(p_fm);
+	if (pending & ERR_INTR_EN_QMI)
+		qmi_err_event(p_fm);
+	if (pending & ERR_INTR_EN_FPM)
+		fpm_err_event(p_fm);
+	if (pending & ERR_INTR_EN_DMA)
+		dma_err_event(p_fm);
+	if (pending & ERR_INTR_EN_IRAM)
+		iram_err_intr(p_fm);
+	if (pending & ERR_INTR_EN_MURAM)
+		muram_err_intr(p_fm);
+	if (pending & ERR_INTR_EN_PRS)
+		p_fm->intr_mng[FM_EV_ERR_PRS].f_isr(p_fm->
+						     intr_mng[FM_EV_ERR_PRS].
+						     h_src_handle);
+
+	/* MAC events may belong to different partitions */
+	if (pending & ERR_INTR_EN_MAC0)
+		FM_M_CALL_MAC_ERR_ISR(0);
+	if (pending & ERR_INTR_EN_MAC1)
+		FM_M_CALL_MAC_ERR_ISR(1);
+	if (pending & ERR_INTR_EN_MAC2)
+		FM_M_CALL_MAC_ERR_ISR(2);
+	if (pending & ERR_INTR_EN_MAC3)
+		FM_M_CALL_MAC_ERR_ISR(3);
+	if (pending & ERR_INTR_EN_MAC4)
+		FM_M_CALL_MAC_ERR_ISR(4);
+	if (pending & ERR_INTR_EN_MAC5)
+		FM_M_CALL_MAC_ERR_ISR(5);
+	if (pending & ERR_INTR_EN_MAC6)
+		FM_M_CALL_MAC_ERR_ISR(6);
+	if (pending & ERR_INTR_EN_MAC7)
+		FM_M_CALL_MAC_ERR_ISR(7);
+	if (pending & ERR_INTR_EN_MAC8)
+		FM_M_CALL_MAC_ERR_ISR(8);
+	if (pending & ERR_INTR_EN_MAC9)
+		FM_M_CALL_MAC_ERR_ISR(9);
+
+	return 0;
+}
+
+int fm_disable_rams_ecc(void *h_fm)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	bool explicit_disable = false;
+	struct fman_fpm_regs __iomem *fpm_rg;
+	int ret;
+
+	ret = is_init_done(p_fm->p_fm_drv_param);
+	if (ret)
+		return ret;
+
+	fpm_rg = p_fm->p_fm_fpm_regs;
+
+	if (!p_fm->p_fm_state_struct->internal_call)
+		explicit_disable = true;
+	p_fm->p_fm_state_struct->internal_call = false;
+
+	/* if rams are already disabled, or if rams were explicitly enabled and
+	 *  are currently called indirectly (not explicitly), ignore this call.
+	 */
+	if (!p_fm->p_fm_state_struct->rams_ecc_enable ||
+	    (p_fm->p_fm_state_struct->explicit_enable && !explicit_disable))
+		return 0;
+	if (p_fm->p_fm_state_struct->explicit_enable)
+		/* This is the case were both explicit are true.
+		 * Turn off this flag for cases were following
+		 * ramsEnable routines are called
+		 */
+		p_fm->p_fm_state_struct->explicit_enable = false;
+
+	fman_enable_rams_ecc(fpm_rg);
+	p_fm->p_fm_state_struct->rams_ecc_enable = false;
+
+	return 0;
+}
+
+int fm_set_exception(void *h_fm, enum fm_exceptions exception,
+		     bool enable)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	uint32_t bit_mask = 0;
+	enum fman_exceptions fsl_exception;
+	struct fman_rg fman_rg;
+	int ret;
+
+	ret = is_init_done(p_fm->p_fm_drv_param);
+	if (ret)
+		return ret;
+
+	fman_rg.bmi_rg = p_fm->p_fm_bmi_regs;
+	fman_rg.qmi_rg = p_fm->p_fm_qmi_regs;
+	fman_rg.fpm_rg = p_fm->p_fm_fpm_regs;
+	fman_rg.dma_rg = p_fm->p_fm_dma_regs;
+
+	GET_EXCEPTION_FLAG(bit_mask, exception);
+	if (bit_mask) {
+		if (enable)
+			p_fm->p_fm_state_struct->exceptions |= bit_mask;
+		else
+			p_fm->p_fm_state_struct->exceptions &= ~bit_mask;
+
+		FMAN_EXCEPTION_TRANS(fsl_exception, exception);
+
+		return (int)fman_set_exception(&fman_rg,
+					       fsl_exception, enable);
+	} else {
+		pr_err("Undefined exceptioni\n");
+		return -EDOM;
+	}
+
+	return 0;
+}
+
+int fm_get_revision(void *h_fm, struct fm_revision_info_t
+			*p_fm_revision_info)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+	p_fm_revision_info->major_rev = p_fm->p_fm_state_struct->
+					rev_info.major_rev;
+	p_fm_revision_info->minor_rev = p_fm->p_fm_state_struct->
+					rev_info.minor_rev;
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/fm.h b/drivers/net/ethernet/freescale/fman/fm.h
new file mode 100644
index 0000000..ba5bb16
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm.h
@@ -0,0 +1,486 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM internal structures and definitions. */
+#ifndef __FM_H
+#define __FM_H
+
+#include "service.h"
+#include "fm_ext.h"
+
+#include "fsl_fman.h"
+
+#define FM_MAX_NUM_OF_HW_PORT_IDS           64
+#define FM_MAX_NUM_OF_GUESTS                100
+
+/* Exceptions */
+/* DMA bus error. */
+#define FM_EX_DMA_BUS_ERROR                 0x80000000
+#define FM_EX_DMA_READ_ECC                  0x40000000
+#define FM_EX_DMA_SYSTEM_WRITE_ECC          0x20000000
+#define FM_EX_DMA_FM_WRITE_ECC              0x10000000
+/* Stall of tasks on FPM */
+#define FM_EX_FPM_STALL_ON_TASKS            0x08000000
+/* Single ECC on FPM */
+#define FM_EX_FPM_SINGLE_ECC                0x04000000
+#define FM_EX_FPM_DOUBLE_ECC                0x02000000
+/* Single ECC on FPM */
+#define FM_EX_QMI_SINGLE_ECC                0x01000000
+/* Dequeu from default queue id */
+#define FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID   0x00800000
+#define FM_EX_QMI_DOUBLE_ECC                0x00400000
+#define FM_EX_BMI_LIST_RAM_ECC              0x00200000
+#define FM_EX_BMI_STORAGE_PROFILE_ECC       0x00100000
+#define FM_EX_BMI_STATISTICS_RAM_ECC        0x00080000
+#define FM_EX_IRAM_ECC                      0x00040000
+#define FM_EX_MURAM_ECC                     0x00020000
+#define FM_EX_BMI_DISPATCH_RAM_ECC          0x00010000
+#define FM_EX_DMA_SINGLE_PORT_ECC           0x00008000
+
+#define DMA_EMSR_EMSTR_MASK                 0x0000FFFF
+
+#define DMA_THRESH_COMMQ_MASK               0xFF000000
+#define DMA_THRESH_READ_INT_BUF_MASK        0x007F0000
+#define DMA_THRESH_WRITE_INT_BUF_MASK       0x0000007F
+
+#define GET_EXCEPTION_FLAG(bit_mask, exception)			\
+do {									\
+	switch ((int)exception) {					\
+	case FM_EX_DMA_BUS_ERROR:					\
+		bit_mask = FM_EX_DMA_BUS_ERROR;			\
+		break;							\
+	case FM_EX_DMA_SINGLE_PORT_ECC:				\
+		bit_mask = FM_EX_DMA_SINGLE_PORT_ECC;			\
+		break;							\
+	case FM_EX_DMA_READ_ECC:					\
+		bit_mask = FM_EX_DMA_READ_ECC;				\
+		break;							\
+	case FM_EX_DMA_SYSTEM_WRITE_ECC:				\
+		bit_mask = FM_EX_DMA_SYSTEM_WRITE_ECC;			\
+		break;							\
+	case FM_EX_DMA_FM_WRITE_ECC:					\
+		bit_mask = FM_EX_DMA_FM_WRITE_ECC;			\
+		break;							\
+	case FM_EX_FPM_STALL_ON_TASKS:					\
+		bit_mask = FM_EX_FPM_STALL_ON_TASKS;			\
+		break;							\
+	case FM_EX_FPM_SINGLE_ECC:					\
+		bit_mask = FM_EX_FPM_SINGLE_ECC;			\
+		break;							\
+	case FM_EX_FPM_DOUBLE_ECC:					\
+		bit_mask = FM_EX_FPM_DOUBLE_ECC;			\
+		break;							\
+	case FM_EX_QMI_SINGLE_ECC:					\
+		bit_mask = FM_EX_QMI_SINGLE_ECC;			\
+		break;							\
+	case FM_EX_QMI_DOUBLE_ECC:					\
+		bit_mask = FM_EX_QMI_DOUBLE_ECC;			\
+		break;							\
+	case FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID:			\
+		bit_mask = FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID;		\
+		break;							\
+	case FM_EX_BMI_LIST_RAM_ECC:					\
+		bit_mask = FM_EX_BMI_LIST_RAM_ECC;			\
+		break;							\
+	case FM_EX_BMI_STORAGE_PROFILE_ECC:				\
+		bit_mask = FM_EX_BMI_STORAGE_PROFILE_ECC;		\
+		break;							\
+	case FM_EX_BMI_STATISTICS_RAM_ECC:				\
+		bit_mask = FM_EX_BMI_STATISTICS_RAM_ECC;		\
+		break;							\
+	case FM_EX_BMI_DISPATCH_RAM_ECC:				\
+		bit_mask = FM_EX_BMI_DISPATCH_RAM_ECC;			\
+		break;							\
+	case FM_EX_IRAM_ECC:						\
+		bit_mask = FM_EX_IRAM_ECC;				\
+		break;							\
+	case FM_EX_MURAM_ECC:						\
+		bit_mask = FM_EX_MURAM_ECC;				\
+		break;							\
+	default:							\
+		bit_mask = 0;						\
+		break;							\
+	}								\
+} while (0)
+
+#define GET_FM_MODULE_EVENT(_p_fm, _mod, _id, _intr_type, _event)	\
+do {									\
+	switch (_mod) {							\
+	case (FM_MOD_PRS):						\
+		if (_id)						\
+			_event = FM_EV_DUMMY_LAST;			\
+		else							\
+			event = (_intr_type == FM_INTR_TYPE_ERR) ?	\
+			FM_EV_ERR_PRS : FM_EV_PRS;			\
+		break;							\
+	case (FM_MOD_TMR):						\
+		if (_id)						\
+			_event = FM_EV_DUMMY_LAST;			\
+		else							\
+			_event = (_intr_type == FM_INTR_TYPE_ERR) ?	\
+			FM_EV_DUMMY_LAST : FM_EV_TMR;			\
+		break;							\
+	case (FM_MOD_MAC):						\
+			_event = (_intr_type == FM_INTR_TYPE_ERR) ?	\
+			(FM_EV_ERR_MAC0 + _id) :			\
+			(FM_EV_MAC0 + _id);				\
+		break;							\
+	case (FM_MOD_FMAN_CTRL):					\
+		if (_intr_type == FM_INTR_TYPE_ERR)			\
+			_event = FM_EV_DUMMY_LAST;			\
+		else							\
+			_event = (FM_EV_FMAN_CTRL_0 + _id);		\
+		break;							\
+	default:							\
+		_event = FM_EV_DUMMY_LAST;				\
+		break;							\
+	}								\
+} while (0)
+
+#define FMAN_EXCEPTION_TRANS(fsl_exception, _exception) do {\
+switch ((int)_exception) {\
+case  FM_EX_DMA_BUS_ERROR:                    \
+	fsl_exception =  E_FMAN_EX_DMA_BUS_ERROR;\
+	break;    \
+case  FM_EX_DMA_READ_ECC:                    \
+	fsl_exception =  E_FMAN_EX_DMA_READ_ECC;\
+	break;        \
+case  FM_EX_DMA_SYSTEM_WRITE_ECC:                \
+	fsl_exception =  E_FMAN_EX_DMA_SYSTEM_WRITE_ECC;\
+	break;    \
+case  FM_EX_DMA_FM_WRITE_ECC:                    \
+	fsl_exception =  E_FMAN_EX_DMA_FM_WRITE_ECC;\
+	break;    \
+case  FM_EX_FPM_STALL_ON_TASKS:                \
+	fsl_exception =  E_FMAN_EX_FPM_STALL_ON_TASKS;\
+	break;    \
+case  FM_EX_FPM_SINGLE_ECC:                    \
+	fsl_exception =  E_FMAN_EX_FPM_SINGLE_ECC;\
+	break;    \
+case  FM_EX_FPM_DOUBLE_ECC:                    \
+	fsl_exception =  E_FMAN_EX_FPM_DOUBLE_ECC;\
+	break;    \
+case  FM_EX_QMI_SINGLE_ECC:                    \
+	fsl_exception =  E_FMAN_EX_QMI_SINGLE_ECC;\
+	break;    \
+case  FM_EX_QMI_DOUBLE_ECC:                    \
+	fsl_exception =  E_FMAN_EX_QMI_DOUBLE_ECC;\
+	break;    \
+case  FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID:            \
+	fsl_exception =  E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID;\
+	break; \
+case  FM_EX_BMI_LIST_RAM_ECC:                    \
+	fsl_exception =  E_FMAN_EX_BMI_LIST_RAM_ECC;\
+	break;    \
+case  FM_EX_BMI_STORAGE_PROFILE_ECC:                    \
+	fsl_exception =  E_FMAN_EX_BMI_STORAGE_PROFILE_ECC;\
+	break;    \
+case  FM_EX_BMI_STATISTICS_RAM_ECC:                \
+	fsl_exception =  E_FMAN_EX_BMI_STATISTICS_RAM_ECC;\
+	break; \
+case  FM_EX_BMI_DISPATCH_RAM_ECC:                \
+	fsl_exception =  E_FMAN_EX_BMI_DISPATCH_RAM_ECC;\
+	break;    \
+case  FM_EX_IRAM_ECC:                        \
+	fsl_exception =  E_FMAN_EX_IRAM_ECC;\
+	break;        \
+case  FM_EX_MURAM_ECC:                    \
+	fsl_exception =  E_FMAN_EX_MURAM_ECC;\
+	break;        \
+default: \
+	fsl_exception =  E_FMAN_EX_DMA_BUS_ERROR; break;    \
+} \
+} while (0)
+
+/* defaults */
+#define DEFAULT_exceptions	\
+(FM_EX_DMA_BUS_ERROR            | \
+FM_EX_DMA_READ_ECC              | \
+FM_EX_DMA_SYSTEM_WRITE_ECC      | \
+FM_EX_DMA_FM_WRITE_ECC          | \
+FM_EX_FPM_STALL_ON_TASKS        | \
+FM_EX_FPM_SINGLE_ECC            | \
+FM_EX_FPM_DOUBLE_ECC            | \
+FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID | \
+FM_EX_BMI_LIST_RAM_ECC          | \
+FM_EX_BMI_STORAGE_PROFILE_ECC   | \
+FM_EX_BMI_STATISTICS_RAM_ECC    | \
+FM_EX_IRAM_ECC                  | \
+FM_EX_MURAM_ECC                 | \
+FM_EX_BMI_DISPATCH_RAM_ECC      | \
+FM_EX_QMI_DOUBLE_ECC            | \
+FM_EX_QMI_SINGLE_ECC)
+
+#ifdef FM_PEDANTIC_DMA
+#define DEFAULT_aid_override(major)          (major == 4 ? : true : false)
+#else
+#define DEFAULT_aid_override(major)          false
+#endif /* FM_PEDANTIC_DMA */
+#define DEFAULT_AXI_DBG_NUM_OF_BEATS            1
+#define DEFAULT_RESET_ON_INIT                 false
+/* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_VERIFY_UCODE                 false
+
+#define DFLT_DMA_READ_INT_BUF_LOW(dma_thresh_max_buf)	\
+	((dma_thresh_max_buf + 1) / 2)
+#define DFLT_DMA_READ_INT_BUF_HIGH(dma_thresh_max_buf)	\
+	((dma_thresh_max_buf + 1) * 3 / 4)
+#define DFLT_DMA_WRITE_INT_BUF_LOW(dma_thresh_max_buf)	\
+	((dma_thresh_max_buf + 1) / 2)
+#define DFLT_DMA_WRITE_INT_BUF_HIGH(dma_thresh_max_buf)\
+	((dma_thresh_max_buf + 1) * 3 / 4)
+
+#define DFLT_DMA_COMM_Q_LOW(major, dma_thresh_max_commq)	\
+	((major == 6) ? 0x2A : ((dma_thresh_max_commq + 1) / 2))
+
+#define DFLT_DMA_COMM_Q_HIGH(major, dma_thresh_max_commq)	\
+	((major == 6) ? 0x3f : ((dma_thresh_max_commq + 1) * 3 / 4))
+
+#define DFLT_TOTAL_NUM_OF_TASKS(major, minor, bmi_max_num_of_tasks)	\
+	((major == 6) ? ((minor == 1 || minor == 4) ? 59 : 124) :	\
+	bmi_max_num_of_tasks)
+
+#define DFLT_CACHE_OVERRIDE			FM_DMA_NO_CACHE_OR
+#define DFLT_DMA_CAM_NUM_OF_ENTRIES(major)	(major == 6 ? 64 : 32)
+#define DFLT_DMA_EN_EMERGENCY			false
+#define DFLT_DMA_SOS_EMERGENCY			0
+#define DFLT_DMA_WATCH_DOG			0
+#define DFLT_DMA_EN_EMERGENCY_SMOOTHER		false
+#define DFLT_DMA_EMERGENCY_SWITCH_COUNTER	0
+
+#define DFLT_DISP_LIMIT				0
+#define DFLT_PRS_DISP_TH			16
+#define DFLT_BMI_DISP_TH			16
+#define DFLT_QMI_ENQ_DISP_TH			16
+#define DFLT_QMI_DEQ_DISP_TH			16
+#define DFLT_FM_CTL1_DISP_TH			16
+#define DFLT_FM_CTL2_DISP_TH			16
+
+#define DFLT_TOTAL_FIFO_SIZE(major, minor)			\
+	((major == 6) ?						\
+	((minor == 1 || minor == 4) ? (156 * 1024) : (295 * 1024)) :	\
+	(((major == 2) || (major == 5)) ?			\
+	(100 * 1024) : ((major == 4) ?			\
+	(46 * 1024) : (122 * 1024))))
+
+#define FM_TIMESTAMP_1_USEC_BIT             8
+
+/* Defines used for enabling/disabling FM interrupts */
+#define ERR_INTR_EN_DMA         0x00010000
+#define ERR_INTR_EN_FPM         0x80000000
+#define ERR_INTR_EN_BMI         0x00800000
+#define ERR_INTR_EN_QMI         0x00400000
+#define ERR_INTR_EN_PRS         0x00200000
+#define ERR_INTR_EN_MURAM       0x00040000
+#define ERR_INTR_EN_IRAM        0x00020000
+#define ERR_INTR_EN_MAC8        0x00008000
+#define ERR_INTR_EN_MAC9        0x00000040
+#define ERR_INTR_EN_MAC0        0x00004000
+#define ERR_INTR_EN_MAC1        0x00002000
+#define ERR_INTR_EN_MAC2        0x00001000
+#define ERR_INTR_EN_MAC3        0x00000800
+#define ERR_INTR_EN_MAC4        0x00000400
+#define ERR_INTR_EN_MAC5        0x00000200
+#define ERR_INTR_EN_MAC6        0x00000100
+#define ERR_INTR_EN_MAC7        0x00000080
+
+#define INTR_EN_QMI             0x40000000
+#define INTR_EN_PRS             0x20000000
+#define INTR_EN_MAC0            0x00080000
+#define INTR_EN_MAC1            0x00040000
+#define INTR_EN_MAC2            0x00020000
+#define INTR_EN_MAC3            0x00010000
+#define INTR_EN_MAC4            0x00000040
+#define INTR_EN_MAC5            0x00000020
+#define INTR_EN_MAC6            0x00000008
+#define INTR_EN_MAC7            0x00000002
+#define INTR_EN_MAC8            0x00200000
+#define INTR_EN_MAC9            0x00100000
+#define INTR_EN_REV0            0x00008000
+#define INTR_EN_REV1            0x00004000
+#define INTR_EN_REV2            0x00002000
+#define INTR_EN_REV3            0x00001000
+#define INTR_EN_BRK             0x00000080
+#define INTR_EN_TMR             0x01000000
+
+/* Modules registers offsets */
+#define FM_MM_MURAM             0x00000000
+#define FM_MM_BMI               0x00080000
+#define FM_MM_QMI               0x00080400
+#define FM_MM_PRS               0x000c7000
+#define FM_MM_DMA               0x000C2000
+#define FM_MM_FPM               0x000C3000
+#define FM_MM_IMEM              0x000C4000
+#define FM_MM_CGP               0x000DB000
+#define FM_MM_TRB(i)            (0x000D0200 + 0x400 * (i))
+#define FM_MM_SP                0x000dc000
+
+/* Memory Mapped Registers */
+
+struct fm_iram_regs_t {
+	uint32_t iadd;	/* FM IRAM instruction address register */
+	uint32_t idata;/* FM IRAM instruction data register */
+	uint32_t itcfg;/* FM IRAM timing config register */
+	uint32_t iready;/* FM IRAM ready register */
+	uint8_t res[0x80000 - 0x10];
+} __attribute__((__packed__));
+
+/* General defines */
+#define FM_DEBUG_STATUS_REGISTER_OFFSET     0x000d1084UL
+#define FM_FW_DEBUG_INSTRUCTION             0x6ffff805UL
+
+/* FPM defines */
+/* masks */
+#define FPM_BRKC_RDBG                   0x00000200
+/* BMI defines */
+/* masks */
+#define BMI_INIT_START                      0x80000000
+#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000
+#define BMI_ERR_INTR_EN_LIST_RAM_ECC        0x40000000
+#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC  0x20000000
+#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC    0x10000000
+/* QMI defines */
+/* masks */
+#define QMI_ERR_INTR_EN_DOUBLE_ECC      0x80000000
+#define QMI_ERR_INTR_EN_DEQ_FROM_DEF    0x40000000
+#define QMI_INTR_EN_SINGLE_ECC          0x80000000
+
+/* IRAM defines */
+/* masks */
+#define IRAM_IADD_AIE                   0x80000000
+#define IRAM_READY                      0x80000000
+
+/* TRB defines */
+/* masks */
+#define TRB_TCRH_RESET              0x04000000
+#define TRB_TCRH_ENABLE_COUNTERS    0x84008000
+#define TRB_TCRH_DISABLE_COUNTERS   0x8400C000
+#define TRB_TCRL_RESET              0x20000000
+#define TRB_TCRL_UTIL               0x00000460
+
+struct fm_state_struct_t {
+/* Master/Guest parameters */
+
+	uint8_t fm_id;
+	uint16_t fm_clk_freq;
+	struct fm_revision_info_t rev_info;
+
+/* Master Only parameters */
+
+	bool enabled_time_stamp;
+	uint8_t count1_micro_bit;
+	uint8_t total_num_of_tasks;
+	uint32_t total_fifo_size;
+	uint8_t max_num_of_open_dmas;
+	uint8_t accumulated_num_of_tasks;
+	uint32_t accumulated_fifo_size;
+	uint8_t accumulated_num_of_open_dmas;
+	uint8_t accumulated_num_of_deq_tnums;
+#ifdef FM_LOW_END_RESTRICTION
+	bool low_end_restriction;
+#endif /* FM_LOW_END_RESTRICTION */
+	uint32_t exceptions;
+	bool rams_ecc_enable;
+	bool explicit_enable;
+	bool internal_call;
+	uint8_t rams_ecc_owners;
+	uint32_t extra_fifo_pool_size;
+	uint8_t extra_tasks_pool_size;
+	uint8_t extra_open_dmas_pool_size;
+};
+
+struct fm_intg_t {
+	/* Ram defines */
+	uint32_t fm_muram_size;
+	uint32_t fm_iram_size;
+	uint32_t fm_num_of_ctrl;
+
+	/* DMA defines */
+	uint32_t dma_thresh_max_commq;
+	uint32_t dma_thresh_max_buf;
+
+	/* QMI defines */
+	uint32_t qmi_max_num_of_tnums;
+	uint32_t qmi_def_tnums_thresh;
+
+	/* BMI defines */
+	uint32_t bmi_max_num_of_tasks;
+	uint32_t bmi_max_num_of_dmas;
+	uint32_t bmi_max_fifo_size;
+	uint32_t port_max_weight;
+
+	uint32_t fm_port_num_of_cg;
+	uint32_t num_of_rx_ports;
+};
+
+struct fm_t {
+/* locals for recovery */
+	uintptr_t base_addr;
+
+/* un-needed for recovery */
+	char fm_module_name[MODULE_NAME_SIZE];
+	/* FM exceptions user callback */
+	struct fm_intr_src_t intr_mng[FM_EV_DUMMY_LAST];
+
+/* Master Only parameters */
+
+/* locals for recovery */
+	struct fman_fpm_regs __iomem *p_fm_fpm_regs;
+	struct fman_bmi_regs __iomem *p_fm_bmi_regs;
+	struct fman_qmi_regs __iomem *p_fm_qmi_regs;
+	struct fman_dma_regs __iomem *p_fm_dma_regs;
+	struct fman_regs __iomem *p_fm_regs;
+	fm_exceptions_cb *f_exception;
+	fm_bus_error_cb *f_bus_error;
+	void *h_app;		/* Application handle */
+	spinlock_t *spinlock;
+	struct fm_state_struct_t *p_fm_state_struct;
+	uint16_t tnum_aging_period;
+
+/* un-needed for recovery */
+	struct fman_cfg *p_fm_drv_param;
+	struct muram_info *p_muram;
+	phys_addr_t fm_muram_phys_base_addr;
+	uintptr_t cam_base_addr;	/* save for freeing */
+	uint32_t cam_size;
+	uintptr_t res_addr;
+	uintptr_t fifo_base_addr;	/* save for freeing */
+	uint32_t fifo_size;
+	struct fm_firmware_params_t firmware;
+	bool fw_verify;
+	bool reset_on_init;
+	uint32_t user_set_exceptions;
+
+	struct fm_intg_t *intg;
+};
+
+#endif /* __FM_H */
diff --git a/drivers/net/ethernet/freescale/fman/fm_common.h b/drivers/net/ethernet/freescale/fman/fm_common.h
new file mode 100644
index 0000000..f9d6575
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm_common.h
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* File          fm_common.h
+ * Description   FM internal structures and definitions.
+ */
+#ifndef __FM_COMMON_H
+#define __FM_COMMON_H
+
+#include "service.h"
+#include "fm_ext.h"
+
+#define CLS_PLAN_NUM_PER_GRP                        8
+
+/* list_object
+ * Macro to get the struct (object) for this entry.
+ * type   - The type of the struct (object) this list
+ * is embedded in.
+ * member - The name of the struct list_head object
+ * within the struct.
+ * Return        The structure pointer for this entry.
+ */
+#define member_offset(type, member) (PTR_TO_UINT(&((type *)0)->member))
+#define list_object(p_list, type, member) \
+((type *)((char *)(p_list) - member_offset(type, member)))
+
+/* Enum for inter-module interrupts registration */
+enum fm_event_modules {
+	FM_MOD_PRS = 0,		/* Parser event */
+	FM_MOD_MAC,		/* MAC event */
+	FM_MOD_TMR,		/* Timer event */
+	FM_MOD_FMAN_CTRL,	/* FMAN Controller  Timer event */
+	FM_MOD_DUMMY_LAST
+};
+
+/* Enum for interrupts types */
+enum fm_intr_type {
+	FM_INTR_TYPE_ERR,
+	FM_INTR_TYPE_NORMAL
+};
+
+/* Enum for inter-module interrupts registration */
+enum fm_inter_module_event {
+	FM_EV_PRS = 0,		/* Parser event */
+	FM_EV_ERR_PRS,		/* Parser error event */
+	FM_EV_ERR_MAC8,		/* MAC 8 error event */
+	FM_EV_ERR_MAC9,		/* MAC 9 error event */
+	FM_EV_ERR_MAC0,		/* MAC 0 error event */
+	FM_EV_ERR_MAC1,		/* MAC 1 error event */
+	FM_EV_ERR_MAC2,		/* MAC 2 error event */
+	FM_EV_ERR_MAC3,		/* MAC 3 error event */
+	FM_EV_ERR_MAC4,		/* MAC 4 error event */
+	FM_EV_ERR_MAC5,		/* MAC 5 error event */
+	FM_EV_ERR_MAC6,		/* MAC 6 error event */
+	FM_EV_ERR_MAC7,		/* MAC 7 error event */
+	FM_EV_TMR,		/* Timer event */
+	FM_EV_MAC8,		/* MAC 8 event (Magic packet detection)*/
+	FM_EV_MAC9,		/* MAC 9 event (Magic packet detection)*/
+	FM_EV_MAC0,		/* MAC 0 event (Magic packet detection)*/
+	FM_EV_MAC1,		/* MAC 1 event (Magic packet detection)*/
+	FM_EV_MAC2,		/* MAC 2 (Magic packet detection)*/
+	FM_EV_MAC3,		/* MAC 3 (Magic packet detection)*/
+	FM_EV_MAC4,		/* MAC 4 (Magic packet detection)*/
+	FM_EV_MAC5,		/* MAC 5 (Magic packet detection)*/
+	FM_EV_MAC6,		/* MAC 6 (Magic packet detection)*/
+	FM_EV_MAC7,		/* MAC 7 (Magic packet detection)*/
+	FM_EV_FMAN_CTRL_0,	/* Fman controller event 0 */
+	FM_EV_FMAN_CTRL_1,	/* Fman controller event 1 */
+	FM_EV_FMAN_CTRL_2,	/* Fman controller event 2 */
+	FM_EV_FMAN_CTRL_3,	/* Fman controller event 3 */
+	FM_EV_DUMMY_LAST
+};
+
+/* FM IP BLOCK versions */
+#define FM_IP_BLOCK_P1			4
+#define FM_IP_BLOCK_P2_P3_P5		3
+#define FM_IP_BLOCK_P4			2
+#define FM_IP_BLOCK_B_T			6
+
+/*for UNDER_CONSTRUCTION_FM_RMU_USE_SEC its defined in fm_ext.h*/
+typedef uint32_t fm_fman_ctrl_t;
+
+#define FPM_PORT_FM_CTL1                0x00000001
+#define FPM_PORT_FM_CTL2                0x00000002
+
+static inline bool TRY_LOCK(spinlock_t *spinlock, volatile bool *p_flag)
+{
+	unsigned long int_flags;
+
+	if (spinlock)
+		spin_lock_irqsave(spinlock, int_flags);
+	else
+		local_irq_save(int_flags);
+
+	if (*p_flag) {
+		if (spinlock)
+			spin_unlock_irqrestore(spinlock, int_flags);
+		else
+			local_irq_restore(int_flags);
+		return false;
+	}
+	*p_flag = true;
+
+	if (spinlock)
+		spin_unlock_irqrestore(spinlock, int_flags);
+	else
+		local_irq_restore(int_flags);
+
+	return true;
+}
+
+#define RELEASE_LOCK(_flag) (_flag = false)
+
+/* Defines used for manipulation CC and BMI */
+#define INTERNAL_CONTEXT_OFFSET                 0x80000000
+#define OFFSET_OF_PR                            0x40000000
+#define NUM_OF_TASKS                            0x10000000
+#define OFFSET_OF_DATA                          0x08000000
+#define HW_PORT_ID                              0x04000000
+#define FM_REV                                  0x02000000
+#define GET_NIA_FPNE                            0x01000000
+#define GET_NIA_PNDN                            0x00800000
+#define NUM_OF_EXTRA_TASKS                      0x00400000
+#define DISCARD_MASK                            0x00200000
+
+#define UPDATE_NIA_PNEN                         0x80000000
+#define UPDATE_PSO                              0x40000000
+#define UPDATE_NIA_PNDN                         0x20000000
+#define UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY      0x10000000
+#define UPDATE_NIA_FENE                         0x04000000
+#define UPDATE_NIA_CMNE                         0x02000000
+#define UPDATE_NIA_FPNE                         0x01000000
+
+/* Defines used for manipulation CC and CC */
+#define UPDATE_NIA_ENQ_WITHOUT_DMA              0x80000000
+
+#define MODULE_NAME_SIZE        30
+#define DUMMY_PORT_ID           0
+
+#define FM_LIODN_OFFSET_MASK    0x3FF
+
+/* Description        CTRL Parameters Page defines */
+#define FM_CTL_PARAMS_PAGE_OP_FIX_EN            0x80000000
+#define FM_CTL_PARAMS_PAGE_ALWAYS_ON            0x00000100
+
+#define FM_CTL_PARAMS_PAGE_ERROR_VSP_MASK       0x0000003f
+
+#define BMI_MAX_FIFO_SIZE                   (FM_MURAM_SIZE)
+#define BMI_FIFO_UNITS                      0x100
+
+struct fm_intr_src_t {
+	void (*f_isr)(void *h_src_arg);
+	void *h_src_handle;
+};
+
+#define ILLEGAL_HDR_NUM                     0xFF
+#define NO_HDR_NUM                          FM_PCD_PRS_NUM_OF_HDRS
+
+#define IS_PRIVATE_HEADER(hdr)	(((hdr) == HEADER_TYPE_USER_DEFINED_SHIM1) || \
+				 ((hdr) == HEADER_TYPE_USER_DEFINED_SHIM2))
+
+#define GET_PRS_HDR_NUM(num, hdr) do {\
+switch (hdr) { \
+case (HEADER_TYPE_ETH):\
+	num = 0;  break;   \
+case (HEADER_TYPE_LLC_SNAP):\
+	num = 1;  break;   \
+case (HEADER_TYPE_VLAN):\
+	num = 2;  break;   \
+case (HEADER_TYPE_PPPOE):\
+	num = 3;  break;   \
+case (HEADER_TYPE_PPP):\
+	num = 3;  break;   \
+case (HEADER_TYPE_MPLS):\
+	num = 4;  break;   \
+case (HEADER_TYPE_IPV4):\
+	num = 5;  break;   \
+case (HEADER_TYPE_IPV6):\
+	num = 6;  break;   \
+case (HEADER_TYPE_GRE):\
+	num = 7;  break;   \
+case (HEADER_TYPE_MINENCAP):\
+	num = 8;  break;   \
+case (HEADER_TYPE_USER_DEFINED_L3):\
+	num = 9;  break;   \
+case (HEADER_TYPE_TCP):\
+	num = 10; break;   \
+case (HEADER_TYPE_UDP):\
+	num = 11; break;   \
+case (HEADER_TYPE_IPSEC_AH): \
+case (HEADER_TYPE_IPSEC_ESP):\
+	num = 12; break;   \
+case (HEADER_TYPE_SCTP):\
+	num = 13; break;   \
+case (HEADER_TYPE_DCCP):\
+	num = 14; break;   \
+case (HEADER_TYPE_USER_DEFINED_L4):\
+	num = 15; break;   \
+case (HEADER_TYPE_USER_DEFINED_SHIM1):                  \
+case (HEADER_TYPE_USER_DEFINED_SHIM2):                  \
+	num = NO_HDR_NUM; break;                            \
+default:                                                \
+	pr_err("Unsupported header for parser\n");\
+	num = ILLEGAL_HDR_NUM; break;                       \
+} \
+} while (0)
+
+#define FM_PCD_MAX_NUM_OF_OPTIONS(cls_plan_entries)   \
+((cls_plan_entries == 256) ? 8 : ((cls_plan_entries == 128) ? 7 : \
+((cls_plan_entries == 64) ? 6 : ((cls_plan_entries == 32) ? 5 : 0))))
+
+/* Function      fm_register_intr
+ * Description   Used to register
+ * an inter-module event handler to be processed by FM
+ * Param[in]     h_fm            A handle to an FM Module.
+ * Param[in]     mod             The module that causes the event
+ * Param[in]     mod_id           Module id - if more than 1 instance of this
+ *				mode exists,0 otherwise.
+ * Param[in]     intr_type        Interrupt type (error/normal) selection.
+ * Param[in]     f_isr           The interrupt service routine.
+ * Param[in]     h_src_arg           Argument to be passed to f_isr.
+ * Return        None.
+ */
+void fm_register_intr(void *h_fm,
+		      enum fm_event_modules mod,
+		      uint8_t mod_id,
+		      enum fm_intr_type intr_type,
+		      void (*f_isr)(void *h_src_arg), void *h_src_arg);
+
+/* Function      fm_unregister_intr
+ * Description   Used to un-register an
+ * inter-module event handler that was processed by FM
+ * Param[in]     h_fm            A handle to an FM Module.
+ * Param[in]     mod             The module that causes the event
+ * Param[in]     mod_id           Module id - if more than 1 instance of this
+ *				mode exists,0 otherwise.
+ * Param[in]     intr_type        Interrupt type (error/normal) selection.
+ * Return        None.
+ */
+void fm_unregister_intr(void *h_fm,
+			enum fm_event_modules mod,
+			uint8_t mod_id, enum fm_intr_type intr_type);
+
+/* Description   enum for defining MAC types */
+enum fm_mac_type {
+	FM_MAC_10G = 0,	    /* 10G MAC */
+	FM_MAC_1G	    /* 1G MAC */
+};
+
+/* Function      fm_get_muram_pointer
+ * Description   Get the pointer of the MURAM from the FM module
+ * Param[in]     h_fm            A handle to an FM Module.
+ * Return        MURAM module pointer.
+ */
+struct muram_info *fm_get_muram_pointer(void *h_fm);
+
+/* Function      fm_get_physical_muram_base
+ * Description   Get the physical base address of the MURAM from the FM module
+ * Param[in]     h_fm            A handle to an FM Module.
+ * Param[in]     fm_phys_addr      Physical MURAM base
+ * Return        Physical base address.
+ */
+void fm_get_physical_muram_base(void *h_fm,
+				struct fm_phys_addr_t *fm_phys_addr);
+
+/* Function      fm_get_clock_freq
+ * Description   Used by MAC driver to get the FM clock frequency
+ * Param[in]     h_fm            A handle to an FM Module.
+ * Return        clock-freq on success; 0 otherwise.
+ * Cautions      Allowed only following fm_init().
+ */
+uint16_t fm_get_clock_freq(void *h_fm);
+
+/*Function      fm_get_id
+ * Description   Used by PCD driver to read rhe FM id
+ * Param[in]     h_fm            A handle to an FM Module.
+ * Return        0 on success; Error code otherwise.
+ * Cautions      Allowed only following fm_init().
+ */
+uint8_t fm_get_id(void *h_fm);
+
+void fm_muram_clear(struct muram_info *p_muram);
+int fm_set_num_of_open_dmas(void *h_fm,
+			    uint8_t port_id,
+			    uint8_t *p_num_of_open_dmas,
+			    uint8_t *p_num_of_extra_open_dmas,
+			    bool initial_config);
+int fm_set_num_of_tasks(void *h_fm,
+			uint8_t port_id,
+			uint8_t *p_num_of_tasks,
+			uint8_t *p_num_of_extra_tasks,
+			bool initial_config);
+int fm_set_size_of_fifo(void *h_fm,
+			uint8_t port_id,
+			uint32_t *p_size_of_fifo,
+			uint32_t *p_extra_size_of_fifo,
+			bool initial_config);
+
+uint32_t fm_get_bmi_max_fifo_size(void *h_fm);
+struct num_of_ports_info_t *fm_get_num_of_ports(void *h_fm);
+
+#endif /* __FM_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/fm_drv.c b/drivers/net/ethernet/freescale/fman/fm_drv.c
new file mode 100644
index 0000000..2d8db7f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm_drv.c
@@ -0,0 +1,856 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#include <asm/qe.h>		/* For struct qe_firmware */
+#include <sysdev/fsl_soc.h>
+#include <linux/stat.h>		/* For file access mask */
+#include <linux/skbuff.h>
+
+/* Internal services */
+#include "service.h"
+#include "fm_ext.h"
+#include "fm_drv.h"
+#include "fm_muram_ext.h"
+
+/* Bootarg used to override the Kconfig FSL_FM_MAX_FRAME_SIZE value */
+#define FSL_FM_MAX_FRM_BOOTARG     "fsl_fm_max_frm"
+
+/* Bootarg used to override FSL_FM_RX_EXTRA_HEADROOM Kconfig value */
+#define FSL_FM_RX_EXTRA_HEADROOM_BOOTARG  "fsl_fm_rx_extra_headroom"
+
+/* Minimum and maximum value for the fsl_fm_rx_extra_headroom bootarg */
+#define FSL_FM_RX_EXTRA_HEADROOM_MIN 16
+#define FSL_FM_RX_EXTRA_HEADROOM_MAX 384
+
+/* Max frame size, across all interfaces.
+ * Configurable from Kconfig or bootargs, to avoid allocating oversized
+ * (socket) buffers when not using jumbo frames.
+ * Must be large enough to accommodate the network MTU, but small enough
+ * to avoid wasting skb memory.
+ *
+ * Could be overridden once, at boot-time, via the
+ * fm_set_max_frm() callback.
+ */
+int fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+
+/* Extra headroom for Rx buffers.
+ * FMan is instructed to allocate, on the Rx path, this amount of
+ * space at the beginning of a data buffer, beside the DPA private
+ * data area and the IC fields.
+ * Does not impact Tx buffer layout.
+ * Configurable from Kconfig or bootargs. Zero by default, it's needed on
+ * particular forwarding scenarios that add extra headers to the
+ * forwarded frame.
+ */
+int fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+
+static struct lnx_wrp_fm_t lnx_wrp_fm;
+
+u16 fm_get_max_frm(void)
+{
+	return fsl_fm_max_frm;
+}
+EXPORT_SYMBOL(fm_get_max_frm);
+
+int fm_get_rx_extra_headroom(void)
+{
+	return ALIGN(fsl_fm_rx_extra_headroom, 16);
+}
+EXPORT_SYMBOL(fm_get_rx_extra_headroom);
+
+static int __init fm_set_max_frm(char *str)
+{
+	int ret = 0;
+
+	ret = get_option(&str, &fsl_fm_max_frm);
+	if (ret != 1) {
+		/* This will only work if CONFIG_EARLY_PRINTK is compiled in,
+		 * and something like "earlyprintk=serial,uart0,115200" is
+		 * specified in the bootargs.
+		 */
+		pr_err("No suitable %s=<int> prop in bootargs; will use the default FSL_FM_MAX_FRAME_SIZE (%d) from Kconfig.\n",
+		       FSL_FM_MAX_FRM_BOOTARG,
+		       CONFIG_FSL_FM_MAX_FRAME_SIZE);
+
+		fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+		return 1;
+	}
+
+	/* Don't allow invalid bootargs; fallback to the Kconfig value */
+	if (fsl_fm_max_frm < 64 || fsl_fm_max_frm > 9600) {
+		pr_err("Invalid %s=%d in bootargs, valid range is 64-9600. Falling back to the FSL_FM_MAX_FRAME_SIZE (%d) from Kconfig.\n",
+		       FSL_FM_MAX_FRM_BOOTARG, fsl_fm_max_frm,
+		       CONFIG_FSL_FM_MAX_FRAME_SIZE);
+
+		fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+		return 1;
+	}
+
+	pr_info("Using fsl_fm_max_frm=%d from bootargs\n", fsl_fm_max_frm);
+	return 0;
+}
+
+early_param(FSL_FM_MAX_FRM_BOOTARG, fm_set_max_frm);
+
+static int __init fm_set_rx_extra_headroom(char *str)
+{
+	int ret;
+
+	ret = get_option(&str, &fsl_fm_rx_extra_headroom);
+
+	if (ret != 1) {
+		pr_err("No suitable %s=<int> prop in bootargs; will use the default FSL_FM_RX_EXTRA_HEADROOM (%d) from Kconfig.\n",
+		       FSL_FM_RX_EXTRA_HEADROOM_BOOTARG,
+		       CONFIG_FSL_FM_RX_EXTRA_HEADROOM);
+		fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+
+		return 1;
+	}
+
+	if (fsl_fm_rx_extra_headroom < FSL_FM_RX_EXTRA_HEADROOM_MIN ||
+	    fsl_fm_rx_extra_headroom > FSL_FM_RX_EXTRA_HEADROOM_MAX) {
+		pr_err("Invalid value for %s=%d prop in bootargs; will use the default FSL_FM_RX_EXTRA_HEADROOM (%d) from Kconfig.\n",
+		       FSL_FM_RX_EXTRA_HEADROOM_BOOTARG,
+		       fsl_fm_rx_extra_headroom,
+		       CONFIG_FSL_FM_RX_EXTRA_HEADROOM);
+		fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+	}
+
+	pr_info("Using fsl_fm_rx_extra_headroom=%d from bootargs\n",
+		fsl_fm_rx_extra_headroom);
+
+	return 0;
+}
+
+early_param(FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, fm_set_rx_extra_headroom);
+
+static irqreturn_t fm_irq(int irq, void *_dev)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+					(struct lnx_wrp_fm_dev_t *)_dev;
+
+	if (!p_lnx_wrp_fm_dev || !p_lnx_wrp_fm_dev->h_dev)
+		return IRQ_NONE;
+
+	fm_event_isr(p_lnx_wrp_fm_dev->h_dev);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t fm_err_irq(int irq, void *_dev)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+					(struct lnx_wrp_fm_dev_t *)_dev;
+
+	if (!p_lnx_wrp_fm_dev || !p_lnx_wrp_fm_dev->h_dev)
+		return IRQ_NONE;
+
+	if (fm_error_isr(p_lnx_wrp_fm_dev->h_dev) == 0)
+		return IRQ_HANDLED;
+
+	return IRQ_NONE;
+}
+
+/* used to protect FMD from concurrent calls in functions
+ * fm_mutex_lock / fm_mutex_unlock
+ */
+static struct mutex lnxwrp_mutex;
+
+static struct lnx_wrp_fm_dev_t *create_fm_dev(uint8_t id)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+
+	p_lnx_wrp_fm_dev = kzalloc(sizeof(*p_lnx_wrp_fm_dev), GFP_KERNEL);
+	if (!p_lnx_wrp_fm_dev)
+		return NULL;
+
+	return p_lnx_wrp_fm_dev;
+}
+
+static void destroy_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+	kfree(p_lnx_wrp_fm_dev);
+}
+
+/**
+*find_fman_microcode - find the Fman microcode
+ *
+*This function returns a pointer to the QE Firmware blob that holds
+*the Fman microcode.  We use the QE Firmware structure because Fman microcode
+*is similar to QE microcode, so there's no point in defining a new layout.
+ *
+*Current versions of U-Boot embed the Fman firmware into the device tree,
+*so we check for that first.  Each Fman node in the device tree contains a
+*node or a pointer to node that holds the firmware.  Technically, we should
+*be fetching the firmware node for the current Fman, but we don't have that
+*information any more, so we assume that there is only one firmware node in
+*the device tree, and that all Fmen use the same firmware.
+ */
+static const struct qe_firmware *find_fman_microcode(void)
+{
+	static const struct qe_firmware *p4080_uc_patch;
+	struct device_node *np;
+
+	if (p4080_uc_patch)
+		return p4080_uc_patch;
+
+	/* The firmware should be inside the device tree. */
+	np = of_find_compatible_node(NULL, NULL, "fsl,fman-firmware");
+	if (np) {
+		p4080_uc_patch = of_get_property(np, "fsl,firmware", NULL);
+		of_node_put(np);
+		if (p4080_uc_patch)
+			return p4080_uc_patch;
+
+		pr_info("firmware node is incomplete\n");
+	}
+
+	/* Returning NULL here forces the reuse of the IRAM content */
+	return NULL;
+}
+
+static int fill_qman_channhels_info(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+	p_lnx_wrp_fm_dev->qman_channels = kcalloc(
+				p_lnx_wrp_fm_dev->num_of_qman_channels,
+				sizeof(uint32_t),
+				GFP_KERNEL);
+	if (!p_lnx_wrp_fm_dev->qman_channels)
+		return -ENOMEM;
+
+	if (p_lnx_wrp_fm_dev->fm_rev_info.major_rev >= 6) {
+		p_lnx_wrp_fm_dev->qman_channels[0] = 0x30;
+		p_lnx_wrp_fm_dev->qman_channels[1] = 0x31;
+		p_lnx_wrp_fm_dev->qman_channels[2] = 0x28;
+		p_lnx_wrp_fm_dev->qman_channels[3] = 0x29;
+		p_lnx_wrp_fm_dev->qman_channels[4] = 0x2a;
+		p_lnx_wrp_fm_dev->qman_channels[5] = 0x2b;
+		p_lnx_wrp_fm_dev->qman_channels[6] = 0x2c;
+		p_lnx_wrp_fm_dev->qman_channels[7] = 0x2d;
+		p_lnx_wrp_fm_dev->qman_channels[8] = 0x2;
+		p_lnx_wrp_fm_dev->qman_channels[9] = 0x3;
+		p_lnx_wrp_fm_dev->qman_channels[10] = 0x4;
+		p_lnx_wrp_fm_dev->qman_channels[11] = 0x5;
+		p_lnx_wrp_fm_dev->qman_channels[12] = 0x6;
+		p_lnx_wrp_fm_dev->qman_channels[13] = 0x7;
+	} else {
+		p_lnx_wrp_fm_dev->qman_channels[0] = 0x30;
+		p_lnx_wrp_fm_dev->qman_channels[1] = 0x28;
+		p_lnx_wrp_fm_dev->qman_channels[2] = 0x29;
+		p_lnx_wrp_fm_dev->qman_channels[3] = 0x2a;
+		p_lnx_wrp_fm_dev->qman_channels[4] = 0x2b;
+		p_lnx_wrp_fm_dev->qman_channels[5] = 0x2c;
+		p_lnx_wrp_fm_dev->qman_channels[6] = 0x1;
+		p_lnx_wrp_fm_dev->qman_channels[7] = 0x2;
+		p_lnx_wrp_fm_dev->qman_channels[8] = 0x3;
+		p_lnx_wrp_fm_dev->qman_channels[9] = 0x4;
+		p_lnx_wrp_fm_dev->qman_channels[10] = 0x5;
+		p_lnx_wrp_fm_dev->qman_channels[11] = 0x6;
+	}
+
+	return 0;
+}
+
+#define SVR_SECURITY_MASK    0x00080000
+#define SVR_PERSONALITY_MASK 0x0000FF00
+#define SVR_VER_IGNORE_MASK (SVR_SECURITY_MASK | SVR_PERSONALITY_MASK)
+#define SVR_B4860_REV1_VALUE 0x86800010
+#define SVR_B4860_REV2_VALUE 0x86800020
+
+static struct lnx_wrp_fm_dev_t *read_fm_dev_tree_node(struct platform_device
+							*of_dev)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+	struct device_node *fm_node, *dev_node;
+	struct of_device_id name; /* used temporarily */
+	struct resource res;
+	const uint32_t *uint32_prop;
+	int lenp, err;
+	struct clk *clk;
+	u32 clk_rate;
+	u8 cell_index;
+
+	fm_node = of_node_get(of_dev->dev.of_node);
+
+	uint32_prop =
+	    (uint32_t *)of_get_property(fm_node, "cell-index", &lenp);
+	if (unlikely(!uint32_prop)) {
+		pr_err("of_get_property(%s, cell-index) failed\n",
+		       fm_node->full_name);
+		goto _return_null;
+	}
+	if (WARN_ON(lenp != sizeof(uint32_t)))
+		return NULL;
+
+	cell_index = (u8)*uint32_prop;
+	p_lnx_wrp_fm_dev = create_fm_dev(cell_index);
+	if (!p_lnx_wrp_fm_dev)
+		goto _return_null;
+	p_lnx_wrp_fm_dev->dev = &of_dev->dev;
+	p_lnx_wrp_fm_dev->id = cell_index;
+
+	/* Get the FM interrupt */
+	p_lnx_wrp_fm_dev->irq = of_irq_to_resource(fm_node, 0, NULL);
+	if (unlikely(p_lnx_wrp_fm_dev->irq == /*NO_IRQ */ 0)) {
+		pr_err("of_irq_to_resource() = %d\n", NO_IRQ);
+		goto _return_null;
+	}
+
+	/* Get the FM error interrupt */
+	p_lnx_wrp_fm_dev->err_irq = of_irq_to_resource(fm_node, 1, NULL);
+
+	/* Get the FM address */
+	err = of_address_to_resource(fm_node, 0, &res);
+	if (unlikely(err < 0)) {
+		pr_err("of_address_to_resource() = %d\n", err);
+		goto _return_null;
+	}
+
+	p_lnx_wrp_fm_dev->fm_base_addr = 0;
+	p_lnx_wrp_fm_dev->fm_phys_base_addr = res.start;
+	p_lnx_wrp_fm_dev->fm_mem_size = res.end + 1 - res.start;
+
+	clk = clk_get(p_lnx_wrp_fm_dev->dev,
+		      p_lnx_wrp_fm_dev->id == 0 ? "fm0clk" : "fm1clk");
+	if (IS_ERR(clk)) {
+		pr_err("Failed to get FM%d clock structure\n",
+		       p_lnx_wrp_fm_dev->id);
+		goto _return_null;
+	}
+
+	clk_rate = clk_get_rate(clk);
+	if (!clk_rate) {
+		pr_err("Failed to determine FM%d clock rate\n",
+		       p_lnx_wrp_fm_dev->id);
+		goto _return_null;
+	}
+	/* Rounding to MHz */
+	clk_rate = (clk_rate + 500000) / 1000000;
+	p_lnx_wrp_fm_dev->params.fm_clk_freq = (u16)clk_rate;
+
+	uint32_prop =
+	    (uint32_t *)of_get_property(fm_node,
+					"fsl,qman-channel-range",
+					&lenp);
+	if (unlikely(!uint32_prop)) {
+		pr_err("of_get_property(%s, fsl,qman-channel-range) failed\n",
+		       fm_node->full_name);
+		goto _return_null;
+	}
+	if (WARN_ON(lenp != sizeof(uint32_t) * 2))
+		goto _return_null;
+	p_lnx_wrp_fm_dev->qman_channel_base = uint32_prop[0];
+	p_lnx_wrp_fm_dev->num_of_qman_channels = uint32_prop[1];
+
+	/* Get the MURAM base address and size */
+	memset(&name, 0, sizeof(name));
+	if (WARN_ON(strlen("muram") >= sizeof(name.name)))
+		goto _return_null;
+	strcpy(name.name, "muram");
+	if (WARN_ON(strlen("fsl,fman-muram") >= sizeof(name.compatible)))
+		goto _return_null;
+	strcpy(name.compatible, "fsl,fman-muram");
+	for_each_child_of_node(fm_node, dev_node) {
+		if (likely(of_match_node(&name, dev_node))) {
+			err = of_address_to_resource(dev_node, 0, &res);
+			if (unlikely(err < 0)) {
+				pr_err("of_address_to_resource() = %d\n",
+				       err);
+				goto _return_null;
+			}
+
+			p_lnx_wrp_fm_dev->fm_muram_base_addr = 0;
+			p_lnx_wrp_fm_dev->fm_muram_phys_base_addr = res.start;
+			p_lnx_wrp_fm_dev->fm_muram_mem_size =
+							res.end + 1 - res.start;
+			{
+				/* In B4 rev 2.0 (and above) the MURAM size is
+				 * 512KB.
+				 * Check the SVR and update MURAM size if
+				 * required.
+				 */
+				uint32_t svr;
+
+				svr = mfspr(SPRN_SVR);
+
+				if ((svr & ~SVR_VER_IGNORE_MASK) >=
+				    SVR_B4860_REV2_VALUE)
+					p_lnx_wrp_fm_dev->fm_muram_mem_size =
+									0x80000;
+			}
+		}
+	}
+
+	of_node_put(fm_node);
+
+	p_lnx_wrp_fm_dev->active = true;
+
+	goto _return;
+
+_return_null:
+	of_node_put(fm_node);
+	return NULL;
+_return:
+	return p_lnx_wrp_fm_dev;
+}
+
+static void lnxwrp_fm_dev_exceptions_cb(void *h_app,
+					enum fm_exceptions
+					__maybe_unused exception)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+					(struct lnx_wrp_fm_dev_t *)h_app;
+
+	ASSERT(p_lnx_wrp_fm_dev);
+
+	pr_debug("got fm exception %d\n", exception);
+}
+
+static void lnxwrp_fm_dev_bus_error_cb(void *h_app,
+				       enum fm_port_type
+				       __maybe_unused port_type,
+				       uint8_t __maybe_unused port_id,
+				       uint64_t __maybe_unused addr,
+				       uint8_t __maybe_unused tnum,
+				       uint16_t __maybe_unused liodn)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+					(struct lnx_wrp_fm_dev_t *)h_app;
+
+	ASSERT(p_lnx_wrp_fm_dev);
+}
+
+uint32_t get_qman_channel_id(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev,
+			     uint32_t port_id,
+			     enum fm_port_type port_type,
+			     enum fm_port_speed port_speed)
+{
+	uint32_t qman_channel = 0;
+	int i;
+
+	for (i = 0; i < p_lnx_wrp_fm_dev->num_of_qman_channels; i++) {
+		if (p_lnx_wrp_fm_dev->qman_channels[i] == port_id)
+			break;
+	}
+
+	if (i == p_lnx_wrp_fm_dev->num_of_qman_channels)
+		return 0;
+
+	qman_channel = p_lnx_wrp_fm_dev->qman_channel_base + i;
+
+	return qman_channel;
+}
+
+static int configure_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+	int err;
+
+	if (!p_lnx_wrp_fm_dev->active) {
+		pr_err("FM not configured!\n");
+		return -ENOSYS;
+	}
+
+#ifndef MODULE
+	err = can_request_irq(p_lnx_wrp_fm_dev->irq, 0);
+	if (unlikely(err < 0)) {
+		pr_err("can_request_irq() = %d\n", err);
+		return -ENOSYS;
+	}
+#endif
+	err = devm_request_irq(p_lnx_wrp_fm_dev->dev,
+			       p_lnx_wrp_fm_dev->irq,
+				  fm_irq,
+				  IRQF_NO_SUSPEND,
+				  "fman",
+				  p_lnx_wrp_fm_dev);
+	if (unlikely(err < 0)) {
+		pr_err("request_irq(%d) = %d\n", p_lnx_wrp_fm_dev->irq,
+		       err);
+		return -ENOSYS;
+	}
+
+	if (p_lnx_wrp_fm_dev->err_irq != 0) {
+#ifndef MODULE
+		err = can_request_irq(p_lnx_wrp_fm_dev->err_irq, 0);
+		if (unlikely(err < 0)) {
+			pr_err("can_request_irq() = %d\n", err);
+			return -ENOSYS;
+		}
+#endif
+		err = devm_request_irq(p_lnx_wrp_fm_dev->dev,
+				       p_lnx_wrp_fm_dev->err_irq,
+					  fm_err_irq,
+					  IRQF_SHARED | IRQF_NO_SUSPEND,
+					  "fman-err",
+					  p_lnx_wrp_fm_dev);
+		if (unlikely(err < 0)) {
+			pr_err("request_irq(%d) = %d\n",
+			       p_lnx_wrp_fm_dev->err_irq, err);
+			return -ENOSYS;
+		}
+	}
+
+	p_lnx_wrp_fm_dev->res =
+	    devm_request_mem_region(p_lnx_wrp_fm_dev->dev,
+				    p_lnx_wrp_fm_dev->fm_phys_base_addr,
+				    p_lnx_wrp_fm_dev->fm_mem_size, "fman");
+	if (unlikely(!p_lnx_wrp_fm_dev->res)) {
+		pr_err("request_mem_region() failed\n");
+		return -ENOSYS;
+	}
+
+	p_lnx_wrp_fm_dev->fm_base_addr =
+	    PTR_TO_UINT(devm_ioremap
+			(p_lnx_wrp_fm_dev->dev,
+			 p_lnx_wrp_fm_dev->fm_phys_base_addr,
+			 p_lnx_wrp_fm_dev->fm_mem_size));
+	if (unlikely(p_lnx_wrp_fm_dev->fm_base_addr == 0)) {
+		pr_err("devm_ioremap() failed\n");
+		return -ENOSYS;
+	}
+
+	p_lnx_wrp_fm_dev->params.base_addr = p_lnx_wrp_fm_dev->fm_base_addr;
+	p_lnx_wrp_fm_dev->params.fm_id = p_lnx_wrp_fm_dev->id;
+	p_lnx_wrp_fm_dev->params.f_exception = lnxwrp_fm_dev_exceptions_cb;
+	p_lnx_wrp_fm_dev->params.f_bus_error = lnxwrp_fm_dev_bus_error_cb;
+	p_lnx_wrp_fm_dev->params.h_app = p_lnx_wrp_fm_dev;
+
+	return 0;
+}
+
+static int init_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+	const struct qe_firmware *fw;
+
+	if (!p_lnx_wrp_fm_dev->active) {
+		pr_err("FM not configured!!!\n");
+		return -ENOSYS;
+	}
+
+	p_lnx_wrp_fm_dev->p_muram =
+		fm_muram_init(p_lnx_wrp_fm_dev->fm_muram_phys_base_addr,
+			      p_lnx_wrp_fm_dev->fm_muram_mem_size);
+	if (!p_lnx_wrp_fm_dev->p_muram) {
+		pr_err("FM-MURAM!\n");
+		return -ENOSYS;
+	}
+
+	fw = find_fman_microcode();
+
+	if (!fw) {
+		/* this forces the reuse of the current IRAM content */
+		p_lnx_wrp_fm_dev->params.firmware.size = 0;
+		p_lnx_wrp_fm_dev->params.firmware.p_code = NULL;
+	} else {
+		p_lnx_wrp_fm_dev->params.firmware.p_code =
+			(void *)fw + fw->microcode[0].code_offset;
+		p_lnx_wrp_fm_dev->params.firmware.size =
+			sizeof(u32) * fw->microcode[0].count;
+		pr_debug("Loading fman-controller code version %d.%d.%d\n",
+			 fw->microcode[0].major, fw->microcode[0].minor,
+			 fw->microcode[0].revision);
+	}
+
+	p_lnx_wrp_fm_dev->params.p_muram = p_lnx_wrp_fm_dev->p_muram;
+
+	p_lnx_wrp_fm_dev->h_dev = fm_config(&p_lnx_wrp_fm_dev->params);
+	if (!p_lnx_wrp_fm_dev->h_dev) {
+		pr_err("FM\n");
+		return -ENOSYS;
+	}
+
+	if (fm_get_revision(p_lnx_wrp_fm_dev->h_dev,
+			    &p_lnx_wrp_fm_dev->fm_rev_info) != 0) {
+		pr_err("FM\n");
+		return -ENOSYS;
+	}
+
+	if (fm_cfg_reset_on_init(p_lnx_wrp_fm_dev->h_dev, true) != 0) {
+		pr_err("FM\n");
+		return -ENOSYS;
+	}
+	/* Config fm_cfg_dma_aid_override for P1023 */
+	if (p_lnx_wrp_fm_dev->fm_rev_info.major_rev == 4)
+		if (fm_cfg_dma_aid_override(p_lnx_wrp_fm_dev->h_dev,
+					    true) != 0) {
+			pr_err("FM\n");
+			return -ENOSYS;
+		}
+	/* Config total fifo size for FManV3H */
+	if ((p_lnx_wrp_fm_dev->fm_rev_info.major_rev >= 6) &&
+	    (p_lnx_wrp_fm_dev->fm_rev_info.minor_rev != 1 &&
+	     p_lnx_wrp_fm_dev->fm_rev_info.minor_rev != 4))
+			fm_cfg_total_fifo_size(p_lnx_wrp_fm_dev->h_dev,
+					       295 * 1024);
+
+	if (fm_init(p_lnx_wrp_fm_dev->h_dev) != 0) {
+		pr_err("FM\n");
+		return -ENOSYS;
+	}
+
+	/* TODO: Why we mask these interrupts? */
+	if (p_lnx_wrp_fm_dev->err_irq == 0) {
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_DMA_BUS_ERROR, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_DMA_READ_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_DMA_SYSTEM_WRITE_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_DMA_FM_WRITE_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_DMA_SINGLE_PORT_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_FPM_STALL_ON_TASKS, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_FPM_SINGLE_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_FPM_DOUBLE_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_QMI_SINGLE_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_QMI_DOUBLE_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_BMI_LIST_RAM_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_BMI_STORAGE_PROFILE_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_BMI_STATISTICS_RAM_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+				 FM_EX_BMI_DISPATCH_RAM_ECC, false);
+		fm_set_exception(p_lnx_wrp_fm_dev->h_dev, FM_EX_IRAM_ECC,
+				 false);
+		/* TODO: _fm_disable_rams_ecc assert for rams_ecc_owners.
+		 * fm_set_exception(p_lnx_wrp_fm_dev->h_dev,FM_EX_MURAM_ECC,
+		 *		    false);
+		 */
+	}
+
+	if (unlikely(fill_qman_channhels_info(p_lnx_wrp_fm_dev) < 0)) {
+		pr_err("can't fill qman channel info\n");
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
+static void free_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+	if (!p_lnx_wrp_fm_dev->active)
+		return;
+
+	if (p_lnx_wrp_fm_dev->h_dev)
+		fm_free(p_lnx_wrp_fm_dev->h_dev);
+
+	if (p_lnx_wrp_fm_dev->p_muram)
+		fm_muram_free(p_lnx_wrp_fm_dev->p_muram);
+
+	devm_iounmap(p_lnx_wrp_fm_dev->dev,
+		     UINT_TO_PTR(p_lnx_wrp_fm_dev->fm_base_addr));
+	devm_release_mem_region(p_lnx_wrp_fm_dev->dev,
+				p_lnx_wrp_fm_dev->fm_phys_base_addr,
+				p_lnx_wrp_fm_dev->fm_mem_size);
+	if (p_lnx_wrp_fm_dev->err_irq != 0) {
+		devm_free_irq(p_lnx_wrp_fm_dev->dev, p_lnx_wrp_fm_dev->err_irq,
+			      p_lnx_wrp_fm_dev);
+	}
+
+	devm_free_irq(p_lnx_wrp_fm_dev->dev, p_lnx_wrp_fm_dev->irq,
+		      p_lnx_wrp_fm_dev);
+}
+
+/* FMan character device file operations */
+static const struct file_operations fm_fops;
+
+static int /*__devinit*/ fm_probe(struct platform_device *of_dev)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+
+	p_lnx_wrp_fm_dev = read_fm_dev_tree_node(of_dev);
+	if (!p_lnx_wrp_fm_dev)
+		return -EIO;
+	if (configure_fm_dev(p_lnx_wrp_fm_dev) != 0)
+		return -EIO;
+	if (init_fm_dev(p_lnx_wrp_fm_dev) != 0)
+		return -EIO;
+
+	dev_set_drvdata(p_lnx_wrp_fm_dev->dev, p_lnx_wrp_fm_dev);
+
+	pr_debug("FM%d probed\n", p_lnx_wrp_fm_dev->id);
+
+	return 0;
+}
+
+static int fm_remove(struct platform_device *of_dev)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+	struct device *dev;
+
+	dev = &of_dev->dev;
+	p_lnx_wrp_fm_dev = dev_get_drvdata(dev);
+
+	free_fm_dev(p_lnx_wrp_fm_dev);
+
+	destroy_fm_dev(p_lnx_wrp_fm_dev);
+
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id fm_match[] = {
+	{
+	 .compatible = "fsl,fman"},
+	{}
+};
+
+#ifndef MODULE
+MODULE_DEVICE_TABLE(of, fm_match);
+#endif /* !MODULE */
+
+static struct platform_driver fm_driver = {
+	.driver = {
+		   .name = "fsl-fman",
+		   .of_match_table = fm_match,
+		   .owner = THIS_MODULE,
+		   },
+	.probe = fm_probe,
+	.remove = fm_remove
+};
+
+void *lnxwrp_fm_init(void)
+{
+	memset(&lnx_wrp_fm, 0, sizeof(lnx_wrp_fm));
+	mutex_init(&lnxwrp_mutex);
+
+	/* Register to the DTB for basic FM API */
+	platform_driver_register(&fm_driver);
+
+	return &lnx_wrp_fm;
+}
+
+int lnxwrp_fm_free(void *h_lnx_wrp_fm)
+{
+	platform_driver_unregister(&fm_driver);
+	mutex_destroy(&lnxwrp_mutex);
+
+	return 0;
+}
+
+struct fm *fm_bind(struct device *fm_dev)
+{
+	return (struct fm *)(dev_get_drvdata(get_device(fm_dev)));
+}
+EXPORT_SYMBOL(fm_bind);
+
+void fm_unbind(struct fm *fm)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+						(struct lnx_wrp_fm_dev_t *)fm;
+
+	put_device(p_lnx_wrp_fm_dev->dev);
+}
+EXPORT_SYMBOL(fm_unbind);
+
+struct resource *fm_get_mem_region(struct fm *fm)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+						(struct lnx_wrp_fm_dev_t *)fm;
+
+	return p_lnx_wrp_fm_dev->res;
+}
+EXPORT_SYMBOL(fm_get_mem_region);
+
+void *fm_get_handle(struct fm *fm)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+						(struct lnx_wrp_fm_dev_t *)fm;
+
+	return (void *)p_lnx_wrp_fm_dev->h_dev;
+}
+EXPORT_SYMBOL(fm_get_handle);
+
+
+void fm_mutex_lock(void)
+{
+	mutex_lock(&lnxwrp_mutex);
+}
+EXPORT_SYMBOL(fm_mutex_lock);
+
+void fm_mutex_unlock(void)
+{
+	mutex_unlock(&lnxwrp_mutex);
+}
+EXPORT_SYMBOL(fm_mutex_unlock);
+
+static void *h_fm_lnx_wrp;
+
+static int __init __cold fm_load(void)
+{
+	h_fm_lnx_wrp = lnxwrp_fm_init();
+	if (!h_fm_lnx_wrp) {
+		pr_err("Failed to init FM wrapper!\n");
+		return -ENODEV;
+	}
+
+	pr_info("Freescale FM module\n");
+	return 0;
+}
+
+static void __exit __cold fm_unload(void)
+{
+	if (h_fm_lnx_wrp)
+		lnxwrp_fm_free(h_fm_lnx_wrp);
+}
+
+module_init(fm_load);
+module_exit(fm_unload);
diff --git a/drivers/net/ethernet/freescale/fman/fm_drv.h b/drivers/net/ethernet/freescale/fman/fm_drv.h
new file mode 100644
index 0000000..de69965
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm_drv.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FM_DRV_H__
+#define __FM_DRV_H__
+
+#include "service.h"
+#include "fsl_fman_drv.h"
+
+#ifndef CONFIG_FSL_FM_MAX_FRAME_SIZE
+#define CONFIG_FSL_FM_MAX_FRAME_SIZE 0
+#endif
+
+#ifndef CONFIG_FSL_FM_RX_EXTRA_HEADROOM
+#define CONFIG_FSL_FM_RX_EXTRA_HEADROOM       16
+#endif
+
+/* SoC info */
+#define SOC_VERSION(svr)        (((svr) & 0xFFF7FF00) >> 8)
+#define SOC_MAJOR_REV(svr)      (((svr) & 0x000000F0) >> 4)
+#define SOC_MINOR_REV(svr)      ((svr) & 0x0000000F)
+
+/* Port defines */
+#define NUM_OF_FM_PORTS			63
+#define FIRST_OP_PORT(major)		(major >= 6 ? 0x02 : 0x01)
+#define FIRST_RX_PORT			0x08
+#define FIRST_TX_PORT			0x28
+#define LAST_OP_PORT			0x07
+#define LAST_RX_PORT			0x11
+#define LAST_TX_PORT			0x31
+
+#define TX_10G_PORT_BASE		0x30
+#define RX_10G_PORT_BASE		0x10
+
+struct lnx_wrp_fm_port_dev_t {
+	uint8_t id;
+	char name[20];
+	bool active;
+	uint64_t phys_base_addr;
+	uint64_t base_addr;	/* Port's *virtual* address */
+	resource_size_t mem_size;
+	struct fm_buffer_prefix_content_t buff_prefix_content;
+	void *h_dev;
+	void *h_lnx_wrp_fm_dev;
+	uint16_t tx_ch;
+	struct device *dev;
+	struct device_attribute *dev_attr_stats;
+	struct device_attribute *dev_attr_regs;
+	struct device_attribute *dev_attr_bmi_regs;
+	struct device_attribute *dev_attr_qmi_regs;
+	struct device_attribute *dev_attr_ipv4_opt;
+
+	struct fm_revision_info_t fm_rev_info;
+};
+
+struct lnx_wrp_fm_dev_t {
+	uint8_t id;
+	char name[10];
+	bool active;
+	uint64_t fm_phys_base_addr;
+	uint64_t fm_base_addr;
+	resource_size_t fm_mem_size;
+	phys_addr_t fm_muram_phys_base_addr;
+	uint64_t fm_muram_base_addr;
+	resource_size_t fm_muram_mem_size;
+	int irq;
+	int err_irq;
+	struct fm_params_t params;
+	void *h_dev;
+	struct muram_info *p_muram;
+
+	struct lnx_wrp_fm_port_dev_t ports[NUM_OF_FM_PORTS];
+
+	struct device *dev;
+	struct resource *res;
+
+	struct fm_revision_info_t fm_rev_info;
+	uint32_t qman_channel_base;
+	uint32_t num_of_qman_channels;
+	uint32_t *qman_channels;
+
+};
+
+struct lnx_wrp_fm_t {
+	struct lnx_wrp_fm_dev_t *p_fm_devs[INTG_MAX_NUM_OF_FM];
+};
+
+uint32_t get_qman_channel_id(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev,
+			     uint32_t port_id,
+			     enum fm_port_type port_type,
+			     enum fm_port_speed port_speed);
+#endif /* __FM_DRV_H__ */
diff --git a/drivers/net/ethernet/freescale/fman/inc/dpaa_ext.h b/drivers/net/ethernet/freescale/fman/inc/dpaa_ext.h
new file mode 100644
index 0000000..6630cbf
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/dpaa_ext.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* DPAA Application Programming Interface.*/
+#ifndef __DPAA_EXT_H
+#define __DPAA_EXT_H
+
+#include "service.h"
+
+/* DPAA_grp Data Path Acceleration Architecture API
+ * DPAA API functions, definitions and enums.
+ */
+
+/*Frame descriptor*/
+struct dpaa_fd_t {
+	 uint32_t id;		    /* FD id */
+	 uint32_t addrl;	    /* Data Address */
+	 uint32_t length;	    /* Frame length */
+	 uint32_t status;	    /* FD status */
+} __attribute__((__packed__));
+
+/*enum for defining frame format
+ */
+enum dpaa_fd_format_type {
+	/* Simple frame Single buffer; Offset and
+	 * small length (9b OFFSET, 20b LENGTH)
+	 */
+	DPAA_FD_FORMAT_TYPE_SHORT_SBSF = 0x0,
+	/* Simple frame, single buffer; big length
+	 * (29b LENGTH ,No OFFSET)
+	 */
+	DPAA_FD_FORMAT_TYPE_LONG_SBSF = 0x2,
+	/* Simple frame, Scatter Gather table; Offset
+	 * and small length (9b OFFSET, 20b LENGTH)
+	 */
+	DPAA_FD_FORMAT_TYPE_SHORT_MBSF = 0x4,
+	/* Simple frame, Scatter Gather table;
+	 * big length (29b LENGTH ,No OFFSET)
+	 */
+	DPAA_FD_FORMAT_TYPE_LONG_MBSF = 0x6,
+	/* Compound Frame (29b CONGESTION-WEIGHT
+	 * No LENGTH or OFFSET)
+	 */
+	e_DPAA_FD_FORMAT_TYPE_COMPOUND = 0x1,
+	DPAA_FD_FORMAT_TYPE_DUMMY
+};
+
+/* Frame descriptor macros */
+#define DPAA_FD_DD_MASK       0xc0000000	   /* FD DD field mask */
+#define DPAA_FD_PID_MASK      0x3f000000	   /* FD PID field mask */
+#define DPAA_FD_ELIODN_MASK   0x0000f000	   /* FD ELIODN field mask */
+#define DPAA_FD_BPID_MASK     0x00ff0000	   /* FD BPID field mask */
+#define DPAA_FD_ADDRH_MASK    0x000000ff	   /* FD ADDRH field mask */
+#define DPAA_FD_ADDRL_MASK    0xffffffff	   /* FD ADDRL field mask */
+#define DPAA_FD_FORMAT_MASK   0xe0000000	   /* FD FORMAT field mask */
+#define DPAA_FD_OFFSET_MASK   0x1ff00000	   /* FD OFFSET field mask */
+#define DPAA_FD_LENGTH_MASK   0x000fffff	   /* FD LENGTH field mask */
+
+/* Macro to get FD DD field */
+#define DPAA_FD_GET_DD(fd)						\
+	((((struct dpaa_fd_t *)fd)->id & DPAA_FD_DD_MASK) >> (31 - 1))
+/* Macro to get FD PID field */
+#define DPAA_FD_GET_PID(fd)						 \
+	(((((struct dpaa_fd_t *)fd)->id & DPAA_FD_PID_MASK) >> (31 - 7)) | \
+	((((struct dpaa_fd_t *)fd)->id & DPAA_FD_ELIODN_MASK) >>	\
+	(31 - 19 - 6)))
+ /* Macro to get FD BPID field */
+#define DPAA_FD_GET_BPID(fd)						\
+	((((struct dpaa_fd_t *)fd)->id & DPAA_FD_BPID_MASK) >> (31 - 15))
+ /* Macro to get FD ADDRH field */
+#define DPAA_FD_GET_ADDRH(fd)						\
+	(((struct dpaa_fd_t *)fd)->id & DPAA_FD_ADDRH_MASK)
+/* Macro to get FD ADDRL field */
+#define DPAA_FD_GET_ADDRL(fd)						\
+	(((struct dpaa_fd_t *)fd)->addrl)
+/* Macro to get FD ADDR field */
+#define DPAA_FD_GET_PHYS_ADDR(fd)					\
+	((phys_address_t)(((uint64_t)DPAA_FD_GET_ADDRH(fd) << 32) |	\
+	(uint64_t)DPAA_FD_GET_ADDRL(fd)))
+/* Macro to get FD FORMAT field */
+#define DPAA_FD_GET_FORMAT(fd)						\
+	((((struct dpaa_fd_t *)fd)->length & DPAA_FD_FORMAT_MASK) >> (31 - 2))
+/* Macro to get FD OFFSET field */
+#define DPAA_FD_GET_OFFSET(fd)						\
+	((((struct dpaa_fd_t *)fd)->length & DPAA_FD_OFFSET_MASK) >> (31 - 11))
+/* Macro to get FD LENGTH field */
+#define DPAA_FD_GET_LENGTH(fd)						\
+	(((struct dpaa_fd_t *)fd)->length & DPAA_FD_LENGTH_MASK)
+/* Macro to get FD STATUS field */
+#define DPAA_FD_GET_STATUS(fd)						\
+	(((struct dpaa_fd_t *)fd)->status)
+/* Macro to set FD DD field */
+#define DPAA_FD_SET_DD(fd, val)					\
+	(((struct dpaa_fd_t *)fd)->id =				\
+	((((struct dpaa_fd_t *)fd)->id & ~DPAA_FD_DD_MASK) |		\
+	(((val) << (31 - 1)) & DPAA_FD_DD_MASK)))
+/* Macro to set FD PID field or LIODN offset*/
+#define DPAA_FD_SET_PID(fd, val)					\
+	(((struct dpaa_fd_t *)fd)->id =				\
+	((((struct dpaa_fd_t *)fd)->id &				\
+	~(DPAA_FD_PID_MASK | DPAA_FD_ELIODN_MASK)) |			\
+	((((val) << (31 - 7)) & DPAA_FD_PID_MASK) |			\
+	((((val) >> 6) << (31 - 19)) & DPAA_FD_ELIODN_MASK))))
+/* Macro to set FD BPID field */
+#define DPAA_FD_SET_BPID(fd, val)					\
+	(((struct dpaa_fd_t *)fd)->id =				\
+	((((struct dpaa_fd_t *)fd)->id & ~DPAA_FD_BPID_MASK) |		\
+	(((val)  << (31 - 15)) & DPAA_FD_BPID_MASK)))
+/* Macro to set FD ADDRH field */
+#define DPAA_FD_SET_ADDRH(fd, val)					\
+	(((struct dpaa_fd_t *)fd)->id =				\
+	((((struct dpaa_fd_t *)fd)->id & ~DPAA_FD_ADDRH_MASK) |	\
+	((val) & DPAA_FD_ADDRH_MASK)))
+/* Macro to set FD ADDRL field */
+#define DPAA_FD_SET_ADDRL(fd, val)   (((struct dpaa_fd_t *)fd)->addrl = (val))
+/* Macro to set FD FORMAT field */
+#define DPAA_FD_SET_FORMAT(fd, val)					\
+	(((struct dpaa_fd_t *)fd)->length =				\
+	((((struct dpaa_fd_t *)fd)->length & ~DPAA_FD_FORMAT_MASK) |	\
+	(((val) << (31 - 2)) & DPAA_FD_FORMAT_MASK)))
+/* Macro to set FD OFFSET field */
+#define DPAA_FD_SET_OFFSET(fd, val)					\
+	(((struct dpaa_fd_t *)fd)->length =				\
+	((((struct dpaa_fd_t *)fd)->length & ~DPAA_FD_OFFSET_MASK) |	\
+	(((val) << (31 - 11)) & DPAA_FD_OFFSET_MASK)))
+/* Macro to set FD LENGTH field */
+#define DPAA_FD_SET_LENGTH(fd, val)					\
+	(((struct dpaa_fd_t *)fd)->length =				\
+	(((struct dpaa_fd_t *)fd)->length & ~DPAA_FD_LENGTH_MASK) |	\
+	((val) & DPAA_FD_LENGTH_MASK))
+/* Macro to set FD STATUS field */
+#define DPAA_FD_SET_STATUS(fd, val) (((struct dpaa_fd_t *)fd)->status = (val))
+
+/* Frame Scatter/Gather Table Entry */
+struct dpaa_sgte_t {
+	 uint32_t addrh;       /* Buffer Address high */
+	 uint32_t addrl;       /* Buffer Address low */
+	 uint32_t length;      /* Buffer length */
+	 uint32_t offset;      /* SGTE offset */
+} __attribute__((__packed__));
+
+#define DPAA_NUM_OF_SG_TABLE_ENTRY 16
+
+/* Frame Scatter/Gather Table Entry macros */
+/* SGTE ADDRH field mask */
+#define DPAA_SGTE_ADDRH_MASK    0x000000ff
+/* SGTE ADDRL field mask */
+#define DPAA_SGTE_ADDRL_MASK    0xffffffff
+/* SGTE Extension field mask */
+#define DPAA_SGTE_E_MASK        0x80000000
+/* SGTE Final field mask */
+#define DPAA_SGTE_F_MASK        0x40000000
+/* SGTE LENGTH field mask */
+#define DPAA_SGTE_LENGTH_MASK   0x3fffffff
+/* SGTE BPID field mask */
+#define DPAA_SGTE_BPID_MASK     0x00ff0000
+/* SGTE OFFSET field mask */
+#define DPAA_SGTE_OFFSET_MASK   0x00001fff
+/* Macro to get SGTE ADDRH field */
+#define DPAA_SGTE_GET_ADDRH(sgte)         \
+(((struct dpaa_sgte_t *)sgte)->addrh & DPAA_SGTE_ADDRH_MASK)
+/* Macro to get SGTE ADDRL field */
+#define DPAA_SGTE_GET_ADDRL(sgte) (((struct dpaa_sgte_t *)sgte)->addrl)
+/* Macro to get FD ADDR field */
+#define DPAA_SGTE_GET_PHYS_ADDR(sgte)					\
+	((phys_address_t)(((uint64_t)DPAA_SGTE_GET_ADDRH(sgte) << 32) | \\
+	(uint64_t)DPAA_SGTE_GET_ADDRL(sgte)))
+/* Macro to get SGTE EXTENSION field */
+#define DPAA_SGTE_GET_EXTENSION(sgte)					\
+	((((struct dpaa_sgte_t *)sgte)->length &			\
+	DPAA_SGTE_E_MASK) >> (31 - 0))
+/* Macro to get SGTE FINAL field */
+#define DPAA_SGTE_GET_FINAL(sgte)					\
+	((((struct dpaa_sgte_t *)sgte)->length &			\
+	DPAA_SGTE_F_MASK) >> (31 - 1))
+/* Macro to get SGTE LENGTH field */
+#define DPAA_SGTE_GET_LENGTH(sgte)					\
+	(((struct dpaa_sgte_t *)sgte)->length & DPAA_SGTE_LENGTH_MASK)
+/* Macro to get SGTE BPID field */
+#define DPAA_SGTE_GET_BPID(sgte)					\
+	((((struct dpaa_sgte_t *)sgte)->offset &			\
+	DPAA_SGTE_BPID_MASK) >> (31 - 15))
+/* Macro to get SGTE OFFSET field */
+#define DPAA_SGTE_GET_OFFSET(sgte)					\
+	(((struct dpaa_sgte_t *)sgte)->offset & DPAA_SGTE_OFFSET_MASK)
+/* Macro to set SGTE ADDRH field */
+#define DPAA_SGTE_SET_ADDRH(sgte, val)					\
+	(((struct dpaa_sgte_t *)sgte)->addrh =				\
+	((((struct dpaa_sgte_t *)sgte)->addrh & ~DPAA_SGTE_ADDRH_MASK) | \
+	((val) & DPAA_SGTE_ADDRH_MASK)))
+/* Macro to set SGTE ADDRL field */
+#define DPAA_SGTE_SET_ADDRL(sgte, val)					\
+	(((struct dpaa_sgte_t *)sgte)->addrl = (val))
+/* Macro to set SGTE EXTENSION field */
+#define DPAA_SGTE_SET_EXTENSION(sgte, val)				\
+	(((struct dpaa_sgte_t *)sgte)->length =			\
+	((((struct dpaa_sgte_t *)sgte)->length & ~DPAA_SGTE_E_MASK) |	\
+	(((val)  << (31 - 0)) & DPAA_SGTE_E_MASK)))
+/* Macro to set SGTE FINAL field */
+#define DPAA_SGTE_SET_FINAL(sgte, val)					\
+	(((struct dpaa_sgte_t *)sgte)->length =			\
+	((((struct dpaa_sgte_t *)sgte)->length & ~DPAA_SGTE_F_MASK) |	\
+	(((val)  << (31 - 1)) & DPAA_SGTE_F_MASK)))
+/* Macro to set SGTE LENGTH field */
+#define DPAA_SGTE_SET_LENGTH(sgte, val)				\
+	(((struct dpaa_sgte_t *)sgte)->length =			\
+	(((struct dpaa_sgte_t *)sgte)->length & ~DPAA_SGTE_LENGTH_MASK) | \
+	((val) & DPAA_SGTE_LENGTH_MASK))
+/* Macro to set SGTE BPID field */
+#define DPAA_SGTE_SET_BPID(sgte, val)					\
+	(((struct dpaa_sgte_t *)sgte)->offset =			\
+	((((struct dpaa_sgte_t *)sgte)->offset & ~DPAA_SGTE_BPID_MASK) | \
+	(((val)  << (31 - 15)) & DPAA_SGTE_BPID_MASK)))
+/* Macro to set SGTE OFFSET field */
+#define DPAA_SGTE_SET_OFFSET(sgte, val)				\
+	(((struct dpaa_sgte_t *)sgte)->offset =			\
+	((((struct dpaa_sgte_t *)sgte)->offset & ~DPAA_SGTE_OFFSET_MASK) | \
+	(((val) << (31 - 31)) & DPAA_SGTE_OFFSET_MASK)))
+
+#define DPAA_LIODN_DONT_OVERRIDE    (-1)
+
+/* end of DPAA_grp group */
+
+#endif /* __DPAA_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/fman/inc/dpaa_integration_ext.h
new file mode 100644
index 0000000..6adf122
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/dpaa_integration_ext.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DPAA_INTEGRATION_EXT_H
+#define __DPAA_INTEGRATION_EXT_H
+
+/* FM HW DEFINITIONS */
+#define INTG_MAX_NUM_OF_FM		2
+
+#define FM_MAX_NUM_OF_1G_RX_PORTS	6
+#define FM_MAX_NUM_OF_10G_RX_PORTS	2
+#define FM_MAX_NUM_OF_RX_PORTS		\
+	(FM_MAX_NUM_OF_1G_RX_PORTS + FM_MAX_NUM_OF_10G_RX_PORTS)
+
+#define FM_MAX_NUM_OF_1G_TX_PORTS	6
+#define FM_MAX_NUM_OF_10G_TX_PORTS	2
+#define FM_MAX_NUM_OF_TX_PORTS		\
+	(FM_MAX_NUM_OF_1G_TX_PORTS + FM_MAX_NUM_OF_10G_TX_PORTS)
+
+#define FM_MAX_NUM_OF_OH_PORTS		7
+
+#define FM_MAX_NUM_OF_MACS	10
+
+/* BMan INTEGRATION-SPECIFIC DEFINITIONS */
+#define BM_MAX_NUM_OF_POOLS         64
+/**< Number of buffers pools */
+
+/* RTC defines */
+#define FM_RTC_NUM_OF_ALARMS			2
+/**< RTC number of alarms */
+#define FM_RTC_NUM_OF_PERIODIC_PULSES		3
+/**< RTC number of periodic pulses */
+#define FM_RTC_NUM_OF_EXT_TRIGGERS		2
+/**< RTC number of external triggers */
+
+#define FM_PORT_MAX_NUM_OF_EXT_POOLS            8
+/**< Number of external BM pools per Rx port */
+
+#define FM_LOW_END_RESTRICTION
+/**< prevents the use of TX port 1 with OP port 0
+ * for FM_IP_BLOCK Major Rev 4 (P1023)
+ */
+
+/* FPM defines */
+#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS		4
+
+/* Uniqe defines */
+#define FM_QMI_NO_ECC_EXCEPTIONS		/* P1 */
+#define FM_CSI_CFED_LIMIT			/* P1 */
+#define FM_PEDANTIC_DMA				/* P1 */
+#define FM_QMI_NO_DEQ_OPTIONS_SUPPORT		/* P1 */
+#define FM_HAS_TOTAL_DMAS			/* P1-P5 */
+#define FM_DEQ_PIPELINE_PARAMS_FOR_OP		/* P1, T/B */
+#define FM_NO_DISPATCH_RAM_ECC			/* P2-P5 */
+#define FM_NO_WATCHDOG				/* P4 */
+#define FM_NO_TNUM_AGING			/* P2-P5 */
+#define FM_NO_BACKUP_POOLS			/* P2-P5 */
+#define FM_NO_OP_OBSERVED_POOLS		/* P2-P5, T/B */
+#define FM_NO_ADVANCED_RATE_LIMITER		/* P2-P5 */
+#define FM_OP_OPEN_DMA_MIN_LIMIT		/* T/B */
+#define FM_NO_RESTRICT_ON_ACCESS_RSRC		/* T/B */
+#define FM_FRAME_END_PARAMS_FOR_OP		/* T/B */
+#define FM_QMI_NO_SINGLE_ECC_EXCEPTION		/* T/B */
+
+/* FMan errata */
+#define FM_RX_PREAM_4_ERRATA_DTSEC_A001			/* Dtsec */
+#define FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839	/* Dtsec */
+#define FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007		/* Tgec */
+#define FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008			/* P2-P5 */
+#define FM_GRS_ERRATA_DTSEC_A002				/* P4080 */
+#define FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003		/* P4080 */
+#define FM_GTS_ERRATA_DTSEC_A004				/* P4080 */
+#define FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012	/* P4080 */
+#define FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014			/* P2-P5 */
+#define FM_TX_LOCKUP_ERRATA_DTSEC6				/* P4080 */
+#define FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173			/* P2-P5 */
+#define FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005		/* P4080 */
+#define FM_TX_ECC_FRMS_ERRATA_10GMAC_A004			/* P2-P5 */
+#define FM_LEN_CHECK_ERRATA_FMAN_SW002				/* P2-P5, T/B */
+#define FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669		/* T/B */
+#define FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127		/* T/B */
+#define FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320		/* mEMAC */
+#define FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981   /* T4/B4 rev1 */
+#define FM_AID_MODE_NO_TNUM_SW005
+/* refer to pdm TKT068794 - only support of port_id on aid - T/B */
+#define FM_ERROR_VSP_NO_MATCH_SW006
+/* refer to pdm TKT174304 - no match between errorQ and VSP - T/B */
+#define FM_TX_INVALID_ECC_ERRATA_10GMAC_A009			/* P2-P5 */
+#define FM_BCB_ERRATA_BMI_SW001				/* T/B */
+
+#endif /* __DPAA_INTEGRATION_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/enet_ext.h b/drivers/net/ethernet/freescale/fman/inc/enet_ext.h
new file mode 100644
index 0000000..cfade84
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/enet_ext.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Ethernet generic definitions and enums. */
+
+#ifndef __ENET_EXT_H
+#define __ENET_EXT_H
+
+#include "fsl_enet.h"
+
+/* Number of octets (8-bit bytes) in an ethernet address */
+#define ENET_NUM_OCTETS_PER_ADDRESS 6
+/* Group address mask for ethernet addresses */
+#define ENET_GROUP_ADDR	    0x01
+
+/* Ethernet Address */
+typedef uint8_t enet_addr_t[ENET_NUM_OCTETS_PER_ADDRESS];
+
+/* Ethernet MAC-PHY Interface */
+enum ethernet_interface {
+	ENET_IF_MII = E_ENET_IF_MII,	 /* MII interface */
+	ENET_IF_RMII = E_ENET_IF_RMII, /* RMII interface */
+	ENET_IF_SMII = E_ENET_IF_SMII, /* SMII interface */
+	ENET_IF_GMII = E_ENET_IF_GMII, /* GMII interface */
+	ENET_IF_RGMII = E_ENET_IF_RGMII,
+					 /* RGMII interface */
+	ENET_IF_TBI = E_ENET_IF_TBI,	 /* TBI interface */
+	ENET_IF_RTBI = E_ENET_IF_RTBI, /* RTBI interface */
+	ENET_IF_SGMII = E_ENET_IF_SGMII,
+					 /* SGMII interface */
+	ENET_IF_XGMII = E_ENET_IF_XGMII,
+					 /* XGMII interface */
+	ENET_IF_QSGMII = E_ENET_IF_QSGMII,
+					 /* QSGMII interface */
+	ENET_IF_XFI = E_ENET_IF_XFI	 /* XFI interface */
+};
+
+/* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC and phy
+ * or backplane; Note: 1000BaseX auto-negotiation relates only to interface
+ * between MAC and phy/backplane, SGMII phy can still synchronize with far-end
+ * phy at 10Mbps, 100Mbps or 1000Mbps
+ */
+#define ENET_IF_SGMII_BASEX       0x80000000
+
+/* Ethernet Speed (nominal data rate) */
+enum ethernet_speed {
+	ENET_SPEED_10 = E_ENET_SPEED_10,	 /* 10 Mbps */
+	ENET_SPEED_100 = E_ENET_SPEED_100,	 /* 100 Mbps */
+	ENET_SPEED_1000 = E_ENET_SPEED_1000,	 /* 1000 Mbps = 1 Gbps */
+	ENET_SPEED_10000 = E_ENET_SPEED_10000	 /* 10000 Mbps = 10 Gbps */
+};
+
+/* Ethernet mode (combination of MAC-PHY interface and speed) */
+enum e_enet_mode {
+	ENET_MODE_INVALID = 0,	/* Invalid Ethernet mode */
+	/*    10 Mbps MII   */
+	ENET_MODE_MII_10 = (ENET_IF_MII | ENET_SPEED_10),
+	/*   100 Mbps MII   */
+	ENET_MODE_MII_100 = (ENET_IF_MII | ENET_SPEED_100),
+	/*    10 Mbps RMII  */
+	ENET_MODE_RMII_10 = (ENET_IF_RMII | ENET_SPEED_10),
+	/*   100 Mbps RMII  */
+	ENET_MODE_RMII_100 = (ENET_IF_RMII | ENET_SPEED_100),
+	/*    10 Mbps SMII  */
+	ENET_MODE_SMII_10 = (ENET_IF_SMII | ENET_SPEED_10),
+	/*   100 Mbps SMII  */
+	ENET_MODE_SMII_100 = (ENET_IF_SMII | ENET_SPEED_100),
+	/*  1000 Mbps GMII  */
+	ENET_MODE_GMII_1000 = (ENET_IF_GMII | ENET_SPEED_1000),
+	/*    10 Mbps RGMII */
+	ENET_MODE_RGMII_10 = (ENET_IF_RGMII | ENET_SPEED_10),
+	/*   100 Mbps RGMII */
+	ENET_MODE_RGMII_100 = (ENET_IF_RGMII | ENET_SPEED_100),
+	/*  1000 Mbps RGMII */
+	ENET_MODE_RGMII_1000 = (ENET_IF_RGMII | ENET_SPEED_1000),
+	/*  1000 Mbps TBI   */
+	ENET_MODE_TBI_1000 = (ENET_IF_TBI | ENET_SPEED_1000),
+	/*  1000 Mbps RTBI  */
+	ENET_MODE_RTBI_1000 = (ENET_IF_RTBI | ENET_SPEED_1000),
+	/* 10 Mbps SGMII with auto-negotiation between MAC and
+	 * SGMII phy according to Cisco SGMII specification
+	 */
+	ENET_MODE_SGMII_10 = (ENET_IF_SGMII | ENET_SPEED_10),
+	/* 100 Mbps SGMII with auto-negotiation between MAC and
+	 * SGMII phy according to Cisco SGMII specification
+	 */
+	ENET_MODE_SGMII_100 = (ENET_IF_SGMII | ENET_SPEED_100),
+	/* 1000 Mbps SGMII with auto-negotiation between MAC and
+	 * SGMII phy according to Cisco SGMII specification
+	 */
+	ENET_MODE_SGMII_1000 = (ENET_IF_SGMII | ENET_SPEED_1000),
+	/* 10 Mbps SGMII with 1000BaseX auto-negotiation between
+	 * MAC and SGMII phy or backplane
+	 */
+	ENET_MODE_SGMII_BASEX_10 =
+	    (ENET_IF_SGMII_BASEX | ENET_IF_SGMII | ENET_SPEED_10),
+	/* 100 Mbps SGMII with 1000BaseX auto-negotiation between
+	 * MAC and SGMII phy or backplane
+	 */
+	ENET_MODE_SGMII_BASEX_100 =
+	    (ENET_IF_SGMII_BASEX | ENET_IF_SGMII | ENET_SPEED_100),
+	/* 1000 Mbps SGMII with 1000BaseX auto-negotiation between
+	 * MAC and SGMII phy or backplane
+	 */
+	ENET_MODE_SGMII_BASEX_1000 =
+	    (ENET_IF_SGMII_BASEX | ENET_IF_SGMII | ENET_SPEED_1000),
+	/* 1000 Mbps QSGMII with auto-negotiation between MAC and
+	 * QSGMII phy according to Cisco QSGMII specification
+	 */
+	ENET_MODE_QSGMII_1000 = (ENET_IF_QSGMII | ENET_SPEED_1000),
+	/* 1000 Mbps QSGMII with 1000BaseX auto-negotiation between
+	 * MAC and QSGMII phy or backplane
+	 */
+	ENET_MODE_QSGMII_BASEX_1000 =
+	    (ENET_IF_SGMII_BASEX | ENET_IF_QSGMII | ENET_SPEED_1000),
+	/* 10000 Mbps XGMII */
+	ENET_MODE_XGMII_10000 = (ENET_IF_XGMII | ENET_SPEED_10000),
+	/* 10000 Mbps XFI */
+	ENET_MODE_XFI_10000 = (ENET_IF_XFI | ENET_SPEED_10000)
+};
+
+#define IS_ENET_MODE_VALID(mode)			\
+	(((mode) == ENET_MODE_MII_10) ||		\
+	((mode) == ENET_MODE_MII_100) ||		\
+	((mode) == ENET_MODE_RMII_10) ||		\
+	((mode) == ENET_MODE_RMII_100) ||		\
+	((mode) == ENET_MODE_SMII_10) ||		\
+	((mode) == ENET_MODE_SMII_100) ||		\
+	((mode) == ENET_MODE_GMII_1000) ||		\
+	((mode) == ENET_MODE_RGMII_10) ||		\
+	((mode) == ENET_MODE_RGMII_100) ||		\
+	((mode) == ENET_MODE_RGMII_1000) ||		\
+	((mode) == ENET_MODE_TBI_1000) ||		\
+	((mode) == ENET_MODE_RTBI_1000) ||		\
+	((mode) == ENET_MODE_SGMII_10) ||		\
+	((mode) == ENET_MODE_SGMII_100) ||		\
+	((mode) == ENET_MODE_SGMII_1000) ||		\
+	((mode) == ENET_MODE_SGMII_BASEX_10) ||	\
+	((mode) == ENET_MODE_SGMII_BASEX_100) ||	\
+	((mode) == ENET_MODE_SGMII_BASEX_1000) ||	\
+	((mode) == ENET_MODE_XGMII_10000) ||		\
+	((mode) == ENET_MODE_QSGMII_1000) ||		\
+	((mode) == ENET_MODE_QSGMII_BASEX_1000) ||	\
+	((mode) == ENET_MODE_XFI_10000))
+
+#define MAKE_ENET_MODE(_interface, _speed) \
+		      (enum e_enet_mode)((_interface) | (_speed))
+
+#define ENET_INTERFACE_FROM_MODE(mode) \
+				(enum ethernet_interface)((mode) & 0x0FFF0000)
+#define ENET_SPEED_FROM_MODE(mode) \
+			    (enum ethernet_speed)((mode) & 0x0000FFFF)
+
+#define ENET_ADDR_TO_UINT64(_enet_addr)		  \
+	(uint64_t)(((uint64_t)(_enet_addr)[0] << 40) |   \
+		   ((uint64_t)(_enet_addr)[1] << 32) |   \
+		   ((uint64_t)(_enet_addr)[2] << 24) |   \
+		   ((uint64_t)(_enet_addr)[3] << 16) |   \
+		   ((uint64_t)(_enet_addr)[4] << 8) |    \
+		   ((uint64_t)(_enet_addr)[5]))
+
+#define MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr) \
+	do { \
+		int i; \
+		for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) \
+			(_enet_addr)[i] = \
+			(uint8_t)((_addr64) >> ((5 - i) * 8)); \
+	} while (0)
+
+#endif /* __ENET_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/fm_ext.h b/drivers/net/ethernet/freescale/fman/inc/fm_ext.h
new file mode 100644
index 0000000..33e3000
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/fm_ext.h
@@ -0,0 +1,657 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM Application Programming Interface. */
+#ifndef __FM_EXT
+#define __FM_EXT
+
+#include "service.h"
+#include "dpaa_ext.h"
+#include "dpaa_integration_ext.h"
+#include "fsl_fman_sp.h"
+
+/* Enum for defining port types */
+enum fm_port_type {
+	FM_PORT_TYPE_OP = 0,	/* OP Port */
+	FM_PORT_TYPE_TX,	/* TX Port */
+	FM_PORT_TYPE_RX,	/* RX Port */
+	FM_PORT_TYPE_DUMMY
+};
+
+/* Enum for defining port speed */
+enum fm_port_speed {
+	FM_PORT_SPEED_1G = 0,		/* 1G port */
+	FM_PORT_SPEED_10G,		/* 10G port */
+	FM_PORT_SPEED_OP
+};
+
+/* General FM defines */
+#define FM_MAX_NUM_OF_PARTITIONS    64	 /* Maximum number of partitions */
+#define FM_PHYS_ADDRESS_SIZE        6	 /* FM Physical address size */
+
+/* FM physical Address */
+struct fm_phys_addr_t {
+	uint8_t high;	      /* High part of the physical address */
+	uint32_t low;	      /* Low part of the physical address */
+} __attribute__((__packed__));
+
+/* Parse results memory layout */
+struct fm_prs_result_t {
+	 uint8_t lpid;		     /* Logical port id */
+	 uint8_t shimr;		     /* Shim header result  */
+	 uint16_t l2r;		     /* Layer 2 result */
+	 uint16_t l3r;		     /* Layer 3 result */
+	 uint8_t l4r;		     /* Layer 4 result */
+	 uint8_t cplan;		     /* Classification plan id */
+	 uint16_t nxthdr;	     /* Next Header  */
+	 uint16_t cksum;	     /* Running-sum */
+	/* Flags&fragment-offset field of the last IP-header */
+	 uint16_t flags_frag_off;
+	/* Routing type field of a IPV6 routing extension header */
+	 uint8_t route_type;
+	/* Routing Extension Header Present; last bit is IP valid */
+	 uint8_t rhp_ip_valid;
+	 uint8_t shim_off[2];	     /* Shim offset */
+	/* IP PID (last IP-proto) offset */
+	 uint8_t ip_pid_off;
+	 uint8_t eth_off;	     /* ETH offset */
+	 uint8_t llc_snap_off;	     /* LLC_SNAP offset */
+	 uint8_t vlan_off[2];	     /* VLAN offset */
+	 uint8_t etype_off;	     /* ETYPE offset */
+	 uint8_t pppoe_off;	     /* PPP offset */
+	 uint8_t mpls_off[2];	     /* MPLS offset */
+	 uint8_t ip_off[2];	     /* IP offset */
+	 uint8_t gre_off;	     /* GRE offset */
+	 uint8_t l4_off;	     /* Layer 4 offset */
+	 uint8_t nxthdr_off;	     /* Parser end point */
+} __attribute__((__packed__));
+
+/* FM Parser results */
+/* Parse Result: VLAN stack */
+#define FM_PR_L2_VLAN_STACK         0x00000100
+#define FM_PR_L2_ETHERNET           0x00008000	/* Parse Result: Ethernet*/
+#define FM_PR_L2_VLAN               0x00004000	/* Parse Result: VLAN */
+#define FM_PR_L2_LLC_SNAP           0x00002000	/* Parse Result: LLC_SNAP */
+#define FM_PR_L2_MPLS               0x00001000	/* Parse Result: MPLS */
+#define FM_PR_L2_PPPOE              0x00000800	/* Parse Result: PPPOE */
+
+/* FM Frame descriptor macros  */
+/* Frame queue Context Override */
+#define FM_FD_CMD_FCO                   0x80000000
+#define FM_FD_CMD_RPD                   0x40000000  /* Read Prepended Data */
+/* Update Prepended Data */
+#define FM_FD_CMD_UPD                   0x20000000
+#define FM_FD_CMD_DTC                   0x10000000  /* Do L4 Checksum */
+/* Didn't calculate L4 Checksum */
+#define FM_FD_CMD_DCL4C                 0x10000000
+/* Confirmation Frame Queue */
+#define FM_FD_CMD_CFQ                   0x00ffffff
+
+/* Not for Rx-Port! Unsupported Format */
+#define FM_FD_ERR_UNSUPPORTED_FORMAT    0x04000000
+/* Not for Rx-Port! Length Error */
+#define FM_FD_ERR_LENGTH                0x02000000
+#define FM_FD_ERR_DMA                   0x01000000  /* DMA Data error */
+
+/* IPR frame (not error) */
+#define FM_FD_IPR                       0x00000001
+/* IPR non-consistent-sp */
+#define FM_FD_ERR_IPR_NCSP              (0x00100000 | FM_FD_IPR)
+/* IPR error */
+#define FM_FD_ERR_IPR                   (0x00200000 | FM_FD_IPR)
+/* IPR timeout */
+#define FM_FD_ERR_IPR_TO                (0x00300000 | FM_FD_IPR)
+
+/* Rx FIFO overflow, FCS error, code error, running disparity error
+ * (SGMII and TBI modes), FIFO parity error. PHY Sequence error,
+ * PHY error control character detected.
+ */
+#define FM_FD_ERR_PHYSICAL              0x00080000
+/* Frame too long OR Frame size exceeds max_length_frame  */
+#define FM_FD_ERR_SIZE                  0x00040000
+/* classification discard */
+#define FM_FD_ERR_CLS_DISCARD           0x00020000
+/* Extract Out of Frame */
+#define FM_FD_ERR_EXTRACTION            0x00008000
+/* No Scheme Selected */
+#define FM_FD_ERR_NO_SCHEME             0x00004000
+/* Keysize Overflow */
+#define FM_FD_ERR_KEYSIZE_OVERFLOW      0x00002000
+/* Frame color is red */
+#define FM_FD_ERR_COLOR_RED             0x00000800
+/* Frame color is yellow */
+#define FM_FD_ERR_COLOR_YELLOW          0x00000400
+/* Parser Time out Exceed */
+#define FM_FD_ERR_PRS_TIMEOUT           0x00000080
+/* Invalid Soft Parser instruction */
+#define FM_FD_ERR_PRS_ILL_INSTRUCT      0x00000040
+/* Header error was identified during parsing */
+#define FM_FD_ERR_PRS_HDR_ERR           0x00000020
+/* Frame parsed beyind 256 first bytes */
+#define FM_FD_ERR_BLOCK_LIMIT_EXCEEDED  0x00000008
+
+#define FM_FD_TX_STATUS_ERR_MASK        (FM_FD_ERR_UNSUPPORTED_FORMAT   | \
+					 FM_FD_ERR_LENGTH               | \
+					 FM_FD_ERR_DMA)	/* TX Error FD bits */
+
+#define FM_FD_RX_STATUS_ERR_MASK        (FM_FD_ERR_UNSUPPORTED_FORMAT   | \
+					 FM_FD_ERR_LENGTH               | \
+					 FM_FD_ERR_DMA                  | \
+					 FM_FD_ERR_IPR                  | \
+					 FM_FD_ERR_IPR_TO               | \
+					 FM_FD_ERR_IPR_NCSP             | \
+					 FM_FD_ERR_PHYSICAL             | \
+					 FM_FD_ERR_SIZE                 | \
+					 FM_FD_ERR_CLS_DISCARD          | \
+					 FM_FD_ERR_COLOR_RED            | \
+					 FM_FD_ERR_COLOR_YELLOW         | \
+					 FM_FD_ERR_EXTRACTION           | \
+					 FM_FD_ERR_NO_SCHEME            | \
+					 FM_FD_ERR_KEYSIZE_OVERFLOW     | \
+					 FM_FD_ERR_PRS_TIMEOUT          | \
+					 FM_FD_ERR_PRS_ILL_INSTRUCT     | \
+					 FM_FD_ERR_PRS_HDR_ERR          | \
+					 FM_FD_ERR_BLOCK_LIMIT_EXCEEDED)
+					/* RX Error FD bits */
+
+/* non Frame-Manager error */
+#define FM_FD_RX_STATUS_ERR_NON_FM      0x00400000
+
+/* Context A */
+struct fm_context_a_t {
+	 uint32_t command;  /* ContextA Command */
+	 uint8_t res0[4];   /* ContextA Reserved bits */
+} __attribute__((__packed__));
+
+/* Special Operation options */
+/* activate features that related to IPSec (e.g fix Eth-type) */
+#define  FM_SP_OP_IPSEC                     0x80000000
+/* update the UDP-Len after Encryption */
+#define  FM_SP_OP_IPSEC_UPDATE_UDP_LEN      0x40000000
+#define  FM_SP_OP_RPD                       0x10000000	/* Set the RPD bit */
+/* Set the DCL4C bit */
+#define  FM_SP_OP_DCL4C                     0x08000000
+/* Check SEC errors */
+#define  FM_SP_OP_CHECK_SEC_ERRORS          0x04000000
+/* Clear the RPD bit */
+#define  FM_SP_OP_CLEAR_RPD                 0x02000000
+
+/* Context A macros */
+#define FM_CONTEXTA_OVERRIDE_MASK       0x80000000
+#define FM_CONTEXTA_ICMD_MASK           0x40000000
+#define FM_CONTEXTA_A1_VALID_MASK       0x20000000
+#define FM_CONTEXTA_MACCMD_MASK         0x00ff0000
+#define FM_CONTEXTA_MACCMD_VALID_MASK   0x00800000
+#define FM_CONTEXTA_MACCMD_SECURED_MASK 0x00100000
+#define FM_CONTEXTA_MACCMD_SC_MASK      0x000f0000
+#define FM_CONTEXTA_A1_MASK             0x0000ffff
+
+#define FM_CONTEXTA_GET_OVERRIDE(contextA)				\
+	((((struct fm_context_a_t *)contextA)->command &		\
+		FM_CONTEXTA_OVERRIDE_MASK) >> (31 - 0))
+#define FM_CONTEXTA_GET_ICMD(contextA) \
+	((((struct fm_context_a_t *)contextA)->command &		\
+		FM_CONTEXTA_ICMD_MASK) >> (31 - 1))
+#define FM_CONTEXTA_GET_A1_VALID(contextA) \
+	((((struct fm_context_a_t *)contextA)->command &		\
+		FM_CONTEXTA_A1_VALID_MASK) >> (31 - 2))
+#define FM_CONTEXTA_GET_A1(contextA)					\
+	((((struct fm_context_a_t *)contextA)->command &		\
+		FM_CONTEXTA_A1_MASK) >> (31 - 31))
+#define FM_CONTEXTA_GET_MACCMD(contextA)				\
+	((((struct fm_context_a_t *)contextA)->command &		\
+		FM_CONTEXTA_MACCMD_MASK) >> (31 - 15))
+#define FM_CONTEXTA_GET_MACCMD_VALID(contextA)				\
+	((((struct fm_context_a_t *)contextA)->command &		\
+		FM_CONTEXTA_MACCMD_VALID_MASK) >> (31 - 8))
+#define FM_CONTEXTA_GET_MACCMD_SECURED(contextA)			\
+((((struct fm_context_a_t *)contextA)->command &			\
+		FM_CONTEXTA_MACCMD_SECURED_MASK) >> (31 - 11))
+#define FM_CONTEXTA_GET_MACCMD_SECURE_CHANNEL(contextA)		\
+((((struct fm_context_a_t *)contextA)->command &			\
+		FM_CONTEXTA_MACCMD_SC_MASK) >> (31 - 15))
+
+#define FM_CONTEXTA_SET_OVERRIDE(contextA, val)			\
+	(((struct fm_context_a_t *)contextA)->command =		\
+	(uint32_t)((((struct fm_context_a_t *)contextA)->command &	\
+	~FM_CONTEXTA_OVERRIDE_MASK) | (((uint32_t)(val) << (31 - 0)) &\
+	FM_CONTEXTA_OVERRIDE_MASK)))
+#define FM_CONTEXTA_SET_ICMD(contextA, val)				\
+	(((struct fm_context_a_t *)contextA)->command =		\
+	(uint32_t)((((struct fm_context_a_t *)contextA)->command &	\
+	~FM_CONTEXTA_ICMD_MASK)	 | (((val) << (31 - 1)) &		\
+	FM_CONTEXTA_ICMD_MASK)))
+#define FM_CONTEXTA_SET_A1_VALID(contextA, val)			\
+	(((struct fm_context_a_t *)contextA)->command =		\
+	(uint32_t)((((struct fm_context_a_t *)contextA)->command &	\
+	~FM_CONTEXTA_A1_VALID_MASK) | (((val) << (31 - 2)) &		\
+	FM_CONTEXTA_A1_VALID_MASK)))
+#define FM_CONTEXTA_SET_A1(contextA, val)				\
+	(((struct fm_context_a_t *)contextA)->command =		\
+	(uint32_t)((((struct fm_context_a_t *)contextA)->command &	\
+	~FM_CONTEXTA_A1_MASK) | (((val) << (31 - 31)) &		\
+	FM_CONTEXTA_A1_MASK)))
+#define FM_CONTEXTA_SET_MACCMD(contextA, val)				\
+	(((struct fm_context_a_t *)contextA)->command =		\
+	(uint32_t)((((struct fm_context_a_t *)contextA)->command &	\
+	~FM_CONTEXTA_MACCMD_MASK) | (((val) << (31 - 15)) &		\
+	FM_CONTEXTA_MACCMD_MASK)))
+#define FM_CONTEXTA_SET_MACCMD_VALID(contextA, val)			\
+	(((struct fm_context_a_t *)contextA)->command =		\
+	(uint32_t)((((struct fm_context_a_t *)contextA)->command &	\
+	~FM_CONTEXTA_MACCMD_VALID_MASK) | (((val) << (31 - 8)) &	\
+	FM_CONTEXTA_MACCMD_VALID_MASK)))
+#define FM_CONTEXTA_SET_MACCMD_SECURED(contextA, val)			\
+	(((struct fm_context_a_t *)contextA)->command =		\
+	(uint32_t)((((struct fm_context_a_t *)contextA)->command &	\
+	~FM_CONTEXTA_MACCMD_SECURED_MASK) | (((val) << (31 - 11)) &	\
+	FM_CONTEXTA_MACCMD_SECURED_MASK)))
+#define FM_CONTEXTA_SET_MACCMD_SECURE_CHANNEL(contextA, val)		\
+	(((struct fm_context_a_t *)contextA)->command =		\
+	(uint32_t)((((struct fm_context_a_t *)contextA)->command &	\
+	~FM_CONTEXTA_MACCMD_SC_MASK) | (((val) << (31 - 15)) &		\
+	FM_CONTEXTA_MACCMD_SC_MASK)))
+/* @} */
+
+/* FM Exceptions */
+enum fm_exceptions {
+	FM_EX_DMA_BUS_ERROR = 0,	/* DMA bus error. */
+	/* Read Buffer ECC error (Valid for FM rev < 6)*/
+	FM_EX_DMA_READ_ECC,
+	/* Write Buffer ECC error on system side (Valid for FM rev < 6)*/
+	FM_EX_DMA_SYSTEM_WRITE_ECC,
+	/* Write Buffer ECC error on FM side (Valid for FM rev < 6)*/
+	FM_EX_DMA_FM_WRITE_ECC,
+	/* Single Port ECC error on FM side (Valid for FM rev > 6)*/
+	FM_EX_DMA_SINGLE_PORT_ECC,
+	FM_EX_FPM_STALL_ON_TASKS,	/* Stall of tasks on FPM */
+	FM_EX_FPM_SINGLE_ECC,		/* Single ECC on FPM. */
+	/* Double ECC error on FPM ram access */
+	FM_EX_FPM_DOUBLE_ECC,
+	FM_EX_QMI_SINGLE_ECC,		/* Single ECC on QMI. */
+	FM_EX_QMI_DOUBLE_ECC,		/* Double bit ECC occurred on QMI */
+	FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,
+					/* Dequeue from unknown port id */
+	FM_EX_BMI_LIST_RAM_ECC,	/* Linked List RAM ECC error */
+	FM_EX_BMI_STORAGE_PROFILE_ECC,/* Storage Profile ECC Error */
+	/* Statistics Count RAM ECC Error Enable */
+	FM_EX_BMI_STATISTICS_RAM_ECC,
+	FM_EX_BMI_DISPATCH_RAM_ECC,	/* Dispatch RAM ECC Error Enable */
+	FM_EX_IRAM_ECC,		/* Double bit ECC occurred on IRAM*/
+	FM_EX_MURAM_ECC		/* Double bit ECC occurred on MURAM*/
+};
+
+/*  Enum for defining port DMA swap mode */
+enum fm_dma_swap_option {
+	FM_DMA_NO_SWP = FMAN_DMA_NO_SWP,
+    /* No swap, transfer data as is.*/
+	FM_DMA_SWP_PPC_LE = FMAN_DMA_SWP_PPC_LE,
+    /* The transferred data should be swapped in PowerPc
+    *Little Endian mode.
+     */
+	FM_DMA_SWP_BE = FMAN_DMA_SWP_BE
+    /* The transferred data should be swapped in Big Endian mode */
+};
+
+/*  fm_exceptions_cb
+ *   Exceptions user callback routine, will be called upon an
+ *		exception passing the exception identification.
+ *   h_app      - User's application descriptor.
+ *   exception  - The exception.
+ */
+typedef void (fm_exceptions_cb) (void *h_app,
+				 enum fm_exceptions exception);
+
+/*  fm_bus_error_cb
+ *   Bus error user callback routine, will be called upon a
+ *		bus error, passing parameters describing the errors and
+ *		the owner.
+ *   h_app       - User's application descriptor.
+ *   port_type    - Port type (enum fm_port_type)
+ *   port_id      - Port id - relative to type.
+ *   addr        - Address that caused the error
+ *   tnum        - Owner of error
+ *   liodn       - Logical IO device number
+ */
+typedef void (fm_bus_error_cb) (void *h_app,
+				enum fm_port_type port_type,
+				uint8_t port_id,
+				uint64_t addr,
+				uint8_t tnum, uint16_t liodn);
+
+/* A structure for defining buffer prefix area content. */
+struct fm_buffer_prefix_content_t {
+	/* Number of bytes to be left at the beginning of the external
+	 * buffer; Note that the private-area will start from the base
+	 * of the buffer address.
+	 */
+	uint16_t priv_data_size;
+	/* true to pass the parse result to/from the FM;
+	 * User may use FM_PORT_GetBufferPrsResult() in
+	 * order to get the parser-result from a buffer.
+	 */
+	bool pass_prs_result;
+	/* true to pass the timeStamp to/from the FM User may use
+	 * fm_port_get_buffer_time_stamp() in order to get the
+	 * parser-result from a buffer.
+	 */
+	bool pass_time_stamp;
+	/* true to pass the KG hash result to/from the FM User may
+	 * use FM_PORT_GetBufferHashResult() in order to get the
+	 * parser-result from a buffer.
+	 */
+	bool pass_hash_result;
+	/* Add all other Internal-Context information: AD,
+	 * hash-result, key, etc.
+	 */
+	uint16_t data_align;
+};
+
+/* A structure of information about each of the external
+ * buffer pools used by a port or storage-profile.
+ */
+struct fm_ext_pool_params_t {
+	uint8_t id;		    /* External buffer pool id */
+	uint16_t size;		    /* External buffer pool buffer size */
+};
+
+/* A structure for informing the driver about the external
+ * buffer pools allocated in the BM and used by a port or a
+ * storage-profile.
+ */
+struct fm_ext_pools_t {
+	uint8_t num_of_pools_used; /* Number of pools use by this port */
+	struct fm_ext_pool_params_t ext_buf_pool[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+					/* Parameters for each port */
+};
+
+/* A structure for defining backup BM Pools. */
+struct fm_backup_bm_pools_t {
+	/* Number of BM backup pools -  must be smaller
+	 * than the total number of pools defined for the specified port.
+	 */
+	uint8_t num_of_backup_pools;
+	/* num_of_backup_pools pool id's, specifying which pools should
+	 * be used only as backup. Pool id's specified here must be a
+	 * subset of the pools used by the specified port.
+	 */
+	uint8_t pool_ids[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+};
+
+/* A structure for defining BM pool depletion criteria */
+struct fm_buf_pool_depletion_t {
+	/* select mode in which pause frames will be sent after a
+	 * number of pools (all together!) are depleted
+	 */
+	bool pools_grp_mode_enable;
+	/* the number of depleted pools that will invoke pause
+	 * frames transmission.
+	 */
+	uint8_t num_of_pools;
+	/* For each pool, true if it should be considered for
+	 * depletion (Note - this pool must be used by this port!).
+	 */
+	bool pools_to_consider[BM_MAX_NUM_OF_POOLS];
+	/* select mode in which pause frames will be sent
+	 * after a single-pool is depleted;
+	 */
+	bool single_pool_mode_enable;
+	/* For each pool, true if it should be considered
+	 * for depletion (Note - this pool must be used by this port!)
+	 */
+	bool pools_to_consider_for_single_mode[BM_MAX_NUM_OF_POOLS];
+};
+
+/* A Structure for defining Ucode patch for loading. */
+struct fm_firmware_params_t {
+	uint32_t size;			/* Size of uCode */
+	uint32_t *p_code;		/* A pointer to the uCode */
+};
+
+/* A Structure for defining FM initialization parameters */
+struct fm_params_t {
+	uint8_t fm_id;
+	/* Index of the FM */
+	uintptr_t base_addr;
+	/* A pointer to base of memory mapped FM registers (virtual);
+	 * NOTE that this should include ALL common registers of the FM
+	 * including the PCD registers area.
+	 */
+	struct muram_info *p_muram;
+	/* A pointer to an initialized MURAM object, to be used by the FM. */
+	uint16_t fm_clk_freq;
+	/* In Mhz; */
+	fm_exceptions_cb *f_exception;
+	/* An application callback routine to handle exceptions; */
+	fm_bus_error_cb *f_bus_error;
+	/* An application callback routine to handle exceptions; */
+	void *h_app;
+	/* A handle to an application layer object; This handle will be
+	 * passed by the driver upon calling the above callbacks;
+	 */
+	struct fm_firmware_params_t firmware;
+	/* The firmware parameters structure; */
+};
+
+/* FM_Config
+ * Creates the FM module and returns its handle (descriptor).
+ * This descriptor must be passed as first parameter to all other
+ * FM function calls.
+ * No actual initialization or configuration of FM hardware is
+ * done by this routine. All FM parameters get default values that
+ * may be changed by calling one or more of the advance config
+ * routines.
+ * p_fm_params  - A pointer to a data structure of mandatory FM parameters
+ * Return        A handle to the FM object, or NULL for Failure.
+ */
+void *fm_config(struct fm_params_t *p_fm_params);
+
+/* fm_init
+ * Initializes the FM module by defining the software structure
+ * and configuring the hardware registers.
+ * h_fm - FM module descriptor
+ * Return        0 on success; Error code otherwise.
+ */
+int fm_init(void *h_fm);
+
+/* fm_free
+ * Frees all resources that were assigned to FM module.
+ * Calling this routine invalidates the descriptor.
+ * h_fm - FM module descriptor
+ * Return        0 on success; Error code otherwise.
+ */
+int fm_free(void *h_fm);
+
+/* Enum for choosing the field that will be output on AID */
+enum fm_dma_aid_mode {
+	FM_DMA_AID_OUT_PORT_ID = 0,	    /* 4 LSB of PORT_ID */
+	FM_DMA_AID_OUT_TNUM		    /* 4 LSB of TNUM */
+};
+
+/*  Enum for selecting DMA Emergency level by BMI emergency signal */
+enum fm_dma_emergency_level {
+	FM_DMA_EM_EBS = 0,		    /* EBS emergency */
+	FM_DMA_EM_SOS			    /* SOS emergency */
+};
+
+/* Enum for selecting DMA Emergency options */
+/* Enable emergency for MURAM1 */
+#define  FM_DMA_MURAM_READ_EMERGENCY        0x00800000
+/* Enable emergency for MURAM2 */
+#define  FM_DMA_MURAM_WRITE_EMERGENCY       0x00400000
+/* Enable emergency for external bus */
+#define  FM_DMA_EXT_BUS_EMERGENCY           0x00100000
+
+/* fm_cfg_reset_on_init
+ * Define whether to reset the FM before initialization.
+ * Change the default configuration [DEFAULT_RESET_ON_INIT].
+ * h_fm                A handle to an FM Module.
+ * enable              When true, FM will be reset before any
+ * Return        0 on success; Error code otherwise.
+ * Allowed only following fm_config() and before fm_init().
+ */
+int fm_cfg_reset_on_init(void *h_fm, bool enable);
+
+/* fm_cfg_total_fifo_size
+ * Define Total FIFO size for the whole FM.
+ * Calling this routine changes the total Fifo size in the internal driver
+ * data base from its default configuration [DEFAULT_total_fifo_size]
+ *   h_fm                A handle to an FM Module.
+ *   total_fifo_size       The selected new value.
+ *  Return        0 on success; Error code otherwise.
+ *  Allowed only following fm_config() and before fm_init().
+ */
+int fm_cfg_total_fifo_size(void *h_fm, uint32_t total_fifo_size);
+
+/* fm_cfg_dma_aid_override
+ * Define DMA AID override mode.
+ * Calling this routine changes the AID override mode
+ * in the internal driver data base from its default
+ * configuration  [DEFAULT_aid_override]
+ * h_fm            A handle to an FM Module.
+ * aid_override     The selected new value.
+ * Return        0 on success; Error code otherwise.
+ * Allowed only following fm_config() and before fm_init().
+ */
+int fm_cfg_dma_aid_override(void *h_fm, bool aid_override);
+
+/* General FM defines. */
+#define FM_MAX_NUM_OF_VALID_PORTS   (FM_MAX_NUM_OF_OH_PORTS +       \
+				     FM_MAX_NUM_OF_1G_RX_PORTS +    \
+				     FM_MAX_NUM_OF_10G_RX_PORTS +   \
+				     FM_MAX_NUM_OF_1G_TX_PORTS +    \
+				     FM_MAX_NUM_OF_10G_TX_PORTS)
+				     /* Number of available FM ports */
+
+/* A Structure for Port bandwidth requirement.
+ * Port is identified by type and relative id.
+ */
+struct fm_port_bandwidth_t {
+	enum fm_port_type type;		/* FM port type */
+	uint8_t relative_port_id;	/* Type relative port id */
+	uint8_t bandwidth;	/* bandwidth - (in term of percents) */
+};
+
+/* A Structure containing an array of Port bandwidth requirements.
+ * The user should state the ports requiring bandwidth in terms of
+ * percentage - i.e. all port's bandwidths in the array must add
+ * up to 100.
+ */
+struct fm_ports_bandwidth_params_t {
+	/* The number of relevant ports, which is the number of
+	 * valid entries in the array below
+	 */
+	uint8_t num_of_ports;
+	/* for each port, it's bandwidth (all port's bandwidths
+	 * must add up to 100.
+	 */
+	struct fm_port_bandwidth_t ports_bandwidths[FM_MAX_NUM_OF_VALID_PORTS];
+};
+
+/* A Structure for returning FM revision information */
+struct fm_revision_info_t {
+	uint8_t major_rev;		    /* Major revision */
+	uint8_t minor_rev;		    /* Minor revision */
+};
+
+/* A Structure for returning FM ctrl code revision information */
+struct fm_ctrl_code_revision_info_t {
+	uint16_t package_rev;		    /* Package revision */
+	uint8_t major_rev;		    /* Major revision */
+	uint8_t minor_rev;		    /* Minor revision */
+};
+
+/*  fm_set_exception
+ *   Calling this routine enables/disables the specified
+ *                 exception.
+ *   h_fm            A handle to an FM Module.
+ *   exception       The exception to be selected.
+ *   enable          true to enable interrupt, false to mask it.
+ *  Return        0 on success; Error code otherwise.
+ *  Allowed only following fm_init().
+ */
+int fm_set_exception(void *h_fm, enum fm_exceptions exception,
+		     bool enable);
+
+/*   fm_disable_rams_ecc
+ *   Disables ECC mechanism for all the different FM RAM's; E.g. IRAM,
+ *		MURAM, etc.
+ *		Note:
+ *		In opposed to fm_enable_rams_ecc, this routine must be called
+ *		explicitly to disable all Rams ECC.
+ *   h_fm            A handle to an FM Module.
+ *  Return        0 on success; Error code otherwise.
+ *  Allowed only following fm_config() and before fm_init().
+ */
+int fm_disable_rams_ecc(void *h_fm);
+
+/*  fm_get_revision
+ *  Returns the FM revision
+ *  h_fm                A handle to an FM Module.
+ *  p_fm_revision_info    A structure of revision
+ *                                       information parameters.
+ *  Return        0 on success; Error code otherwise.
+ *  Allowed only following fm_init().
+ */
+int fm_get_revision(void *h_fm,
+		    struct fm_revision_info_t *p_fm_revision_info);
+
+/* fm_error_isr
+ * FM interrupt-service-routine for errors.
+ * h_fm            A handle to an FM Module.
+ * Return        0 on success; EMPTY if no errors found in register, other
+ *		error code otherwise.
+ * Allowed only following fm_init().
+ */
+int fm_error_isr(void *h_fm);
+
+/*  fm_event_isr
+ *  FM interrupt-service-routine for normal events.
+ *  h_fm            A handle to an FM Module.
+ *  Allowed only following fm_init().
+ */
+void fm_event_isr(void *h_fm);
+
+#ifdef NCSW_BACKWARD_COMPATIBLE_API
+
+#define FM_CONTEXTA_GET_OVVERIDE    FM_CONTEXTA_GET_OVERRIDE
+#define FM_CONTEXTA_SET_OVVERIDE    FM_CONTEXTA_SET_OVERRIDE
+
+#define FM_EX_BMI_PIPELINE_ECC    FM_EX_BMI_STORAGE_PROFILE_ECC
+#define FM_PORT_DMA_NO_SWP        FM_DMA_NO_SWP
+#define FM_PORT_DMA_SWP_PPC_LE    FM_DMA_SWP_PPC_LE
+#define FM_PORT_DMA_SWP_BE        FM_DMA_SWP_BE
+#define FM_PORT_DMA_NO_STASH      FM_DMA_NO_STASH
+#define FM_PORT_DMA_STASH         FM_DMA_STASH
+#endif /* NCSW_BACKWARD_COMPATIBLE_API */
+
+#endif /* __FM_EXT */
diff --git a/drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h b/drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h
new file mode 100644
index 0000000..cfbf462
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Linux internal kernel API */
+
+#ifndef __FSL_FMAN_DRV_H
+#define __FSL_FMAN_DRV_H
+
+#include <linux/types.h>
+#include <linux/device.h>	/* struct device */
+
+/* FM device opaque structure used for type checking */
+struct fm;
+
+/* fm_bind
+ *	Bind to a specific FM device.
+ *
+ * fm_dev	- the OF handle of the FM device.
+ *  Return	A handle of the FM device.
+ *  Allowed only after the port was created.
+ */
+struct fm *fm_bind(struct device *fm_dev);
+
+/* fm_unbind
+ * Un-bind from a specific FM device.
+ *  fm	- A handle of the FM device.
+ *  Allowed only after the port was created.
+ */
+void fm_unbind(struct fm *fm);
+
+void *fm_get_handle(struct fm *fm);
+struct resource *fm_get_mem_region(struct fm *fm);
+
+/*	fm_mutex_lock
+ *
+ *   Lock function required before any FMD/LLD call.
+ */
+void fm_mutex_lock(void);
+
+/*	fm_mutex_unlock
+ *
+ *   Unlock function required after any FMD/LLD call.
+ */
+void fm_mutex_unlock(void);
+
+/*	fm_get_max_frm
+ *
+ *   Get the maximum frame size
+ */
+u16 fm_get_max_frm(void);
+
+/*	fm_get_rx_extra_headroom
+ *
+ *   Get the extra headroom size
+ */
+int fm_get_rx_extra_headroom(void);
+
+/* default values for initializing PTP 1588 timer clock */
+/* power of 2 for better performance */
+#define DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT 2
+/* 4ns,250MHz */
+#define DPA_PTP_NOMINAL_FREQ_PERIOD_NS \
+(1 << DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT)
+
+#endif /* __FSL_FMAN_DRV_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/net_ext.h b/drivers/net/ethernet/freescale/fman/inc/net_ext.h
new file mode 100644
index 0000000..a05ace0
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/net_ext.h
@@ -0,0 +1,534 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* net_ext.h
+ * This file contains common and general headers definitions.
+ */
+#ifndef __NET_EXT_H
+#define __NET_EXT_H
+
+#define NET_HEADER_FIELD_PPP_PID                        (1)
+#define NET_HEADER_FIELD_PPP_COMPRESSED \
+(NET_HEADER_FIELD_PPP_PID << 1)
+#define NET_HEADER_FIELD_PPP_ALL_FIELDS \
+((NET_HEADER_FIELD_PPP_PID << 2) - 1)
+
+#define NET_HEADER_FIELD_PPPOE_VER                      (1)
+#define NET_HEADER_FIELD_PPPOE_TYPE \
+(NET_HEADER_FIELD_PPPOE_VER << 1)
+#define NET_HEADER_FIELD_PPPOE_CODE \
+(NET_HEADER_FIELD_PPPOE_VER << 2)
+#define NET_HEADER_FIELD_PPPOE_SID \
+(NET_HEADER_FIELD_PPPOE_VER << 3)
+#define NET_HEADER_FIELD_PPPOE_LEN \
+(NET_HEADER_FIELD_PPPOE_VER << 4)
+#define NET_HEADER_FIELD_PPPOE_SESSION \
+(NET_HEADER_FIELD_PPPOE_VER << 5)
+#define NET_HEADER_FIELD_PPPOE_PID \
+(NET_HEADER_FIELD_PPPOE_VER << 6)
+#define NET_HEADER_FIELD_PPPOE_ALL_FIELDS \
+((NET_HEADER_FIELD_PPPOE_VER << 7) - 1)
+
+#define NET_HEADER_FIELD_PPPMUX_PID                     (1)
+#define NET_HEADER_FIELD_PPPMUX_CKSUM \
+(NET_HEADER_FIELD_PPPMUX_PID << 1)
+#define NET_HEADER_FIELD_PPPMUX_COMPRESSED \
+(NET_HEADER_FIELD_PPPMUX_PID << 2)
+#define NET_HEADER_FIELD_PPPMUX_ALL_FIELDS \
+((NET_HEADER_FIELD_PPPMUX_PID << 3) - 1)
+
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF            (1)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_LXT \
+(NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 1)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_LEN \
+(NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 2)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_PID \
+(NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 3)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_USE_PID \
+(NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 4)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_ALL_FIELDS \
+((NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 5) - 1)
+
+#define NET_HEADER_FIELD_ETH_DA                         (1)
+#define NET_HEADER_FIELD_ETH_SA \
+(NET_HEADER_FIELD_ETH_DA << 1)
+#define NET_HEADER_FIELD_ETH_LENGTH \
+(NET_HEADER_FIELD_ETH_DA << 2)
+#define NET_HEADER_FIELD_ETH_TYPE \
+(NET_HEADER_FIELD_ETH_DA << 3)
+#define NET_HEADER_FIELD_ETH_FINAL_CKSUM \
+(NET_HEADER_FIELD_ETH_DA << 4)
+#define NET_HEADER_FIELD_ETH_PADDING \
+(NET_HEADER_FIELD_ETH_DA << 5)
+#define NET_HEADER_FIELD_ETH_ALL_FIELDS \
+((NET_HEADER_FIELD_ETH_DA << 6) - 1)
+
+#define NET_HEADER_FIELD_ETH_ADDR_SIZE                 6
+
+#define NET_HEADER_FIELD_IP_VER                         (1)
+#define NET_HEADER_FIELD_IP_DSCP \
+(NET_HEADER_FIELD_IP_VER << 2)
+#define NET_HEADER_FIELD_IP_ECN \
+(NET_HEADER_FIELD_IP_VER << 3)
+#define NET_HEADER_FIELD_IP_PROTO \
+(NET_HEADER_FIELD_IP_VER << 4)
+
+#define NET_HEADER_FIELD_IP_PROTO_SIZE                  1
+
+#define NET_HEADER_FIELD_IPV4_VER                       (1)
+#define NET_HEADER_FIELD_IPV4_HDR_LEN \
+(NET_HEADER_FIELD_IPV4_VER << 1)
+#define NET_HEADER_FIELD_IPV4_TOS \
+(NET_HEADER_FIELD_IPV4_VER << 2)
+#define NET_HEADER_FIELD_IPV4_TOTAL_LEN \
+(NET_HEADER_FIELD_IPV4_VER << 3)
+#define NET_HEADER_FIELD_IPV4_ID \
+(NET_HEADER_FIELD_IPV4_VER << 4)
+#define NET_HEADER_FIELD_IPV4_FLAG_D \
+(NET_HEADER_FIELD_IPV4_VER << 5)
+#define NET_HEADER_FIELD_IPV4_FLAG_M \
+(NET_HEADER_FIELD_IPV4_VER << 6)
+#define NET_HEADER_FIELD_IPV4_OFFSET \
+(NET_HEADER_FIELD_IPV4_VER << 7)
+#define NET_HEADER_FIELD_IPV4_TTL \
+(NET_HEADER_FIELD_IPV4_VER << 8)
+#define NET_HEADER_FIELD_IPV4_PROTO \
+(NET_HEADER_FIELD_IPV4_VER << 9)
+#define NET_HEADER_FIELD_IPV4_CKSUM \
+(NET_HEADER_FIELD_IPV4_VER << 10)
+#define NET_HEADER_FIELD_IPV4_SRC_IP \
+(NET_HEADER_FIELD_IPV4_VER << 11)
+#define NET_HEADER_FIELD_IPV4_DST_IP \
+(NET_HEADER_FIELD_IPV4_VER << 12)
+#define NET_HEADER_FIELD_IPV4_OPTS \
+(NET_HEADER_FIELD_IPV4_VER << 13)
+#define NET_HEADER_FIELD_IPV4_OPTS_COUNT \
+(NET_HEADER_FIELD_IPV4_VER << 14)
+#define NET_HEADER_FIELD_IPV4_ALL_FIELDS \
+((NET_HEADER_FIELD_IPV4_VER << 15) - 1)
+
+#define NET_HEADER_FIELD_IPV4_ADDR_SIZE                 4
+#define NET_HEADER_FIELD_IPV4_PROTO_SIZE                1
+
+#define NET_HEADER_FIELD_IPV6_VER                       (1)
+#define NET_HEADER_FIELD_IPV6_TC \
+(NET_HEADER_FIELD_IPV6_VER << 1)
+#define NET_HEADER_FIELD_IPV6_SRC_IP  \
+(NET_HEADER_FIELD_IPV6_VER << 2)
+#define NET_HEADER_FIELD_IPV6_DST_IP \
+(NET_HEADER_FIELD_IPV6_VER << 3)
+#define NET_HEADER_FIELD_IPV6_NEXT_HDR \
+(NET_HEADER_FIELD_IPV6_VER << 4)
+#define NET_HEADER_FIELD_IPV6_FL \
+(NET_HEADER_FIELD_IPV6_VER << 5)
+#define NET_HEADER_FIELD_IPV6_HOP_LIMIT \
+(NET_HEADER_FIELD_IPV6_VER << 6)
+#define NET_HEADER_FIELD_IPV6_ALL_FIELDS \
+((NET_HEADER_FIELD_IPV6_VER << 7) - 1)
+
+#define NET_HEADER_FIELD_IPV6_ADDR_SIZE                 16
+#define NET_HEADER_FIELD_IPV6_NEXT_HDR_SIZE             1
+
+#define NET_HEADER_FIELD_ICMP_TYPE                      (1)
+#define NET_HEADER_FIELD_ICMP_CODE  \
+(NET_HEADER_FIELD_ICMP_TYPE << 1)
+#define NET_HEADER_FIELD_ICMP_CKSUM  \
+(NET_HEADER_FIELD_ICMP_TYPE << 2)
+#define NET_HEADER_FIELD_ICMP_ID  \
+(NET_HEADER_FIELD_ICMP_TYPE << 3)
+#define NET_HEADER_FIELD_ICMP_SQ_NUM  \
+(NET_HEADER_FIELD_ICMP_TYPE << 4)
+#define NET_HEADER_FIELD_ICMP_ALL_FIELDS \
+((NET_HEADER_FIELD_ICMP_TYPE << 5) - 1)
+
+#define NET_HEADER_FIELD_ICMP_CODE_SIZE                 1
+#define NET_HEADER_FIELD_ICMP_TYPE_SIZE                 1
+
+#define NET_HEADER_FIELD_IGMP_VERSION                   (1)
+#define NET_HEADER_FIELD_IGMP_TYPE \
+(NET_HEADER_FIELD_IGMP_VERSION << 1)
+#define NET_HEADER_FIELD_IGMP_CKSUM \
+(NET_HEADER_FIELD_IGMP_VERSION << 2)
+#define NET_HEADER_FIELD_IGMP_DATA \
+(NET_HEADER_FIELD_IGMP_VERSION << 3)
+#define NET_HEADER_FIELD_IGMP_ALL_FIELDS \
+((NET_HEADER_FIELD_IGMP_VERSION << 4) - 1)
+
+#define NET_HEADER_FIELD_TCP_PORT_SRC                   (1)
+#define NET_HEADER_FIELD_TCP_PORT_DST \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_TCP_SEQ \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_TCP_ACK \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_TCP_OFFSET \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 4)
+#define NET_HEADER_FIELD_TCP_FLAGS \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 5)
+#define NET_HEADER_FIELD_TCP_WINDOW \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 6)
+#define NET_HEADER_FIELD_TCP_CKSUM \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 7)
+#define NET_HEADER_FIELD_TCP_URGPTR \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 8)
+#define NET_HEADER_FIELD_TCP_OPTS  \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 9)
+#define NET_HEADER_FIELD_TCP_OPTS_COUNT \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 10)
+#define NET_HEADER_FIELD_TCP_ALL_FIELDS \
+((NET_HEADER_FIELD_TCP_PORT_SRC << 11) - 1)
+
+#define NET_HEADER_FIELD_TCP_PORT_SIZE                  2
+
+#define NET_HEADER_FIELD_SCTP_PORT_SRC                  (1)
+#define NET_HEADER_FIELD_SCTP_PORT_DST \
+(NET_HEADER_FIELD_SCTP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_SCTP_VER_TAG \
+(NET_HEADER_FIELD_SCTP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_SCTP_CKSUM \
+(NET_HEADER_FIELD_SCTP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_SCTP_ALL_FIELDS \
+((NET_HEADER_FIELD_SCTP_PORT_SRC << 4) - 1)
+
+#define NET_HEADER_FIELD_SCTP_PORT_SIZE                 2
+
+#define NET_HEADER_FIELD_DCCP_PORT_SRC                  (1)
+#define NET_HEADER_FIELD_DCCP_PORT_DST \
+(NET_HEADER_FIELD_DCCP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_DCCP_ALL_FIELDS \
+((NET_HEADER_FIELD_DCCP_PORT_SRC << 2) - 1)
+
+#define NET_HEADER_FIELD_DCCP_PORT_SIZE                 2
+
+#define NET_HEADER_FIELD_UDP_PORT_SRC                   (1)
+#define NET_HEADER_FIELD_UDP_PORT_DST \
+(NET_HEADER_FIELD_UDP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_UDP_LEN  \
+(NET_HEADER_FIELD_UDP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_UDP_CKSUM \
+(NET_HEADER_FIELD_UDP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_UDP_ALL_FIELDS \
+((NET_HEADER_FIELD_UDP_PORT_SRC << 4) - 1)
+
+#define NET_HEADER_FIELD_UDP_PORT_SIZE                  2
+
+#define NET_HEADER_FIELD_UDP_LITE_PORT_SRC              (1)
+#define NET_HEADER_FIELD_UDP_LITE_PORT_DST  \
+(NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 1)
+#define NET_HEADER_FIELD_UDP_LITE_ALL_FIELDS \
+((NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 2) - 1)
+
+#define NET_HEADER_FIELD_UDP_LITE_PORT_SIZE             2
+
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC         (1)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST \
+(NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN \
+(NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM \
+(NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI \
+(NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 4)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM \
+(NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 5)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_ALL_FIELDS \
+((NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 6) - 1)
+
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SIZE        2
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI_SIZE         4
+
+#define NET_HEADER_FIELD_IPHC_CID                       (1)
+#define NET_HEADER_FIELD_IPHC_CID_TYPE \
+(NET_HEADER_FIELD_IPHC_CID << 1)
+#define NET_HEADER_FIELD_IPHC_HCINDEX \
+(NET_HEADER_FIELD_IPHC_CID << 2)
+#define NET_HEADER_FIELD_IPHC_GEN \
+(NET_HEADER_FIELD_IPHC_CID << 3)
+#define NET_HEADER_FIELD_IPHC_D_BIT \
+(NET_HEADER_FIELD_IPHC_CID << 4)
+#define NET_HEADER_FIELD_IPHC_ALL_FIELDS \
+((NET_HEADER_FIELD_IPHC_CID << 5) - 1)
+
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE           (1)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_FLAGS \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 1)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_LENGTH \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 2)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_TSN \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 3)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_ID \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 4)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_SQN \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 5)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_PAYLOAD_PID \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 6)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_UNORDERED \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 7)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_BEGGINING \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 8)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_END  \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 9)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_ALL_FIELDS \
+((NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 10) - 1)
+
+#define NET_HEADER_FIELD_L2TPV2_TYPE_BIT                (1)
+#define NET_HEADER_FIELD_L2TPV2_LENGTH_BIT \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 1)
+#define NET_HEADER_FIELD_L2TPV2_SEQUENCE_BIT \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 2)
+#define NET_HEADER_FIELD_L2TPV2_OFFSET_BIT  \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 3)
+#define NET_HEADER_FIELD_L2TPV2_PRIORITY_BIT \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 4)
+#define NET_HEADER_FIELD_L2TPV2_VERSION \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 5)
+#define NET_HEADER_FIELD_L2TPV2_LEN \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 6)
+#define NET_HEADER_FIELD_L2TPV2_TUNNEL_ID \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 7)
+#define NET_HEADER_FIELD_L2TPV2_SESSION_ID \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 8)
+#define NET_HEADER_FIELD_L2TPV2_NS \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 9)
+#define NET_HEADER_FIELD_L2TPV2_NR \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 10)
+#define NET_HEADER_FIELD_L2TPV2_OFFSET_SIZE \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 11)
+#define NET_HEADER_FIELD_L2TPV2_FIRST_BYTE \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 12)
+#define NET_HEADER_FIELD_L2TPV2_ALL_FIELDS \
+((NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 13) - 1)
+
+#define NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT           (1)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_LENGTH_BIT \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 1)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_SEQUENCE_BIT \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 2)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_VERSION \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 3)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_LENGTH \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 4)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_CONTROL \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 5)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_SENT \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 6)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_RECV \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 7)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_FIRST_BYTE \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 8)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_ALL_FIELDS \
+((NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 9) - 1)
+
+#define NET_HEADER_FIELD_L2TPV3_SESS_TYPE_BIT           (1)
+#define NET_HEADER_FIELD_L2TPV3_SESS_VERSION  \
+(NET_HEADER_FIELD_L2TPV3_SESS_TYPE_BIT << 1)
+#define NET_HEADER_FIELD_L2TPV3_SESS_ID  \
+(NET_HEADER_FIELD_L2TPV3_SESS_TYPE_BIT << 2)
+#define NET_HEADER_FIELD_L2TPV3_SESS_COOKIE  \
+(NET_HEADER_FIELD_L2TPV3_SESS_TYPE_BIT << 3)
+#define NET_HEADER_FIELD_L2TPV3_SESS_ALL_FIELDS  \
+((NET_HEADER_FIELD_L2TPV3_SESS_TYPE_BIT << 4) - 1)
+
+#define NET_HEADER_FIELD_VLAN_VPRI                      (1)
+#define NET_HEADER_FIELD_VLAN_CFI  \
+(NET_HEADER_FIELD_VLAN_VPRI << 1)
+#define NET_HEADER_FIELD_VLAN_VID  \
+(NET_HEADER_FIELD_VLAN_VPRI << 2)
+#define NET_HEADER_FIELD_VLAN_LENGTH  \
+(NET_HEADER_FIELD_VLAN_VPRI << 3)
+#define NET_HEADER_FIELD_VLAN_TYPE  \
+(NET_HEADER_FIELD_VLAN_VPRI << 4)
+#define NET_HEADER_FIELD_VLAN_ALL_FIELDS \
+((NET_HEADER_FIELD_VLAN_VPRI << 5) - 1)
+
+#define NET_HEADER_FIELD_VLAN_TCI \
+(NET_HEADER_FIELD_VLAN_VPRI | \
+NET_HEADER_FIELD_VLAN_CFI | \
+NET_HEADER_FIELD_VLAN_VID)
+
+#define NET_HEADER_FIELD_LLC_DSAP                       (1)
+#define NET_HEADER_FIELD_LLC_SSAP \
+(NET_HEADER_FIELD_LLC_DSAP << 1)
+#define NET_HEADER_FIELD_LLC_CTRL \
+(NET_HEADER_FIELD_LLC_DSAP << 2)
+#define NET_HEADER_FIELD_LLC_ALL_FIELDS  \
+((NET_HEADER_FIELD_LLC_DSAP << 3) - 1)
+
+#define NET_HEADER_FIELD_NLPID_NLPID                    (1)
+#define NET_HEADER_FIELD_NLPID_ALL_FIELDS  \
+((NET_HEADER_FIELD_NLPID_NLPID << 1) - 1)
+
+#define NET_HEADER_FIELD_SNAP_OUI                       (1)
+#define NET_HEADER_FIELD_SNAP_PID  \
+(NET_HEADER_FIELD_SNAP_OUI << 1)
+#define NET_HEADER_FIELD_SNAP_ALL_FIELDS  \
+((NET_HEADER_FIELD_SNAP_OUI << 2) - 1)
+
+#define NET_HEADER_FIELD_LLC_SNAP_TYPE                  (1)
+#define NET_HEADER_FIELD_LLC_SNAP_ALL_FIELDS  \
+((NET_HEADER_FIELD_LLC_SNAP_TYPE << 1) - 1)
+
+#define NET_HEADER_FIELD_ARP_HTYPE                      (1)
+#define NET_HEADER_FIELD_ARP_PTYPE  \
+(NET_HEADER_FIELD_ARP_HTYPE << 1)
+#define NET_HEADER_FIELD_ARP_HLEN  \
+(NET_HEADER_FIELD_ARP_HTYPE << 2)
+#define NET_HEADER_FIELD_ARP_PLEN  \
+(NET_HEADER_FIELD_ARP_HTYPE << 3)
+#define NET_HEADER_FIELD_ARP_OPER  \
+(NET_HEADER_FIELD_ARP_HTYPE << 4)
+#define NET_HEADER_FIELD_ARP_SHA  \
+(NET_HEADER_FIELD_ARP_HTYPE << 5)
+#define NET_HEADER_FIELD_ARP_SPA  \
+(NET_HEADER_FIELD_ARP_HTYPE << 6)
+#define NET_HEADER_FIELD_ARP_THA  \
+(NET_HEADER_FIELD_ARP_HTYPE << 7)
+#define NET_HEADER_FIELD_ARP_TPA  \
+(NET_HEADER_FIELD_ARP_HTYPE << 8)
+#define NET_HEADER_FIELD_ARP_ALL_FIELDS  \
+((NET_HEADER_FIELD_ARP_HTYPE << 9) - 1)
+
+#define NET_HEADER_FIELD_RFC2684_LLC                    (1)
+#define NET_HEADER_FIELD_RFC2684_NLPID  \
+(NET_HEADER_FIELD_RFC2684_LLC << 1)
+#define NET_HEADER_FIELD_RFC2684_OUI  \
+(NET_HEADER_FIELD_RFC2684_LLC << 2)
+#define NET_HEADER_FIELD_RFC2684_PID  \
+(NET_HEADER_FIELD_RFC2684_LLC << 3)
+#define NET_HEADER_FIELD_RFC2684_VPN_OUI  \
+(NET_HEADER_FIELD_RFC2684_LLC << 4)
+#define NET_HEADER_FIELD_RFC2684_VPN_IDX  \
+(NET_HEADER_FIELD_RFC2684_LLC << 5)
+#define NET_HEADER_FIELD_RFC2684_ALL_FIELDS  \
+((NET_HEADER_FIELD_RFC2684_LLC << 6) - 1)
+
+#define NET_HEADER_FIELD_USER_DEFINED_SRCPORT           (1)
+#define NET_HEADER_FIELD_USER_DEFINED_PCDID  \
+(NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 1)
+#define NET_HEADER_FIELD_USER_DEFINED_ALL_FIELDS  \
+((NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 2) - 1)
+
+#define NET_HEADER_FIELD_PAYLOAD_BUFFER                 (1)
+#define NET_HEADER_FIELD_PAYLOAD_SIZE  \
+(NET_HEADER_FIELD_PAYLOAD_BUFFER << 1)
+#define NET_HEADER_FIELD_MAX_FRM_SIZE \
+(NET_HEADER_FIELD_PAYLOAD_BUFFER << 2)
+#define NET_HEADER_FIELD_MIN_FRM_SIZE  \
+(NET_HEADER_FIELD_PAYLOAD_BUFFER << 3)
+#define NET_HEADER_FIELD_PAYLOAD_TYPE  \
+(NET_HEADER_FIELD_PAYLOAD_BUFFER << 4)
+#define NET_HEADER_FIELD_FRAME_SIZE  \
+(NET_HEADER_FIELD_PAYLOAD_BUFFER << 5)
+#define NET_HEADER_FIELD_PAYLOAD_ALL_FIELDS  \
+((NET_HEADER_FIELD_PAYLOAD_BUFFER << 6) - 1)
+
+#define NET_HEADER_FIELD_GRE_TYPE                       (1)
+#define NET_HEADER_FIELD_GRE_ALL_FIELDS  \
+((NET_HEADER_FIELD_GRE_TYPE << 1) - 1)
+
+#define NET_HEADER_FIELD_MINENCAP_SRC_IP                (1)
+#define NET_HEADER_FIELD_MINENCAP_DST_IP  \
+(NET_HEADER_FIELD_MINENCAP_SRC_IP << 1)
+#define NET_HEADER_FIELD_MINENCAP_TYPE  \
+(NET_HEADER_FIELD_MINENCAP_SRC_IP << 2)
+#define NET_HEADER_FIELD_MINENCAP_ALL_FIELDS \
+((NET_HEADER_FIELD_MINENCAP_SRC_IP << 3) - 1)
+
+#define NET_HEADER_FIELD_IPSEC_AH_NH  \
+(NET_HEADER_FIELD_IPSEC_AH_SPI << 1)
+#define NET_HEADER_FIELD_IPSEC_AH_ALL_FIELDS   \
+((NET_HEADER_FIELD_IPSEC_AH_SPI << 2) - 1)
+
+#define NET_HEADER_FIELD_IPSEC_ESP_SPI                  (1)
+#define NET_HEADER_FIELD_IPSEC_ESP_SEQUENCE_NUM  \
+(NET_HEADER_FIELD_IPSEC_ESP_SPI << 1)
+#define NET_HEADER_FIELD_IPSEC_ESP_ALL_FIELDS  \
+((NET_HEADER_FIELD_IPSEC_ESP_SPI << 2) - 1)
+
+#define NET_HEADER_FIELD_IPSEC_ESP_SPI_SIZE             4
+
+#define NET_HEADER_FIELD_MPLS_LABEL_STACK               (1)
+#define NET_HEADER_FIELD_MPLS_LABEL_STACK_ALL_FIELDS \
+((NET_HEADER_FIELD_MPLS_LABEL_STACK << 1) - 1)
+
+#define NET_HEADER_FIELD_MACSEC_SECTAG                  (1)
+#define NET_HEADER_FIELD_MACSEC_ALL_FIELDS  \
+((NET_HEADER_FIELD_MACSEC_SECTAG << 1) - 1)
+
+enum net_header_type {
+	HEADER_TYPE_NONE = 0,
+	HEADER_TYPE_PAYLOAD,
+	HEADER_TYPE_ETH,
+	HEADER_TYPE_VLAN,
+	HEADER_TYPE_IPV4,
+	HEADER_TYPE_IPV6,
+	HEADER_TYPE_IP,
+	HEADER_TYPE_TCP,
+	HEADER_TYPE_UDP,
+	HEADER_TYPE_UDP_LITE,
+	HEADER_TYPE_IPHC,
+	HEADER_TYPE_SCTP,
+	HEADER_TYPE_SCTP_CHUNK_DATA,
+	HEADER_TYPE_PPPOE,
+	HEADER_TYPE_PPP,
+	HEADER_TYPE_PPPMUX,
+	HEADER_TYPE_PPPMUX_SUBFRAME,
+	HEADER_TYPE_L2TPV2,
+	HEADER_TYPE_L2TPV3_CTRL,
+	HEADER_TYPE_L2TPV3_SESS,
+	HEADER_TYPE_LLC,
+	HEADER_TYPE_LLC_SNAP,
+	HEADER_TYPE_NLPID,
+	HEADER_TYPE_SNAP,
+	HEADER_TYPE_MPLS,
+	HEADER_TYPE_IPSEC_AH,
+	HEADER_TYPE_IPSEC_ESP,
+	HEADER_TYPE_UDP_ENCAP_ESP,	/* RFC 3948 */
+	HEADER_TYPE_MACSEC,
+	HEADER_TYPE_GRE,
+	HEADER_TYPE_MINENCAP,
+	HEADER_TYPE_DCCP,
+	HEADER_TYPE_ICMP,
+	HEADER_TYPE_IGMP,
+	HEADER_TYPE_ARP,
+	HEADER_TYPE_CAPWAP,
+	HEADER_TYPE_CAPWAP_DTLS,
+	HEADER_TYPE_RFC2684,
+	HEADER_TYPE_USER_DEFINED_L2,
+	HEADER_TYPE_USER_DEFINED_L3,
+	HEADER_TYPE_USER_DEFINED_L4,
+	HEADER_TYPE_USER_DEFINED_SHIM1,
+	HEADER_TYPE_USER_DEFINED_SHIM2,
+	MAX_HEADER_TYPE_COUNT
+};
+
+#endif /* __NET_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/service.h b/drivers/net/ethernet/freescale/fman/inc/service.h
new file mode 100644
index 0000000..7311d10
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/service.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SERVICE_h
+#define __SERVICE_h
+
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+/* Define ASSERT condition */
+#undef ASSERT
+#define ASSERT(x)       WARN_ON(!(x))
+
+/* In range macro */
+#define IN_RANGE(min, val, max) ((min) <= (val) && (val) <= (max))
+
+/* Ceiling division - not the fastest way, but safer in terms of overflow */
+#define DIV_CEIL(x, y) \
+	((div64_u64(x, y)) + (((((div64_u64(x, y))) * (y)) == (x)) ? 0 : 1))
+
+/* Round up a number to be a multiple of a second number */
+#define ROUND_UP(x, y)   ((((x) + (y) - 1) / (y)) * (y))
+
+#define PTR_TO_UINT(_ptr)           ((uintptr_t)(_ptr))
+#define UINT_TO_PTR(_val)           ((void __iomem *)(uintptr_t)(_val))
+#define PTR_MOVE(_ptr, _offset)     (void *)((uint8_t *)(_ptr) + (_offset))
+
+/* memory access macros */
+#define GET_UINT8(arg)		in_be8(&(arg))
+#define GET_UINT16(arg)		in_be16(&(arg))
+#define GET_UINT32(arg)		in_be32(&(arg))
+#define GET_UINT64(arg)		(*(__iomem uint64_t *)(&(arg)))
+
+#define WRITE_UINT8(arg, data)		out_be8(&(arg), data)
+#define WRITE_UINT16(arg, data)	out_be16(&(arg), data)
+#define WRITE_UINT32(arg, data)	out_be32(&(arg), data)
+#define WRITE_UINT64(arg, data)	(*(__iomem uint64_t *)(&(arg)) = (data))
+
+/* Timing macro for converting usec units to number of ticks
+ * (number of usec* clock_Hz) / 1,000,000) - since clk is in MHz units,
+ * no division needed.
+ */
+#define USEC_TO_CLK(usec, clk)       ((usec) * (clk))
+#define CYCLES_TO_USEC(cycles, clk)  ((cycles) / (clk))
+
+#define ILLEGAL_BASE    (~0)
+
+/* Enumeration (bit flags) of communication modes (Transmit,
+ * receive or both).
+ */
+enum comm_mode {
+	COMM_MODE_NONE = 0,	    /* No transmit/receive communication */
+	COMM_MODE_RX = 1,	    /* Only receive communication */
+	COMM_MODE_TX = 2,	    /* Only transmit communication */
+	COMM_MODE_RX_AND_TX = 3   /*Both transmit and receive communication*/
+};
+
+#endif /* SERVICE */
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 09/12] fsl/fman: Add FMan MAC support
  2015-05-07 13:05             ` [RFC,v3 08/12] fsl/fman: Add Frame Manager support Madalin Bucur
@ 2015-05-07 13:05               ` Madalin Bucur
  2015-05-07 13:05                 ` [RFC,v3 10/12] fsl/fman: Add FMan SP support Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

Add Frame Manger MAC Driver support.
This patch adds The FMan MAC configuration, initialization and
runtime control routines.
This patch contains support for these types of MACs:
	tGEC, dTSEC and mEMAC

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 drivers/net/ethernet/freescale/fman/fm.c           |   77 ++
 drivers/net/ethernet/freescale/fman/fm.h           |    4 +-
 drivers/net/ethernet/freescale/fman/fm_common.h    |   41 +
 .../ethernet/freescale/fman/inc/crc_mac_addr_ext.h |  343 ++++++
 .../net/ethernet/freescale/fman/inc/fm_mac_ext.h   |  452 ++++++++
 drivers/net/ethernet/freescale/fman/mac/Makefile   |    7 +-
 drivers/net/ethernet/freescale/fman/mac/dtsec.c    | 1226 ++++++++++++++++++++
 drivers/net/ethernet/freescale/fman/mac/dtsec.h    |  185 +++
 .../ethernet/freescale/fman/mac/dtsec_mii_acc.c    |   82 ++
 .../ethernet/freescale/fman/mac/dtsec_mii_acc.h    |   43 +
 drivers/net/ethernet/freescale/fman/mac/fm_mac.c   |  510 ++++++++
 drivers/net/ethernet/freescale/fman/mac/fm_mac.h   |  183 +++
 drivers/net/ethernet/freescale/fman/mac/memac.c    |  837 +++++++++++++
 drivers/net/ethernet/freescale/fman/mac/memac.h    |  103 ++
 .../ethernet/freescale/fman/mac/memac_mii_acc.c    |   66 ++
 .../ethernet/freescale/fman/mac/memac_mii_acc.h    |   50 +
 drivers/net/ethernet/freescale/fman/mac/tgec.c     |  797 +++++++++++++
 drivers/net/ethernet/freescale/fman/mac/tgec.h     |  112 ++
 .../net/ethernet/freescale/fman/mac/tgec_mii_acc.h |   66 ++
 19 files changed, 5181 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec.h
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_mac.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_mac.h
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac.h
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/tgec.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/tgec.h
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h

diff --git a/drivers/net/ethernet/freescale/fman/fm.c b/drivers/net/ethernet/freescale/fman/fm.c
index fbe4c16..c8889bd 100644
--- a/drivers/net/ethernet/freescale/fman/fm.c
+++ b/drivers/net/ethernet/freescale/fman/fm.c
@@ -703,6 +703,36 @@ static int fw_not_reset_erratum_bugzilla6173wa(struct fm_t *p_fm)
 #endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
 
 /*       Inter-Module functions         */
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_10g_tx_ecc_workaround(void *h_fm, uint8_t mac_id)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	uint8_t rx_port_id, tx_port_id;
+	struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+	if (!(is_fman_ctrl_code_loaded(p_fm)))
+		return -ENOSYS;
+
+	SW_PORT_ID_TO_HW_PORT_ID(p_fm->p_fm_state_struct->rev_info.major_rev,
+				 rx_port_id,
+				 FM_PORT_TYPE_RX,
+				 mac_id);
+	SW_PORT_ID_TO_HW_PORT_ID(p_fm->p_fm_state_struct->rev_info.major_rev,
+				 tx_port_id,
+				 FM_PORT_TYPE_TX,
+				 mac_id);
+
+	if ((p_fm->p_fm_state_struct->ports_types[rx_port_id] !=
+	     FM_PORT_TYPE_DUMMY) ||
+	    (p_fm->p_fm_state_struct->ports_types[tx_port_id] !=
+		FM_PORT_TYPE_DUMMY)) {
+		pr_err("Initialize MAC  prior to Rx & Tx ports!\n");
+		return -ENOSYS;
+	}
+
+	return fman_set_erratum_10gmac_a004_wa(fpm_rg);
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
 
 void fm_register_intr(void *h_fm, enum fm_event_modules module,
 		      uint8_t mod_id, enum fm_intr_type intr_type,
@@ -739,6 +769,53 @@ uint8_t fm_get_id(void *h_fm)
 	return p_fm->p_fm_state_struct->fm_id;
 }
 
+int fm_reset_mac(void *h_fm, enum fm_mac_type type, uint8_t mac_id)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	int err;
+	struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+	if (p_fm->p_fm_state_struct->rev_info.major_rev >= 6) {
+		pr_warn("FMan MAC reset!\n");
+		return -ENOSYS;
+	}
+	if (!p_fm->base_addr) {
+		pr_warn("'base_address' is required!\n");
+		return -ENOSYS;
+	}
+	err =
+	    (int)fman_reset_mac(fpm_rg, mac_id);
+
+	if (err == -EINVAL) {
+		pr_warn("Illegal MAC Id\n");
+		return -EINVAL;
+	} else if (err == EINVAL) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int fm_set_mac_max_frame(void *h_fm, enum fm_mac_type type,
+			 uint8_t mac_id,
+			     uint16_t mtu)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+	/* if port is already initialized, check that MaxFrameLength is smaller
+	 * or equal to the port's max
+	 */
+	if ((!p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id]) ||
+	    (p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id] &&
+	    (mtu <=
+	    p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id]))) {
+		p_fm->p_fm_state_struct->mac_max_frame_lengths[mac_id] = mtu;
+	} else {
+		pr_warn("MAC max_frame_length is larger than Port max_frame_length\n");
+		return -EDOM;
+	}
+	return 0;
+}
+
 uint16_t fm_get_clock_freq(void *h_fm)
 {
 	struct fm_t *p_fm = (struct fm_t *)h_fm;
diff --git a/drivers/net/ethernet/freescale/fman/fm.h b/drivers/net/ethernet/freescale/fman/fm.h
index ba5bb16..0f8d028 100644
--- a/drivers/net/ethernet/freescale/fman/fm.h
+++ b/drivers/net/ethernet/freescale/fman/fm.h
@@ -391,6 +391,7 @@ struct fm_state_struct_t {
 /* Master/Guest parameters */
 
 	uint8_t fm_id;
+	enum fm_port_type ports_types[FM_MAX_NUM_OF_HW_PORT_IDS];
 	uint16_t fm_clk_freq;
 	struct fm_revision_info_t rev_info;
 
@@ -416,6 +417,8 @@ struct fm_state_struct_t {
 	uint32_t extra_fifo_pool_size;
 	uint8_t extra_tasks_pool_size;
 	uint8_t extra_open_dmas_pool_size;
+	uint16_t port_max_frame_lengths[FM_MAX_NUM_OF_MACS];
+	uint16_t mac_max_frame_lengths[FM_MAX_NUM_OF_MACS];
 };
 
 struct fm_intg_t {
@@ -466,7 +469,6 @@ struct fm_t {
 	struct fm_state_struct_t *p_fm_state_struct;
 	uint16_t tnum_aging_period;
 
-/* un-needed for recovery */
 	struct fman_cfg *p_fm_drv_param;
 	struct muram_info *p_muram;
 	phys_addr_t fm_muram_phys_base_addr;
diff --git a/drivers/net/ethernet/freescale/fman/fm_common.h b/drivers/net/ethernet/freescale/fman/fm_common.h
index f9d6575..4fe12c6 100644
--- a/drivers/net/ethernet/freescale/fman/fm_common.h
+++ b/drivers/net/ethernet/freescale/fman/fm_common.h
@@ -174,6 +174,30 @@ static inline bool TRY_LOCK(spinlock_t *spinlock, volatile bool *p_flag)
 
 #define FM_CTL_PARAMS_PAGE_ERROR_VSP_MASK       0x0000003f
 
+/* Description       Port Id defines */
+#define BASE_OH_PORTID(major)		(major >= 6 ? 2 : 1)
+#define BASE_RX_PORTID			0x08
+#define BASE_TX_PORTID			0x28
+
+#define SW_PORT_ID_TO_HW_PORT_ID(major, _port,	type, mac_id)		\
+do {									\
+	switch (type) {							\
+	case (FM_PORT_TYPE_OP):						\
+		_port = (uint8_t)(BASE_OH_PORTID(major) + mac_id);	\
+		break;							\
+	case (FM_PORT_TYPE_RX):					\
+		_port = (uint8_t)(BASE_RX_PORTID + mac_id);		\
+		break;							\
+	case (FM_PORT_TYPE_TX):					\
+		_port = (uint8_t)(BASE_TX_PORTID + mac_id);		\
+		break;							\
+	default:							\
+		pr_err("Illegal port type\n");				\
+		_port = 0;						\
+		break;							\
+	}								\
+} while (0)
+
 #define BMI_MAX_FIFO_SIZE                   (FM_MURAM_SIZE)
 #define BMI_FIFO_UNITS                      0x100
 
@@ -292,6 +316,16 @@ struct muram_info *fm_get_muram_pointer(void *h_fm);
 void fm_get_physical_muram_base(void *h_fm,
 				struct fm_phys_addr_t *fm_phys_addr);
 
+/* Function      fm_reset_mac
+ * Description   Used by MAC driver to reset the MAC registers
+ * Param[in]     h_fm            A handle to an FM Module.
+ * Param[in]     type            MAC type.
+ * Param[in]     mac_id           MAC id - according to type.
+ * Return        0 on success; Error code otherwise.
+ * Cautions      Allowed only following fm_init().
+ */
+int fm_reset_mac(void *h_fm, enum fm_mac_type type, uint8_t mac_id);
+
 /* Function      fm_get_clock_freq
  * Description   Used by MAC driver to get the FM clock frequency
  * Param[in]     h_fm            A handle to an FM Module.
@@ -308,6 +342,10 @@ uint16_t fm_get_clock_freq(void *h_fm);
  */
 uint8_t fm_get_id(void *h_fm);
 
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_10g_tx_ecc_workaround(void *h_fm, uint8_t mac_id);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
 void fm_muram_clear(struct muram_info *p_muram);
 int fm_set_num_of_open_dmas(void *h_fm,
 			    uint8_t port_id,
@@ -328,4 +366,7 @@ int fm_set_size_of_fifo(void *h_fm,
 uint32_t fm_get_bmi_max_fifo_size(void *h_fm);
 struct num_of_ports_info_t *fm_get_num_of_ports(void *h_fm);
 
+int fm_set_mac_max_frame(void *h_fm, enum fm_mac_type type,
+			 uint8_t mac_id, uint16_t mtu);
+
 #endif /* __FM_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h b/drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h
new file mode 100644
index 0000000..12468cb
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Define a macro that calculate the crc value of an Ethernet MAC address
+ * (48 bitd address)
+ */
+
+#ifndef __crc_mac_addr_ext_h
+#define __crc_mac_addr_ext_h
+
+#include <linux/bitrev.h>
+
+static uint32_t crc_table[256] = {
+	0x00000000,
+	0x77073096,
+	0xee0e612c,
+	0x990951ba,
+	0x076dc419,
+	0x706af48f,
+	0xe963a535,
+	0x9e6495a3,
+	0x0edb8832,
+	0x79dcb8a4,
+	0xe0d5e91e,
+	0x97d2d988,
+	0x09b64c2b,
+	0x7eb17cbd,
+	0xe7b82d07,
+	0x90bf1d91,
+	0x1db71064,
+	0x6ab020f2,
+	0xf3b97148,
+	0x84be41de,
+	0x1adad47d,
+	0x6ddde4eb,
+	0xf4d4b551,
+	0x83d385c7,
+	0x136c9856,
+	0x646ba8c0,
+	0xfd62f97a,
+	0x8a65c9ec,
+	0x14015c4f,
+	0x63066cd9,
+	0xfa0f3d63,
+	0x8d080df5,
+	0x3b6e20c8,
+	0x4c69105e,
+	0xd56041e4,
+	0xa2677172,
+	0x3c03e4d1,
+	0x4b04d447,
+	0xd20d85fd,
+	0xa50ab56b,
+	0x35b5a8fa,
+	0x42b2986c,
+	0xdbbbc9d6,
+	0xacbcf940,
+	0x32d86ce3,
+	0x45df5c75,
+	0xdcd60dcf,
+	0xabd13d59,
+	0x26d930ac,
+	0x51de003a,
+	0xc8d75180,
+	0xbfd06116,
+	0x21b4f4b5,
+	0x56b3c423,
+	0xcfba9599,
+	0xb8bda50f,
+	0x2802b89e,
+	0x5f058808,
+	0xc60cd9b2,
+	0xb10be924,
+	0x2f6f7c87,
+	0x58684c11,
+	0xc1611dab,
+	0xb6662d3d,
+	0x76dc4190,
+	0x01db7106,
+	0x98d220bc,
+	0xefd5102a,
+	0x71b18589,
+	0x06b6b51f,
+	0x9fbfe4a5,
+	0xe8b8d433,
+	0x7807c9a2,
+	0x0f00f934,
+	0x9609a88e,
+	0xe10e9818,
+	0x7f6a0dbb,
+	0x086d3d2d,
+	0x91646c97,
+	0xe6635c01,
+	0x6b6b51f4,
+	0x1c6c6162,
+	0x856530d8,
+	0xf262004e,
+	0x6c0695ed,
+	0x1b01a57b,
+	0x8208f4c1,
+	0xf50fc457,
+	0x65b0d9c6,
+	0x12b7e950,
+	0x8bbeb8ea,
+	0xfcb9887c,
+	0x62dd1ddf,
+	0x15da2d49,
+	0x8cd37cf3,
+	0xfbd44c65,
+	0x4db26158,
+	0x3ab551ce,
+	0xa3bc0074,
+	0xd4bb30e2,
+	0x4adfa541,
+	0x3dd895d7,
+	0xa4d1c46d,
+	0xd3d6f4fb,
+	0x4369e96a,
+	0x346ed9fc,
+	0xad678846,
+	0xda60b8d0,
+	0x44042d73,
+	0x33031de5,
+	0xaa0a4c5f,
+	0xdd0d7cc9,
+	0x5005713c,
+	0x270241aa,
+	0xbe0b1010,
+	0xc90c2086,
+	0x5768b525,
+	0x206f85b3,
+	0xb966d409,
+	0xce61e49f,
+	0x5edef90e,
+	0x29d9c998,
+	0xb0d09822,
+	0xc7d7a8b4,
+	0x59b33d17,
+	0x2eb40d81,
+	0xb7bd5c3b,
+	0xc0ba6cad,
+	0xedb88320,
+	0x9abfb3b6,
+	0x03b6e20c,
+	0x74b1d29a,
+	0xead54739,
+	0x9dd277af,
+	0x04db2615,
+	0x73dc1683,
+	0xe3630b12,
+	0x94643b84,
+	0x0d6d6a3e,
+	0x7a6a5aa8,
+	0xe40ecf0b,
+	0x9309ff9d,
+	0x0a00ae27,
+	0x7d079eb1,
+	0xf00f9344,
+	0x8708a3d2,
+	0x1e01f268,
+	0x6906c2fe,
+	0xf762575d,
+	0x806567cb,
+	0x196c3671,
+	0x6e6b06e7,
+	0xfed41b76,
+	0x89d32be0,
+	0x10da7a5a,
+	0x67dd4acc,
+	0xf9b9df6f,
+	0x8ebeeff9,
+	0x17b7be43,
+	0x60b08ed5,
+	0xd6d6a3e8,
+	0xa1d1937e,
+	0x38d8c2c4,
+	0x4fdff252,
+	0xd1bb67f1,
+	0xa6bc5767,
+	0x3fb506dd,
+	0x48b2364b,
+	0xd80d2bda,
+	0xaf0a1b4c,
+	0x36034af6,
+	0x41047a60,
+	0xdf60efc3,
+	0xa867df55,
+	0x316e8eef,
+	0x4669be79,
+	0xcb61b38c,
+	0xbc66831a,
+	0x256fd2a0,
+	0x5268e236,
+	0xcc0c7795,
+	0xbb0b4703,
+	0x220216b9,
+	0x5505262f,
+	0xc5ba3bbe,
+	0xb2bd0b28,
+	0x2bb45a92,
+	0x5cb36a04,
+	0xc2d7ffa7,
+	0xb5d0cf31,
+	0x2cd99e8b,
+	0x5bdeae1d,
+	0x9b64c2b0,
+	0xec63f226,
+	0x756aa39c,
+	0x026d930a,
+	0x9c0906a9,
+	0xeb0e363f,
+	0x72076785,
+	0x05005713,
+	0x95bf4a82,
+	0xe2b87a14,
+	0x7bb12bae,
+	0x0cb61b38,
+	0x92d28e9b,
+	0xe5d5be0d,
+	0x7cdcefb7,
+	0x0bdbdf21,
+	0x86d3d2d4,
+	0xf1d4e242,
+	0x68ddb3f8,
+	0x1fda836e,
+	0x81be16cd,
+	0xf6b9265b,
+	0x6fb077e1,
+	0x18b74777,
+	0x88085ae6,
+	0xff0f6a70,
+	0x66063bca,
+	0x11010b5c,
+	0x8f659eff,
+	0xf862ae69,
+	0x616bffd3,
+	0x166ccf45,
+	0xa00ae278,
+	0xd70dd2ee,
+	0x4e048354,
+	0x3903b3c2,
+	0xa7672661,
+	0xd06016f7,
+	0x4969474d,
+	0x3e6e77db,
+	0xaed16a4a,
+	0xd9d65adc,
+	0x40df0b66,
+	0x37d83bf0,
+	0xa9bcae53,
+	0xdebb9ec5,
+	0x47b2cf7f,
+	0x30b5ffe9,
+	0xbdbdf21c,
+	0xcabac28a,
+	0x53b39330,
+	0x24b4a3a6,
+	0xbad03605,
+	0xcdd70693,
+	0x54de5729,
+	0x23d967bf,
+	0xb3667a2e,
+	0xc4614ab8,
+	0x5d681b02,
+	0x2a6f2b94,
+	0xb40bbe37,
+	0xc30c8ea1,
+	0x5a05df1b,
+	0x2d02ef8d
+};
+
+/* CRC calculation */
+#define GET_MAC_ADDR_CRC(addr, crc)				\
+{								\
+	uint32_t i;						\
+	uint8_t  data;						\
+	crc = 0xffffffff;					\
+	for (i = 0; i < 6; i++) {				\
+		data = (uint8_t)(addr >> ((5 - i) * 8));	\
+		crc = crc ^ data;				\
+		crc = crc_table[crc & 0xff] ^ (crc >> 8);	\
+	}							\
+}								\
+
+/*    Define a macro for getting the mirrored value of      */
+/*    a byte size number. (0x11010011 --> 0x11001011)       */
+/*    Sometimes the mirrored value of the CRC is required   */
+static inline uint8_t swab(uint8_t n)
+{
+	uint8_t mirror[16] = {
+		0x00,
+		0x08,
+		0x04,
+		0x0c,
+		0x02,
+		0x0a,
+		0x06,
+		0x0e,
+		0x01,
+		0x09,
+		0x05,
+		0x0d,
+		0x03,
+		0x0b,
+		0x07,
+		0x0f
+	};
+	return ((uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4]))));
+}
+
+#define MIRROR      bitrev
+#define MIRROR_32   bitrev32
+
+#endif /* __crc_mac_addr_ext_h */
diff --git a/drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h b/drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h
new file mode 100644
index 0000000..4d4b211
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h
@@ -0,0 +1,452 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* File          fm_mac_ext.h
+ * Description   FM MAC ...
+ */
+#ifndef __FM_MAC_EXT_H
+#define __FM_MAC_EXT_H
+
+#include "service.h"
+#include "enet_ext.h"
+#include "dpaa_integration_ext.h"
+
+struct fm_mac_dev;
+
+/* Description   FM MAC API functions, definitions and enums */
+
+#define FM_MAC_NO_PFC   0xff
+
+/* FM MAC Exceptions */
+enum fm_mac_exceptions {
+	FM_MAC_EX_10G_MDIO_SCAN_EVENT = 0
+	/* 10GEC MDIO scan event interrupt */
+	, FM_MAC_EX_10G_MDIO_CMD_CMPL
+	/* 10GEC MDIO command completion interrupt */
+	, FM_MAC_EX_10G_REM_FAULT
+	/* 10GEC, mEMAC Remote fault interrupt */
+	, FM_MAC_EX_10G_LOC_FAULT
+	/* 10GEC, mEMAC Local fault interrupt */
+	, FM_MAC_EX_10G_1TX_ECC_ER
+	/* 10GEC, mEMAC Transmit frame ECC error interrupt */
+	, FM_MAC_EX_10G_TX_FIFO_UNFL
+	/* 10GEC, mEMAC Transmit FIFO underflow interrupt */
+	, FM_MAC_EX_10G_TX_FIFO_OVFL
+	/* 10GEC, mEMAC Transmit FIFO overflow interrupt */
+	, FM_MAC_EX_10G_TX_ER
+	/* 10GEC Transmit frame error interrupt */
+	, FM_MAC_EX_10G_RX_FIFO_OVFL
+	/* 10GEC, mEMAC Receive FIFO overflow interrupt */
+	, FM_MAC_EX_10G_RX_ECC_ER
+	/* 10GEC, mEMAC Receive frame ECC error interrupt */
+	, FM_MAC_EX_10G_RX_JAB_FRM
+	/* 10GEC Receive jabber frame interrupt */
+	, FM_MAC_EX_10G_RX_OVRSZ_FRM
+	/* 10GEC Receive oversized frame interrupt */
+	, FM_MAC_EX_10G_RX_RUNT_FRM
+	/* 10GEC Receive runt frame interrupt */
+	, FM_MAC_EX_10G_RX_FRAG_FRM
+	/* 10GEC Receive fragment frame interrupt */
+	, FM_MAC_EX_10G_RX_LEN_ER
+	/* 10GEC Receive payload length error interrupt */
+	, FM_MAC_EX_10G_RX_CRC_ER
+	/* 10GEC Receive CRC error interrupt */
+	, FM_MAC_EX_10G_RX_ALIGN_ER
+	/* 10GEC Receive alignment error interrupt */
+	, FM_MAC_EX_1G_BAB_RX
+	/* dTSEC Babbling receive error */
+	, FM_MAC_EX_1G_RX_CTL
+	/* dTSEC Receive control (pause frame) interrupt */
+	, FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET
+	/* dTSEC Graceful transmit stop complete */
+	, FM_MAC_EX_1G_BAB_TX
+	/* dTSEC Babbling transmit error */
+	, FM_MAC_EX_1G_TX_CTL
+	/* dTSEC Transmit control (pause frame) interrupt */
+	, FM_MAC_EX_1G_TX_ERR
+	/* dTSEC Transmit error */
+	, FM_MAC_EX_1G_LATE_COL
+	/* dTSEC Late collision */
+	, FM_MAC_EX_1G_COL_RET_LMT
+	/* dTSEC Collision retry limit */
+	, FM_MAC_EX_1G_TX_FIFO_UNDRN
+	/* dTSEC Transmit FIFO underrun */
+	, FM_MAC_EX_1G_MAG_PCKT
+	/* dTSEC Magic Packet detection */
+	, FM_MAC_EX_1G_MII_MNG_RD_COMPLET
+	/* dTSEC MII management read completion */
+	, FM_MAC_EX_1G_MII_MNG_WR_COMPLET
+	/* dTSEC MII management write completion */
+	, FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET
+	/* dTSEC Graceful receive stop complete */
+	, FM_MAC_EX_1G_DATA_ERR
+	/* dTSEC Internal data error on transmit */
+	, FM_MAC_1G_RX_DATA_ERR
+	/* dTSEC Internal data error on receive */
+	, FM_MAC_EX_1G_1588_TS_RX_ERR
+	/* dTSEC Time-Stamp Receive Error */
+	, FM_MAC_EX_1G_RX_MIB_CNT_OVFL
+	/* dTSEC MIB counter overflow */
+	, FM_MAC_EX_TS_FIFO_ECC_ERR
+	/* mEMAC Time-stamp FIFO ECC error interrupt;
+	 * not supported on T4240/B4860 rev1 chips
+	 */
+	, FM_MAC_EX_MAGIC_PACKET_INDICATION = FM_MAC_EX_1G_MAG_PCKT
+	/* mEMAC Magic Packet Indication Interrupt */
+};
+
+/* Function      fm_mac_exception_cb
+ * Description   Fm Mac Exception Callback from FM MAC to the user
+ *  Param[in]     h_app             - Handle to the upper layer handler
+ *  Param[in]     exceptions        - The exception that occurred
+ *  Return        void.
+ */
+typedef void (fm_mac_exception_cb) (void *h_app,
+				    enum fm_mac_exceptions exceptions);
+
+/* FM MAC Initialization Unit */
+
+/* FM MAC config input */
+struct fm_mac_params_t {
+	/* Base of memory mapped FM MAC registers */
+	uintptr_t base_addr;
+	/* MAC address of device; First octet is sent first */
+	enet_addr_t addr;
+	/* MAC ID; numbering of dTSEC and 1G-mEMAC:
+	 * 0 - FM_MAX_NUM_OF_1G_MACS;
+	 * numbering of 10G-MAC (TGEC) and 10G-mEMAC:
+	 * 0 - FM_MAX_NUM_OF_10G_MACS
+	 */
+	uint8_t mac_id;
+	/* Ethernet operation mode (MAC-PHY interface and speed);
+	 * Note that the speed should indicate the maximum rate that
+	 * this MAC should support rather than the actual speed;
+	 * i.e. user should use the FM_MAC_AdjustLink() routine to
+	 * provide accurate speed;
+	 * In case of mEMAC RGMII mode, the MAC is configured to RGMII
+	 * automatic mode, where actual speed/duplex mode information
+	 * is provided by PHY automatically in-band; FM_MAC_AdjustLink()
+	 * function should be used to switch to manual RGMII speed/duplex mode
+	 * configuration if RGMII PHY doesn't support in-band status signaling;
+	 * In addition, in mEMAC, in case where user is using the higher MACs
+	 * (i.e. the MACs that should support 10G), user should pass here
+	 * speed=10000 even if the interface is not allowing that (e.g. SGMII).
+	 */
+	enum e_enet_mode enet_mode;
+	/* A handle to the FM object this port related to */
+	void *h_fm;
+	/* MDIO exceptions interrupt source - not valid for all
+	 * MACs; MUST be set to 'NO_IRQ' for MACs that don't have
+	 * mdio-irq, or for polling
+	 */
+	int mdio_irq;
+	fm_mac_exception_cb *f_event;	    /* MDIO Events Callback Routine */
+	fm_mac_exception_cb *f_exception;  /* Exception Callback Routine */
+	void *h_app;	/* A handle to an application layer object;
+			 * This handle will be passed by the driver
+			 * upon calling the above callbacks
+			 */
+};
+
+struct fm_mac_dev;
+
+/* Function	fm_mac_config
+ * Description	  Creates descriptor for the FM MAC module.
+ *		  The routine returns a pointer to the FM MAC object.
+ *		  This pointer must be passed as first parameter to all other
+ *		  FM MAC function calls.
+ *		  No actual initialization or configuration of FM MAC hardware
+ *		  is done by this routine.
+ * Param[in]	  p_fm_mac_param - Pointer to data structure of parameters
+ * Retval	  Pointer to FM MAC object, or NULL for Failure.
+ */
+struct fm_mac_dev *fm_mac_config(struct fm_mac_params_t *p_fm_mac_param);
+
+/* Function	fm_mac_init
+ * Description	  Initializes the FM MAC module
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Return	  0 on success; Error code otherwise.
+ */
+int fm_mac_init(struct fm_mac_dev *fm_mac_dev);
+
+/* Function	fm_free
+ * Description	  Frees all resources that were assigned to FM MAC module.
+ *		  Calling this routine invalidates the descriptor.
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Return	  0 on success; Error code otherwise.
+ */
+int fm_mac_free(struct fm_mac_dev *fm_mac_dev);
+
+/* Description   Configuration functions used to change default values. */
+
+/* Function	fm_mac_cfg_reset_on_init
+ * Description	  Tell the driver whether to reset the FM MAC before
+ *		  initialization or not. It changes the default configuration
+ *		  [DEFAULT_RESET_ON_INIT].
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  enable - When true, FM will be reset before initialization.
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_config() and before
+ *		  fm_mac_init().
+ */
+int fm_mac_cfg_reset_on_init(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function	fm_mac_cfg_max_frame_len
+ * Description	  Setup maximum Rx Frame Length (in 1G MAC, effects also Tx)
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  new_val - MAX Frame length
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_config() and before
+ *		  fm_mac_init().
+ */
+int fm_mac_cfg_max_frame_len(struct fm_mac_dev *fm_mac_dev, uint16_t new_val);
+
+/* Function	fm_mac_cfg_pad_and_crc
+ * Description	  Config PAD and CRC mode
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  enable - true to enable or false to disable.
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_config() and before
+ *		  fm_mac_init().
+ *		  Not supported on 10G-MAC (i.e. CRC&PAD are added
+ *		  automatically by HW); on mEMAC, this routine supports only
+ *		  PAD (i.e. CRC is added automatically by HW).
+ */
+int fm_mac_cfg_pad_and_crc(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function	fm_mac_cfg_tbi_phy_addr
+ * Description	  Configures the address of internal TBI PHY.
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  new_val - TBI PHY address (1-31).
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_config() and before
+ *		  fm_mac_init().
+ */
+int fm_mac_cfg_tbi_phy_addr(struct fm_mac_dev *fm_mac_dev, uint8_t new_val);
+
+/* Function	fm_mac_cfg_len_check
+ * Description	  Configure the frame length checking.
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  enable - true to enable or false to disable.
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_config() and before
+ *		  fm_mac_init().
+ */
+int fm_mac_cfg_len_check(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function	fm_mac_cfg_exception
+ * Description	  Change Exception selection from default
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  ex - Type of the desired exceptions
+ * Param[in]	  enable - true to enable the specified exception,
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_config() and before
+ *		  fm_mac_init().
+ */
+int fm_mac_cfg_exception(struct fm_mac_dev *fm_mac_dev,
+			 enum fm_mac_exceptions ex,
+			 bool enable);
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_mac_cfg_skip_fman11_wa(struct fm_mac_dev *fm_mac_dev);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* FM MAC Runtime control unit API functions, definitions and enums. */
+
+/* Function	fm_mac_enable
+ * Description	  Enable the MAC
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  mode - Mode of operation (RX, TX, Both)
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_init().
+ */
+int fm_mac_enable(struct fm_mac_dev*, enum comm_mode mode);
+
+/* Function	fm_mac_disable
+ * Description	  Disavle the MAC
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  mode - Mode of operation (RX, TX, Both)
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_init().
+ */
+int fm_mac_disable(struct fm_mac_dev *fm_mac_dev, enum comm_mode mode);
+
+#define FSL_FM_PAUSE_TIME_ENABLE	0xf000
+#define FSL_FM_PAUSE_TIME_DISABLE	0
+#define FSL_FM_PAUSE_THRESH_DEFAULT	0
+
+/* Function	fm_mac_set_tx_pause_frames
+ * Description	  Enable/Disable transmission of Pause-Frames.
+ *		  The routine changes the default configuration:
+ *		  pause-time - [DEFAULT_TX_PAUSE_TIME]
+ *		  threshold-time - [0]
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  priority - the PFC class of service; use 'FM_MAC_NO_PFC'
+ *		  to indicate legacy pause support (i.e. no PFC).
+ * Param[in]	  pause_time - Pause quanta value used with transmitted pause
+ *		  frames. Each quanta represents a 512 bit-times;
+ *		  Note that '0' as an input here will be used as disabling the
+ *		  transmission of the pause-frames.
+ * Param[in]	  For legacy pause support (i.e. no PFC), thus
+ *		  value should be '0'.
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_init().
+ */
+int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev,
+			       uint8_t priority,
+			       uint16_t pause_time,
+			       uint16_t thresh_time);
+
+/* Function	fm_mac_set_rx_pause_frames
+ * Description	  Enable/Disable rx Pause-Frames.
+ * Param[in]	  fm_mac_dev - A Pointer to MAC object
+ * Param[in]	  en - boolean indicates whether to ignore the incoming pause
+ *		  frames or not.
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_init().
+ */
+int fm_mac_set_rx_pause_frames(struct fm_mac_dev *fm_mac_dev, bool en);
+
+/* Function	fm_mac_set_exception
+ * Description	  Enable/Disable a specific Exception
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  ex - Type of the desired exceptions
+ * Param[in]	  enable - true to enable the specified exception,
+ *		  false to disable it.
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_init().
+ */
+int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev,
+			 enum fm_mac_exceptions ex,
+			 bool enable);
+
+/* Function	fm_mac_modify_mac_addr
+ * Description	  Replace the main MAC Address
+ * Param[in]	  fm_mac_dev - A pointer to MAC object
+ * Param[in]	  p_enet_addr - Ethernet Mac address
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only after fm_mac_init().
+ */
+int fm_mac_modify_mac_addr(struct fm_mac_dev *fm_mac_dev,
+			   enet_addr_t *p_enet_addr);
+
+/* Function	fm_mac_add_hash_mac_addr
+ * Description	  Add an Address to the hash table. This is for filter purpose
+ *		  only.
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  p_enet_addr - Ethernet Mac address
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_init().
+ *		  It is a filter only address.
+ * Cautions	  Some address need to be filterd out in upper FM blocks.
+ */
+int fm_mac_add_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+			     enet_addr_t *p_enet_addr);
+
+/* Function	fm_mac_remove_hash_mac_addr
+ * Description	  Delete an Address to the hash table. This is for filter
+ *		  purpose only.
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  p_enet_addr - Ethernet Mac address
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only following fm_mac_init().
+ */
+int fm_mac_remove_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+				enet_addr_t *p_enet_addr);
+
+/* Function	fm_mac_set_promiscuous
+ * Description	  Enable/Disable MAC Promiscuous mode for ALL mac addresses.
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[in]	  enable -true to enable or false to disable.
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only after fm_mac_init().
+ */
+int fm_mac_set_promiscuous(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function	fm_mac_adjust_link
+ * Description	  Adjusts the Ethernet link with new speed/duplex setup.
+ *		  This routine is relevant for dTSEC and mEMAC.
+ *		  In case of mEMAC, this routine is also used for manual
+ *		  re-configuration of RGMII speed and duplex mode for
+ *		  RGMII PHYs not supporting in-band status information to MAC.
+ * Param[in]	  fm_mac_dev - A pointer to MAC object
+ * Param[in]	  speed - Ethernet speed.
+ *		  false for half-duplex mode.
+ * Return	  0 on success; Error code otherwise.
+ */
+int fm_mac_adjust_link(struct fm_mac_dev *fm_mac_dev, int link,
+		       enum ethernet_speed speed);
+
+/* Function	fm_mac_restart_autoneg
+ * Description	  Restarts the auto-negotiation process.
+ *		  When auto-negotiation process is invoked under traffic the
+ *		  auto-negotiation process between the internal SGMII PHY and
+ *		  the external PHY does not always complete successfully.
+ *		  Calling this function will restart the auto-negotiation
+ *		  process that will end successfully. It is recommended to
+ *		  call this function after issuing auto-negotiation restart
+ *		  command to the Eth Phy.
+ *		  This routine is relevant only for dTSEC.
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Return	  0 on success; Error code otherwise.
+ */
+int fm_mac_restart_autoneg(struct fm_mac_dev *fm_mac_dev);
+
+/* Function	fm_mac_get_max_frame_length
+ * Description	  Return the max frame length value
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[out]	  p_mac_id - MAC ID of device.
+ * Return	  the maximum frame length value
+ * Cautions	  Allowed only after fm_mac_init().
+ */
+uint16_t fm_mac_get_max_frame_length(struct fm_mac_dev *fm_mac_dev);
+
+/* Function	fm_mac_get_id
+ * Description	  Return the MAC ID
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[out]	  p_mac_id - MAC ID of device.
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only after fm_mac_init().
+ */
+int fm_mac_get_id(struct fm_mac_dev *fm_mac_dev, uint32_t *p_mac_id);
+
+/* Function	fm_mac_get_version
+ * Description	  Return Mac HW chip version
+ * Param[in]	  fm_mac_dev - Pointer to MAC object
+ * Param[out]	  p_mac_version -   Mac version as defined by the chip
+ * Return	  0 on success; Error code otherwise.
+ * Cautions	  Allowed only after fm_mac_init().
+ */
+int fm_mac_get_version(struct fm_mac_dev *fm_mac_dev,
+		       uint32_t *p_mac_version);
+
+#endif /* __FM_MAC_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/Makefile b/drivers/net/ethernet/freescale/fman/mac/Makefile
index 80b7048..042a1f7 100644
--- a/drivers/net/ethernet/freescale/fman/mac/Makefile
+++ b/drivers/net/ethernet/freescale/fman/mac/Makefile
@@ -1,5 +1,8 @@
 obj-$(CONFIG_FSL_FMAN_MAC)	+= fsl_fman_mac.o
 
 fsl_fman_mac-objs		:= fman_dtsec.o fman_dtsec_mii_acc.o	\
-				   fman_memac.o fman_tgec.o		\
-				   fman_crc32.o fman_memac_mii_acc.o
+				    dtsec.o dtsec_mii_acc.o		\
+				   fman_memac.o fman_memac_mii_acc.o	\
+				   memac.o memac_mii_acc.o		\
+				   fman_tgec.o tgec.o			\
+				   fman_crc32.o fm_mac.o
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec.c b/drivers/net/ethernet/freescale/fman/mac/dtsec.c
new file mode 100644
index 0000000..e5c830b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec.c
@@ -0,0 +1,1226 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FMan dTSEC driver */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "crc_mac_addr_ext.h"
+
+#include "fm_common.h"
+#include "dtsec.h"
+#include "fsl_fman_dtsec.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/bitrev.h>
+
+/* Internal routines */
+
+static int check_init_parameters(struct dtsec_t *p_dtsec)
+{
+	if (ENET_SPEED_FROM_MODE(p_dtsec->enet_mode) >= ENET_SPEED_10000) {
+		pr_err("1G MAC driver supports 1G or lower speeds\n");
+		return -EDOM;
+	}
+	if (p_dtsec->addr == 0) {
+		pr_err("Ethernet MAC Must have a valid MAC Address\n");
+		return -EDOM;
+	}
+	if ((ENET_SPEED_FROM_MODE(p_dtsec->enet_mode) >= ENET_SPEED_1000) &&
+	    p_dtsec->p_dtsec_drv_param->halfdup_on) {
+		pr_err("Ethernet MAC 1G can't work in half duplex\n");
+		return -EDOM;
+	}
+#ifdef FM_RX_PREAM_4_ERRATA_DTSEC_A001
+	/* fixed for rev3 */
+	if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev <= 6)
+		if (p_dtsec->p_dtsec_drv_param->rx_preamble) {
+			pr_err("preambleRxEn\n");
+			return -ENOSYS;
+	}
+#endif /* FM_RX_PREAM_4_ERRATA_DTSEC_A001 */
+	if (((p_dtsec->p_dtsec_drv_param)->tx_preamble ||
+	     (p_dtsec->p_dtsec_drv_param)->rx_preamble) &&
+	    ((p_dtsec->p_dtsec_drv_param)->preamble_len != 0x7)) {
+		pr_err("Preamble length should be 0x7 bytes\n");
+		return -EDOM;
+	}
+	if ((p_dtsec->p_dtsec_drv_param)->halfdup_on &&
+	    (p_dtsec->p_dtsec_drv_param->tx_time_stamp_en ||
+	     p_dtsec->p_dtsec_drv_param->rx_time_stamp_en)) {
+		pr_err("1588 timeStamp disabled in half duplex mode\n");
+		return -EDOM;
+	}
+	if ((p_dtsec->p_dtsec_drv_param)->rx_flow &&
+	    (p_dtsec->p_dtsec_drv_param)->rx_ctrl_acc) {
+		pr_err("Receive control frame can not be accepted\n");
+		return -ENOSYS;
+	}
+	if ((p_dtsec->p_dtsec_drv_param)->rx_prepend >
+	    MAX_PACKET_ALIGNMENT) {
+		pr_err("packetAlignmentPadding can't be > than %d\n",
+		       MAX_PACKET_ALIGNMENT);
+		return -ENOSYS;
+	}
+	if (((p_dtsec->p_dtsec_drv_param)->non_back_to_back_ipg1 >
+	     MAX_INTER_PACKET_GAP) ||
+	    ((p_dtsec->p_dtsec_drv_param)->non_back_to_back_ipg2 >
+	     MAX_INTER_PACKET_GAP) ||
+	     ((p_dtsec->p_dtsec_drv_param)->back_to_back_ipg >
+	      MAX_INTER_PACKET_GAP)) {
+		pr_err("Inter packet gap can't be greater than %d\n",
+		       MAX_INTER_PACKET_GAP);
+		return -ENOSYS;
+	}
+	if ((p_dtsec->p_dtsec_drv_param)->halfdup_alt_backoff_val >
+	    MAX_INTER_PALTERNATE_BEB) {
+		pr_err("alternateBackoffVal can't be greater than %d\n",
+		       MAX_INTER_PALTERNATE_BEB);
+		return -ENOSYS;
+	}
+	if ((p_dtsec->p_dtsec_drv_param)->halfdup_retransmit >
+	    MAX_RETRANSMISSION) {
+		pr_err("maxRetransmission can't be greater than %d\n",
+		       MAX_RETRANSMISSION);
+		return -ENOSYS;
+	}
+	if ((p_dtsec->p_dtsec_drv_param)->halfdup_coll_window >
+	    MAX_COLLISION_WINDOW) {
+		pr_err("collisionWindow can't be greater than %d\n",
+		       MAX_COLLISION_WINDOW);
+		return -ENOSYS;
+	/*  If Auto negotiation process is disabled, need to */
+	/*  Set up the PHY using the MII Management Interface */
+	}
+	if (p_dtsec->p_dtsec_drv_param->tbipa > MAX_PHYS) {
+		pr_err("PHY address (should be 0-%d)\n", MAX_PHYS);
+		return -ERANGE;
+	}
+	if (!p_dtsec->f_exception) {
+		pr_err("uninitialized f_exception\n");
+		return -EINVAL;
+	}
+	if (!p_dtsec->f_event) {
+		pr_err("uninitialized f_event\n");
+		return -EINVAL;
+	}
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+	if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev != 4 &&
+	    p_dtsec->p_dtsec_drv_param->rx_len_check) {
+		pr_warn("LengthCheck!\n");
+		return -ENOSYS;
+	}
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+
+	return 0;
+}
+
+static int get_exception_flag(enum fm_mac_exceptions exception)
+{
+	uint32_t bit_mask;
+
+	switch (exception) {
+	case FM_MAC_EX_1G_BAB_RX:
+		bit_mask = DTSEC_IMASK_BREN;
+		break;
+	case FM_MAC_EX_1G_RX_CTL:
+		bit_mask = DTSEC_IMASK_RXCEN;
+		break;
+	case FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET:
+		bit_mask = DTSEC_IMASK_GTSCEN;
+		break;
+	case FM_MAC_EX_1G_BAB_TX:
+		bit_mask = DTSEC_IMASK_BTEN;
+		break;
+	case FM_MAC_EX_1G_TX_CTL:
+		bit_mask = DTSEC_IMASK_TXCEN;
+		break;
+	case FM_MAC_EX_1G_TX_ERR:
+		bit_mask = DTSEC_IMASK_TXEEN;
+		break;
+	case FM_MAC_EX_1G_LATE_COL:
+		bit_mask = DTSEC_IMASK_LCEN;
+		break;
+	case FM_MAC_EX_1G_COL_RET_LMT:
+		bit_mask = DTSEC_IMASK_CRLEN;
+		break;
+	case FM_MAC_EX_1G_TX_FIFO_UNDRN:
+		bit_mask = DTSEC_IMASK_XFUNEN;
+		break;
+	case FM_MAC_EX_1G_MAG_PCKT:
+		bit_mask = DTSEC_IMASK_MAGEN;
+		break;
+	case FM_MAC_EX_1G_MII_MNG_RD_COMPLET:
+		bit_mask = DTSEC_IMASK_MMRDEN;
+		break;
+	case FM_MAC_EX_1G_MII_MNG_WR_COMPLET:
+		bit_mask = DTSEC_IMASK_MMWREN;
+		break;
+	case FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET:
+		bit_mask = DTSEC_IMASK_GRSCEN;
+		break;
+	case FM_MAC_EX_1G_DATA_ERR:
+		bit_mask = DTSEC_IMASK_TDPEEN;
+		break;
+	case FM_MAC_EX_1G_RX_MIB_CNT_OVFL:
+		bit_mask = DTSEC_IMASK_MSROEN;
+		break;
+	default:
+		bit_mask = 0;
+		break;
+	}
+
+	return bit_mask;
+}
+
+/* Checks if p_dtsec driver parameters were initialized
+ * returns 0 if success else returns error code
+ */
+static int is_init_done(struct dtsec_cfg *p_dtsec_drv_parameters)
+{
+	if (!p_dtsec_drv_parameters)
+		return 0;
+	return -ENOSYS;
+}
+
+static uint32_t get_mac_addr_hash_code(uint64_t eth_addr)
+{
+	uint32_t crc;
+
+	/* CRC calculation */
+	GET_MAC_ADDR_CRC(eth_addr, crc);
+
+	crc = bitrev32(crc);
+
+	return crc;
+}
+
+static uint16_t dtsec_get_max_frame_length(void *h_dtsec)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return 0;
+
+	return fman_dtsec_get_max_frame_len(p_dtsec->p_mem_map);
+}
+
+static void dtsec_isr(void *h_dtsec)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	uint32_t event;
+	struct dtsec_regs __iomem *p_dtsec_mem_map = p_dtsec->p_mem_map;
+
+	/* do not handle MDIO events */
+	event =
+	    fman_dtsec_get_event(p_dtsec_mem_map,
+				 (uint32_t)(~
+					     (DTSEC_IMASK_MMRDEN |
+					      DTSEC_IMASK_MMWREN)));
+
+	event &= fman_dtsec_get_interrupt_mask(p_dtsec_mem_map);
+
+	fman_dtsec_ack_event(p_dtsec_mem_map, event);
+
+	if (event & DTSEC_IMASK_BREN)
+		p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_BAB_RX);
+	if (event & DTSEC_IMASK_RXCEN)
+		p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_RX_CTL);
+	if (event & DTSEC_IMASK_GTSCEN)
+		p_dtsec->f_exception(p_dtsec->h_app,
+				     FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET);
+	if (event & DTSEC_IMASK_BTEN)
+		p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_BAB_TX);
+	if (event & DTSEC_IMASK_TXCEN)
+		p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_TX_CTL);
+	if (event & DTSEC_IMASK_TXEEN)
+		p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_TX_ERR);
+	if (event & DTSEC_IMASK_LCEN)
+		p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_LATE_COL);
+	if (event & DTSEC_IMASK_CRLEN)
+		p_dtsec->f_exception(p_dtsec->h_app,
+				     FM_MAC_EX_1G_COL_RET_LMT);
+	if (event & DTSEC_IMASK_XFUNEN) {
+#ifdef FM_TX_LOCKUP_ERRATA_DTSEC6
+		if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2) {
+			uint32_t tpkt1, tmp_reg1, tpkt2, tmp_reg2, i;
+			/* a. Write 0x00E0_0C00 to DTSEC_ID */
+			/* This is a read only regidter
+			 */
+
+			/* b. Read and save the value of TPKT */
+			tpkt1 = GET_UINT32(p_dtsec_mem_map->tpkt);
+
+			/* c. Read the register at dTSEC address offset 0x32C */
+			tmp_reg1 =
+			    GET_UINT32(*(uint32_t *)
+				       ((uint8_t *)p_dtsec_mem_map + 0x32c));
+
+			/* d. Compare bits [9:15] to bits [25:31] of the
+			 * register at address offset 0x32C.
+			 */
+			if ((tmp_reg1 & 0x007F0000) !=
+				(tmp_reg1 & 0x0000007F)) {
+				/* If they are not equal, save the value of
+				 * this register and wait for at least
+				 * MAXFRM*16 ns
+				 */
+				usleep_range((uint32_t)(min
+					(dtsec_get_max_frame_length(p_dtsec) *
+					16 / 1000, 1)), (uint32_t)
+					(min(dtsec_get_max_frame_length
+					(p_dtsec) * 16 / 1000, 1) + 1));
+			}
+
+			/* e. Read and save TPKT again and read the register
+			 * at dTSEC address offset 0x32C again
+			 */
+			tpkt2 = GET_UINT32(p_dtsec_mem_map->tpkt);
+			tmp_reg2 =
+			    GET_UINT32(*(uint32_t __iomem *)
+				       ((uint8_t *)p_dtsec_mem_map + 0x32c));
+
+			/* f. Compare the value of TPKT saved in step b to
+			 * value read in step e. Also compare bits [9:15] of
+			 * the register at offset 0x32C saved in step d to the
+			 * value of bits [9:15] saved in step e. If the two
+			 * registers values are unchanged, then the transmit
+			 * portion of the dTSEC controller is locked up and
+			 * the user should proceed to the recover sequence.
+			 */
+			if ((tpkt1 == tpkt2) && ((tmp_reg1 & 0x007F0000) ==
+				(tmp_reg2 & 0x007F0000))) {
+				/* recover sequence */
+
+				/* a.Write a 1 to RCTRL[GRS] */
+
+				WRITE_UINT32(p_dtsec_mem_map->rctrl,
+					     GET_UINT32(p_dtsec_mem_map->
+							rctrl) | RCTRL_GRS);
+
+				/* b.Wait until IEVENT[GRSC]=1, or at least
+				 * 100 us has elapsed.
+				 */
+				for (i = 0; i < 100; i++) {
+					if (GET_UINT32(p_dtsec_mem_map->
+						       ievent) &
+					    DTSEC_IMASK_GRSCEN)
+						break;
+					udelay(1);
+				}
+				if (GET_UINT32(p_dtsec_mem_map->ievent) &
+				    DTSEC_IMASK_GRSCEN)
+					WRITE_UINT32(p_dtsec_mem_map->ievent,
+						     DTSEC_IMASK_GRSCEN);
+				else
+					pr_debug("Rx lockup due to Tx lockup\n");
+
+				/* c.Write a 1 to bit n of FM_RSTC
+				 * (offset 0x0CC of FPM)
+				 */
+				fm_reset_mac(p_dtsec->fm_mac_ctrl_drv.h_fm,
+					     FM_MAC_1G,
+					     p_dtsec->fm_mac_ctrl_drv.mac_id);
+
+				/* d.Wait 4 Tx clocks (32 ns) */
+				udelay(1);
+
+				/* e.Write a 0 to bit n of FM_RSTC. */
+				/* cleared by FMAN
+				 */
+			}
+		}
+#endif /* FM_TX_LOCKUP_ERRATA_DTSEC6 */
+
+		p_dtsec->f_exception(p_dtsec->h_app,
+				     FM_MAC_EX_1G_TX_FIFO_UNDRN);
+	}
+	if (event & DTSEC_IMASK_MAGEN)
+		p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_MAG_PCKT);
+	if (event & DTSEC_IMASK_GRSCEN)
+		p_dtsec->f_exception(p_dtsec->h_app,
+				     FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET);
+	if (event & DTSEC_IMASK_TDPEEN)
+		p_dtsec->f_exception(p_dtsec->h_app,
+				     FM_MAC_EX_1G_DATA_ERR);
+	if (event & DTSEC_IMASK_RDPEEN)
+		p_dtsec->f_exception(p_dtsec->h_app,
+				     FM_MAC_1G_RX_DATA_ERR);
+
+	/*  - masked interrupts */
+	ASSERT(!(event & DTSEC_IMASK_ABRTEN));
+	ASSERT(!(event & DTSEC_IMASK_IFERREN));
+}
+
+static void dtsec_1588_isr(void *h_dtsec)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	uint32_t event;
+	struct dtsec_regs __iomem *p_dtsec_mem_map = p_dtsec->p_mem_map;
+
+	if (p_dtsec->ptp_tsu_enabled) {
+		event = fman_dtsec_check_and_clear_tmr_event(p_dtsec_mem_map);
+
+		if (event) {
+			ASSERT(event & TMR_PEVENT_TSRE);
+			p_dtsec->f_exception(p_dtsec->h_app,
+					     FM_MAC_EX_1G_1588_TS_RX_ERR);
+		}
+	}
+}
+
+static void free_init_resources(struct dtsec_t *p_dtsec)
+{
+	fm_unregister_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+			   FM_MOD_MAC, p_dtsec->mac_id, FM_INTR_TYPE_ERR);
+	fm_unregister_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+			   FM_MOD_MAC, p_dtsec->mac_id,
+			   FM_INTR_TYPE_NORMAL);
+
+	/* release the driver's group hash table */
+	free_hash_table(p_dtsec->p_multicast_addr_hash);
+	p_dtsec->p_multicast_addr_hash = NULL;
+
+	/* release the driver's individual hash table */
+	free_hash_table(p_dtsec->p_unicast_addr_hash);
+	p_dtsec->p_unicast_addr_hash = NULL;
+}
+
+static int graceful_stop(struct dtsec_t *p_dtsec, enum comm_mode mode)
+{
+	struct dtsec_regs __iomem *p_mem_map;
+
+	p_mem_map = p_dtsec->p_mem_map;
+
+	/* Assert the graceful transmit stop bit */
+	if (mode & COMM_MODE_RX) {
+		fman_dtsec_stop_rx(p_mem_map);
+
+#ifdef FM_GRS_ERRATA_DTSEC_A002
+		if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+			usleep_range(100, 101);
+#else				/* FM_GRS_ERRATA_DTSEC_A002 */
+#ifdef FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839
+		usleep_range(10, 11);
+#endif /* FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 */
+#endif /* FM_GRS_ERRATA_DTSEC_A002 */
+	}
+
+	if (mode & COMM_MODE_TX) {
+#if defined(FM_GTS_ERRATA_DTSEC_A004) || \
+defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012)
+		if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+			pr_debug("GTS not supported due to DTSEC_A004 errata.\n");
+#else				/* not defined(FM_GTS_ERRATA_DTSEC_A004) ||..*/
+#ifdef FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014
+		if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev != 4)
+			pr_debug("GTS not supported due to DTSEC_A0014 errata.\n");
+#else				/* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
+		fman_dtsec_stop_tx(p_mem_map);
+#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
+#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) ||...  */
+	}
+	return 0;
+}
+
+static int graceful_restart(struct dtsec_t *p_dtsec, enum comm_mode mode)
+{
+	struct dtsec_regs __iomem *p_mem_map;
+
+	p_mem_map = p_dtsec->p_mem_map;
+	/* clear the graceful receive stop bit */
+	if (mode & COMM_MODE_TX)
+		fman_dtsec_start_tx(p_mem_map);
+
+	if (mode & COMM_MODE_RX)
+		fman_dtsec_start_rx(p_mem_map);
+
+	return 0;
+}
+
+/* dTSEC Configs modification functions */
+
+static int dtsec_cfg_lb(void *h_dtsec, bool new_val)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_dtsec->p_dtsec_drv_param->loopback = new_val;
+
+	return 0;
+}
+
+static int dtsec_cfg_max_frame_len(void *h_dtsec, uint16_t new_val)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_dtsec->p_dtsec_drv_param->maximum_frame = new_val;
+
+	return 0;
+}
+
+static int dtsec_cfg_pad_and_crc(void *h_dtsec, bool new_val)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_dtsec->p_dtsec_drv_param->tx_pad_crc = new_val;
+
+	return 0;
+}
+
+static int dtsec_cfg_tbi_phy_addr(void *h_dtsec, uint8_t new_val)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_dtsec->p_dtsec_drv_param->tbi_phy_addr = new_val;
+
+	return 0;
+}
+
+static int dtsec_cfg_len_check(void *h_dtsec, bool new_val)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_dtsec->p_dtsec_drv_param->rx_len_check = new_val;
+
+	return 0;
+}
+
+static int dtsec_cfg_exception(void *h_dtsec, enum fm_mac_exceptions
+			       exception, bool enable)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	uint32_t bit_mask = 0;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) {
+		bit_mask = get_exception_flag(exception);
+		if (bit_mask) {
+			if (enable)
+				p_dtsec->exceptions |= bit_mask;
+			else
+				p_dtsec->exceptions &= ~bit_mask;
+		} else {
+			pr_err("Undefined exception\n");
+			return -EDOM;
+		}
+	} else {
+		if (!p_dtsec->ptp_tsu_enabled) {
+			pr_err("Exception valid for 1588 only\n");
+			return -EDOM;
+		}
+		switch (exception) {
+		case (FM_MAC_EX_1G_1588_TS_RX_ERR):
+			if (enable)
+				p_dtsec->en_tsu_err_exeption = true;
+			else
+				p_dtsec->en_tsu_err_exeption = false;
+			break;
+		default:
+			pr_err("Undefined exception\n");
+			return -EDOM;
+		}
+	}
+	return 0;
+}
+
+/* dTSEC Run Time API functions  */
+
+static int dtsec_enable(void *h_dtsec, enum comm_mode mode)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	fman_dtsec_enable(p_dtsec->p_mem_map,
+			  (bool)!!(mode & COMM_MODE_RX),
+			  (bool)!!(mode & COMM_MODE_TX));
+
+	graceful_restart(p_dtsec, mode);
+
+	return 0;
+}
+
+static int dtsec_disable(void *h_dtsec, enum comm_mode mode)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	graceful_stop(p_dtsec, mode);
+
+	fman_dtsec_disable(p_dtsec->p_mem_map,
+			   (bool)!!(mode & COMM_MODE_RX),
+			   (bool)!!(mode & COMM_MODE_TX));
+
+	return 0;
+}
+
+static int dtsec_set_tx_pause_frames(void *h_dtsec,
+				     uint8_t __maybe_unused priority,
+				     uint16_t pause_time,
+				     uint16_t __maybe_unused thresh_time)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+#ifdef FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003
+	if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+		if (0 < pause_time && pause_time <= 320) {
+			pr_warn("pause-time:%d illegal.Should be >320\n",
+				pause_time);
+			return -EDOM;
+		}
+#endif /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 */
+
+	fman_dtsec_set_tx_pause_frames(p_dtsec->p_mem_map, pause_time);
+	return 0;
+}
+
+/* backward compatibility. will be removed in the future. */
+static int dtsec_tx_mac_pause(void *h_dtsec, uint16_t pause_time)
+{
+	return dtsec_set_tx_pause_frames(h_dtsec, 0, pause_time, 0);
+}
+
+static int dtsec_rx_ignore_mac_pause(void *h_dtsec, bool en)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+	bool accept_pause = !en;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	fman_dtsec_handle_rx_pause(p_dtsec->p_mem_map, accept_pause);
+
+	return 0;
+}
+
+static int dtsec_modify_mac_address(void *h_dtsec, enet_addr_t
+					*p_enet_addr)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	/* Initialize MAC Station Address registers (1&2)    */
+	/* Station address have to be swapped (big endian to little endian */
+	p_dtsec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr);
+	fman_dtsec_set_mac_address(p_dtsec->p_mem_map,
+				   (uint8_t *)(*p_enet_addr));
+
+	return 0;
+}
+
+static int dtsec_add_hash_mac_address(void *h_dtsec,
+				      enet_addr_t *p_eth_addr)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	struct eth_hash_entry_t *p_hash_entry;
+	uint64_t eth_addr;
+	int32_t bucket;
+	uint32_t crc;
+	bool mcast, ghtx;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+	ghtx = (bool)((fman_dtsec_get_rctrl(p_dtsec->p_mem_map) &
+			RCTRL_GHTX) ? true : false);
+	mcast = (bool)((eth_addr & MAC_GROUP_ADDRESS) ? true : false);
+
+	/* Cannot handle unicast mac addr when GHTX is on */
+	if (ghtx && !mcast) {
+		pr_err("Could not compute hash bucket\n");
+		return -ENOSYS;
+	}
+	crc = get_mac_addr_hash_code(eth_addr);
+
+	/* considering the 9 highest order bits in crc H[8:0]:
+	 *if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register
+	 *and H[5:1] (next 5 bits) identify the hash bit
+	 *if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register
+	 *and H[4:0] (next 5 bits) identify the hash bit.
+	 *
+	 *In bucket index output the low 5 bits identify the hash register
+	 *bit, while the higher 4 bits identify the hash register
+	 */
+
+	if (ghtx) {
+		bucket = (int32_t)((crc >> 23) & 0x1ff);
+	} else {
+		bucket = (int32_t)((crc >> 24) & 0xff);
+		/* if !ghtx and mcast the bit must be set in gaddr instead of
+		 *igaddr.
+		 */
+		if (mcast)
+			bucket += 0x100;
+	}
+
+	fman_dtsec_set_bucket(p_dtsec->p_mem_map, bucket, true);
+
+	/* Create element to be added to the driver hash table */
+	p_hash_entry = kmalloc(sizeof(*p_hash_entry), GFP_KERNEL);
+	if (!p_hash_entry)
+		return -ENOMEM;
+	p_hash_entry->addr = eth_addr;
+	INIT_LIST_HEAD(&p_hash_entry->node);
+
+	if (eth_addr & MAC_GROUP_ADDRESS)
+		/* Group Address */
+		list_add_tail(&p_hash_entry->node,
+			      &(p_dtsec->p_multicast_addr_hash->p_lsts[bucket]
+			       ));
+	else
+		list_add_tail(&p_hash_entry->node,
+			      &p_dtsec->p_unicast_addr_hash->p_lsts[bucket]);
+
+	return 0;
+}
+
+static int dtsec_del_hash_mac_address(void *h_dtsec, enet_addr_t
+					  *p_eth_addr)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	struct list_head *p_pos;
+	struct eth_hash_entry_t *p_hash_entry = NULL;
+	uint64_t eth_addr;
+	int32_t bucket;
+	uint32_t crc;
+	bool mcast, ghtx;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+	ghtx =
+	    (bool)((fman_dtsec_get_rctrl(p_dtsec->p_mem_map) & RCTRL_GHTX) ?
+		    true : false);
+	mcast = (bool)((eth_addr & MAC_GROUP_ADDRESS) ? true : false);
+
+	/* Cannot handle unicast mac addr when GHTX is on */
+	if (ghtx && !mcast) {
+		pr_err("Could not compute hash bucket\n");
+		return -ENOSYS;
+	}
+	crc = get_mac_addr_hash_code(eth_addr);
+
+	if (ghtx) {
+		bucket = (int32_t)((crc >> 23) & 0x1ff);
+	} else {
+		bucket = (int32_t)((crc >> 24) & 0xff);
+		/* if !ghtx and mcast the bit must be set
+		 * in gaddr instead of igaddr.
+		 */
+		if (mcast)
+			bucket += 0x100;
+	}
+
+	if (eth_addr & MAC_GROUP_ADDRESS) {
+		/* Group Address */
+		list_for_each(p_pos,
+			      &(p_dtsec->p_multicast_addr_hash->
+				p_lsts[bucket])) {
+			p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+			if (p_hash_entry->addr == eth_addr) {
+				list_del_init(&p_hash_entry->node);
+				kfree(p_hash_entry);
+				break;
+			}
+		}
+		if (list_empty(&p_dtsec->p_multicast_addr_hash->p_lsts[bucket]))
+			fman_dtsec_set_bucket(p_dtsec->p_mem_map, bucket,
+					      false);
+	} else {
+		/* Individual Address */
+		list_for_each(p_pos,
+			      &p_dtsec->p_unicast_addr_hash->p_lsts[bucket]) {
+			p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+			if (p_hash_entry->addr == eth_addr) {
+				list_del_init(&p_hash_entry->node);
+				kfree(p_hash_entry);
+				break;
+			}
+		}
+		if (list_empty(&p_dtsec->p_unicast_addr_hash->p_lsts[bucket]))
+			fman_dtsec_set_bucket(p_dtsec->p_mem_map, bucket,
+					      false);
+	}
+
+	/* address does not exist */
+	ASSERT(p_hash_entry);
+
+	return 0;
+}
+
+static int dtsec_set_promiscuous(void *h_dtsec, bool new_val)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	fman_dtsec_set_uc_promisc(p_dtsec->p_mem_map, new_val);
+	fman_dtsec_set_mc_promisc(p_dtsec->p_mem_map, new_val);
+
+	return 0;
+}
+
+static int dtsec_adjust_link(void *h_dtsec, enum ethernet_speed speed)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int err;
+	enum enet_interface enet_interface;
+	enum enet_speed enet_speed;
+	int ret, full_duplex = true;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	p_dtsec->enet_mode =
+	    MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode), speed);
+	enet_interface =
+	    (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode);
+	enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_dtsec->enet_mode);
+
+	err =
+	    (int)fman_dtsec_adjust_link(p_dtsec->p_mem_map, enet_interface,
+					    enet_speed, full_duplex);
+
+	if (err == -EINVAL) {
+		pr_err("Ethernet doesn't support Half Duplex mode\n");
+		return -EINVAL;
+	}
+
+	return err;
+}
+
+static int dtsec_restart_autoneg(void *h_dtsec)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	uint16_t tmp_reg16;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	dtsec_mii_read_phy_reg(p_dtsec, p_dtsec->tbi_phy_addr, 0, &tmp_reg16);
+
+	tmp_reg16 &= ~(PHY_CR_SPEED0 | PHY_CR_SPEED1);
+	tmp_reg16 |=
+	    (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
+
+	dtsec_mii_write_phy_reg(p_dtsec, p_dtsec->tbi_phy_addr, 0, tmp_reg16);
+
+	return 0;
+}
+
+static int dtsec_get_id(void *h_dtsec, uint32_t *mac_id)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	*mac_id = p_dtsec->mac_id;
+
+	return 0;
+}
+
+static int dtsec_get_version(void *h_dtsec, uint32_t *mac_version)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	*mac_version = fman_dtsec_get_revision(p_dtsec->p_mem_map);
+
+	return 0;
+}
+
+static int dtsec_set_exception(void *h_dtsec,
+			       enum fm_mac_exceptions exception,
+				   bool enable)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	uint32_t bit_mask = 0;
+	int ret;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (ret)
+		return ret;
+
+	if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) {
+		bit_mask = get_exception_flag(exception);
+		if (bit_mask) {
+			if (enable)
+				p_dtsec->exceptions |= bit_mask;
+			else
+				p_dtsec->exceptions &= ~bit_mask;
+		} else {
+			pr_err("Undefined exception\n");
+			return -EDOM;
+		}
+		if (enable)
+			fman_dtsec_enable_interrupt(p_dtsec->p_mem_map,
+						    bit_mask);
+		else
+			fman_dtsec_disable_interrupt(p_dtsec->p_mem_map,
+						     bit_mask);
+	} else {
+		if (!p_dtsec->ptp_tsu_enabled) {
+			pr_err("Exception valid for 1588 only\n");
+			return -EDOM;
+		}
+		switch (exception) {
+		case (FM_MAC_EX_1G_1588_TS_RX_ERR):
+			if (enable) {
+				p_dtsec->en_tsu_err_exeption = true;
+				fman_dtsec_enable_tmr_interrupt(p_dtsec->
+								p_mem_map);
+			} else {
+				p_dtsec->en_tsu_err_exeption = false;
+				fman_dtsec_disable_tmr_interrupt(p_dtsec->
+								 p_mem_map);
+			}
+			break;
+		default:
+			pr_err("Undefined exception\n");
+			return -EDOM;
+		}
+	}
+
+	return 0;
+}
+
+/* dTSEC Init&Free API */
+
+static int dtsec_init(void *h_dtsec)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	struct dtsec_cfg *p_dtsec_drv_param;
+	int err;
+	uint16_t max_frm_ln;
+	enum enet_interface enet_interface;
+	enum enet_speed enet_speed;
+	enet_addr_t eth_addr;
+	int ret, ret_err;
+
+	ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+	if (!ret)
+		return ret;
+
+	fm_get_revision(p_dtsec->fm_mac_ctrl_drv.h_fm,
+			&p_dtsec->fm_mac_ctrl_drv.fm_rev_info);
+	ret_err = check_init_parameters(p_dtsec);
+	if (ret_err)
+		return -ret_err;
+
+	p_dtsec_drv_param = p_dtsec->p_dtsec_drv_param;
+
+	enet_interface =
+	    (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode);
+	enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_dtsec->enet_mode);
+	MAKE_ENET_ADDR_FROM_UINT64(p_dtsec->addr, eth_addr);
+
+	err = (int)fman_dtsec_init(p_dtsec->p_mem_map,
+				       p_dtsec_drv_param,
+				       enet_interface,
+				       enet_speed,
+				       (uint8_t *)eth_addr,
+				       p_dtsec->fm_mac_ctrl_drv.
+				       fm_rev_info.major_rev,
+				       p_dtsec->fm_mac_ctrl_drv.
+				       fm_rev_info.minor_rev,
+				       p_dtsec->exceptions);
+	if (err) {
+		free_init_resources(p_dtsec);
+		pr_err("DTSEC version doesn't support this i/f mode\n");
+		return err;
+	}
+
+	if (ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode) == ENET_IF_SGMII) {
+		uint16_t tmp_reg16;
+
+		/* Configure the TBI PHY Control Register */
+		tmp_reg16 = PHY_TBICON_CLK_SEL | PHY_TBICON_SRESET;
+		dtsec_mii_write_phy_reg(p_dtsec,
+					(uint8_t)p_dtsec_drv_param->tbipa,
+					17, tmp_reg16);
+
+		tmp_reg16 = PHY_TBICON_CLK_SEL;
+		dtsec_mii_write_phy_reg(p_dtsec,
+					(uint8_t)p_dtsec_drv_param->tbipa,
+					17, tmp_reg16);
+
+		tmp_reg16 =
+		    (PHY_CR_PHY_RESET | PHY_CR_ANE | PHY_CR_FULLDUPLEX |
+		     PHY_CR_SPEED1);
+		dtsec_mii_write_phy_reg(p_dtsec,
+					(uint8_t)p_dtsec_drv_param->tbipa,
+					0, tmp_reg16);
+
+		if (p_dtsec->enet_mode & ENET_IF_SGMII_BASEX)
+			tmp_reg16 = PHY_TBIANA_1000X;
+		else
+			tmp_reg16 = PHY_TBIANA_SGMII;
+		dtsec_mii_write_phy_reg(p_dtsec,
+					(uint8_t)p_dtsec_drv_param->tbipa,
+					4, tmp_reg16);
+
+		tmp_reg16 =
+		    (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX |
+		     PHY_CR_SPEED1);
+
+		dtsec_mii_write_phy_reg(p_dtsec,
+					(uint8_t)p_dtsec_drv_param->tbipa,
+					0, tmp_reg16);
+	}
+
+	/* Max Frame Length */
+	max_frm_ln = fman_dtsec_get_max_frame_len(p_dtsec->p_mem_map);
+	err = fm_set_mac_max_frame(p_dtsec->fm_mac_ctrl_drv.h_fm,
+				   FM_MAC_1G,
+				   p_dtsec->fm_mac_ctrl_drv.mac_id,
+				   max_frm_ln);
+	if (err) {
+		pr_err("Setting max frame length FAILED\n");
+		free_init_resources(p_dtsec);
+		return -EINVAL;
+	}
+
+	p_dtsec->p_multicast_addr_hash =
+	alloc_hash_table(EXTENDED_HASH_TABLE_SIZE);
+	if (!p_dtsec->p_multicast_addr_hash) {
+		free_init_resources(p_dtsec);
+		pr_err("MC hash table is FAILED\n");
+		return -ENOMEM;
+	}
+
+	p_dtsec->p_unicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+	if (!p_dtsec->p_unicast_addr_hash) {
+		free_init_resources(p_dtsec);
+		pr_err("UC hash table is FAILED\n");
+		return -ENOMEM;
+	}
+
+	/* register err intr handler for dtsec to FPM (err) */
+	fm_register_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+			 FM_MOD_MAC,
+			 p_dtsec->mac_id,
+			 FM_INTR_TYPE_ERR,
+			 dtsec_isr,
+			 p_dtsec);
+	/* register 1588 intr handler for TMR to FPM (normal) */
+	fm_register_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+			 FM_MOD_MAC,
+			 p_dtsec->mac_id,
+			 FM_INTR_TYPE_NORMAL,
+			 dtsec_1588_isr,
+			 p_dtsec);
+
+	kfree(p_dtsec_drv_param);
+	p_dtsec->p_dtsec_drv_param = NULL;
+
+	return 0;
+}
+
+static int dtsec_free(void *h_dtsec)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+
+	free_init_resources(p_dtsec);
+
+	kfree(p_dtsec->p_dtsec_drv_param);
+	p_dtsec->p_dtsec_drv_param = NULL;
+	kfree(h_dtsec);
+
+	return 0;
+}
+
+static void init_fm_mac_ctrl_drv(struct fm_mac_ctrl_drv_t *
+				      p_fm_mac_ctrl_drv)
+{
+	p_fm_mac_ctrl_drv->f_fm_mac_init = dtsec_init;
+	p_fm_mac_ctrl_drv->f_fm_mac_free = dtsec_free;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_lb = dtsec_cfg_lb;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len =
+	dtsec_cfg_max_frame_len;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc =
+	    dtsec_cfg_pad_and_crc;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check = dtsec_cfg_len_check;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_tbi_phy_addr = dtsec_cfg_tbi_phy_addr;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception = dtsec_cfg_exception;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init = NULL;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_enable = dtsec_enable;
+	p_fm_mac_ctrl_drv->f_fm_mac_disable = dtsec_disable;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_set_exception = dtsec_set_exception;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous = dtsec_set_promiscuous;
+	p_fm_mac_ctrl_drv->f_fm_mac_adjust_link = dtsec_adjust_link;
+	p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg = dtsec_restart_autoneg;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames =
+	    dtsec_tx_mac_pause;
+	p_fm_mac_ctrl_drv->f_fm_mac_set_tx_pause_frames =
+	    dtsec_set_tx_pause_frames;
+	p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames =
+	    dtsec_rx_ignore_mac_pause;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr =
+	dtsec_modify_mac_address;
+	p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr =
+	    dtsec_add_hash_mac_address;
+	p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr =
+	    dtsec_del_hash_mac_address;
+	p_fm_mac_ctrl_drv->f_fm_mac_get_id = dtsec_get_id;
+	p_fm_mac_ctrl_drv->f_fm_mac_get_version = dtsec_get_version;
+	p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length =
+	    dtsec_get_max_frame_length;
+}
+
+/* d_tsec config main entry */
+
+void *dtsec_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+	struct dtsec_t *p_dtsec;
+	struct dtsec_cfg *p_dtsec_drv_param;
+	uintptr_t base_addr;
+
+	base_addr = p_fm_mac_param->base_addr;
+
+	/* allocate memory for the UCC GETH data structure. */
+	p_dtsec = kzalloc(sizeof(*p_dtsec), GFP_KERNEL);
+	if (!p_dtsec)
+		return ERR_PTR(-ENOMEM);
+	init_fm_mac_ctrl_drv(&p_dtsec->fm_mac_ctrl_drv);
+
+	/* allocate memory for the d_tsec driver parameters data structure. */
+	p_dtsec_drv_param = kzalloc(sizeof(*p_dtsec_drv_param),
+				    GFP_KERNEL);
+	if (!p_dtsec_drv_param) {
+		kfree(p_dtsec);
+		pr_err("dTSEC driver parameters");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Plant parameter structure pointer */
+	p_dtsec->p_dtsec_drv_param = p_dtsec_drv_param;
+
+	fman_dtsec_defconfig(p_dtsec_drv_param);
+
+	p_dtsec->p_mem_map = (struct dtsec_regs __iomem *)
+			    UINT_TO_PTR(base_addr);
+	p_dtsec->p_mii_mem_map = (struct dtsec_mii_reg __iomem *)
+	    UINT_TO_PTR(base_addr + DTSEC_TO_MII_OFFSET);
+	p_dtsec->addr = ENET_ADDR_TO_UINT64(p_fm_mac_param->addr);
+	p_dtsec->enet_mode = p_fm_mac_param->enet_mode;
+	p_dtsec->mac_id = p_fm_mac_param->mac_id;
+	p_dtsec->exceptions = DEFAULT_exceptions;
+	p_dtsec->f_exception = p_fm_mac_param->f_exception;
+	p_dtsec->f_event = p_fm_mac_param->f_event;
+	p_dtsec->h_app = p_fm_mac_param->h_app;
+	p_dtsec->ptp_tsu_enabled = p_dtsec->p_dtsec_drv_param->ptp_tsu_en;
+	p_dtsec->en_tsu_err_exeption =
+	    p_dtsec->p_dtsec_drv_param->ptp_exception_en;
+	p_dtsec->tbi_phy_addr = p_dtsec->p_dtsec_drv_param->tbi_phy_addr;
+
+	return p_dtsec;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec.h b/drivers/net/ethernet/freescale/fman/mac/dtsec.h
new file mode 100644
index 0000000..723a7d2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM dTSEC ... */
+#ifndef __DTSEC_H
+#define __DTSEC_
+
+#include "service.h"
+#include "enet_ext.h"
+
+#include "dtsec_mii_acc.h"
+#include "fm_mac.h"
+
+#define DEFAULT_exceptions			\
+((uint32_t)(DTSEC_IMASK_BREN		|	\
+		DTSEC_IMASK_RXCEN	|	\
+		DTSEC_IMASK_BTEN	|	\
+		DTSEC_IMASK_TXCEN	|	\
+		DTSEC_IMASK_TXEEN	|	\
+		DTSEC_IMASK_ABRTEN	|	\
+		DTSEC_IMASK_LCEN	|	\
+		DTSEC_IMASK_CRLEN	|	\
+		DTSEC_IMASK_XFUNEN	|	\
+		DTSEC_IMASK_IFERREN	|	\
+		DTSEC_IMASK_MAGEN	|	\
+		DTSEC_IMASK_TDPEEN	|	\
+		DTSEC_IMASK_RDPEEN))
+
+#define MAX_PACKET_ALIGNMENT        31
+#define MAX_INTER_PACKET_GAP        0x7f
+#define MAX_INTER_PALTERNATE_BEB    0x0f
+#define MAX_RETRANSMISSION          0x0f
+#define MAX_COLLISION_WINDOW        0x03ff
+
+/*number of pattern match registers (entries) */
+#define DTSEC_NUM_OF_PADDRS             15
+
+/* Group address bit indication */
+#define GROUP_ADDRESS                   0x0000010000000000LL
+
+/* Hash table size (32 bits*8 regs) */
+#define HASH_TABLE_SIZE                 256
+/* Extended Hash table size (32 bits*16 regs) */
+#define EXTENDED_HASH_TABLE_SIZE        512
+
+/* number of pattern match registers (entries) */
+#define DTSEC_TO_MII_OFFSET             0x1000
+/* maximum number of phys */
+#define MAX_PHYS                    32
+
+#define     VAL32BIT    0x100000000LL
+#define     VAL22BIT    0x00400000
+#define     VAL16BIT    0x00010000
+#define     VAL12BIT    0x00001000
+
+/* CAR1/2 bits */
+#define CAR1_TR64   0x80000000
+#define CAR1_TR127  0x40000000
+#define CAR1_TR255  0x20000000
+#define CAR1_TR511  0x10000000
+#define CAR1_TRK1   0x08000000
+#define CAR1_TRMAX  0x04000000
+#define CAR1_TRMGV  0x02000000
+
+#define CAR1_RBYT   0x00010000
+#define CAR1_RPKT   0x00008000
+#define CAR1_RMCA   0x00002000
+#define CAR1_RBCA   0x00001000
+#define CAR1_RXPF   0x00000400
+#define CAR1_RALN   0x00000100
+#define CAR1_RFLR   0x00000080
+#define CAR1_RCDE   0x00000040
+#define CAR1_RCSE   0x00000020
+#define CAR1_RUND   0x00000010
+#define CAR1_ROVR   0x00000008
+#define CAR1_RFRG   0x00000004
+#define CAR1_RJBR   0x00000002
+#define CAR1_RDRP   0x00000001
+
+#define CAR2_TFCS   0x00040000
+#define CAR2_TBYT   0x00002000
+#define CAR2_TPKT   0x00001000
+#define CAR2_TMCA   0x00000800
+#define CAR2_TBCA   0x00000400
+#define CAR2_TXPF   0x00000200
+#define CAR2_TDRP   0x00000001
+
+struct internal_statistics_t {
+	uint64_t tr64;
+	uint64_t tr127;
+	uint64_t tr255;
+	uint64_t tr511;
+	uint64_t tr1k;
+	uint64_t trmax;
+	uint64_t trmgv;
+	uint64_t rfrg;
+	uint64_t rjbr;
+	uint64_t rdrp;
+	uint64_t raln;
+	uint64_t rund;
+	uint64_t rovr;
+	uint64_t rxpf;
+	uint64_t txpf;
+	uint64_t rbyt;
+	uint64_t rpkt;
+	uint64_t rmca;
+	uint64_t rbca;
+	uint64_t rflr;
+	uint64_t rcde;
+	uint64_t rcse;
+	uint64_t tbyt;
+	uint64_t tpkt;
+	uint64_t tmca;
+	uint64_t tbca;
+	uint64_t tdrp;
+	uint64_t tfcs;
+};
+
+struct dtsec_t {
+	struct fm_mac_ctrl_drv_t fm_mac_ctrl_drv;
+	/* Handle to the upper layer application              */
+	void *h_app;
+	/* pointer to dTSEC memory mapped registers.          */
+	struct dtsec_regs __iomem *p_mem_map;
+	/* pointer to dTSEC MII memory mapped registers.          */
+	struct dtsec_mii_reg __iomem *p_mii_mem_map;
+	/* MAC address of device;                             */
+	uint64_t addr;
+	/* Ethernet physical interface  */
+	enum e_enet_mode enet_mode;
+	fm_mac_exception_cb *f_exception;
+	fm_mac_exception_cb *f_event;
+	/* Whether a particular individual address recognition
+	 * register is being used
+	 */
+	bool ind_addr_reg_used[DTSEC_NUM_OF_PADDRS];
+	/* MAC address for particular individual
+	 * address recognition register
+	 */
+	uint64_t paddr[DTSEC_NUM_OF_PADDRS];
+	/* Number of individual addresses in registers for this station. */
+	uint8_t num_of_ind_addr_in_regs;
+	struct internal_statistics_t internal_statistics;
+	/* pointer to driver's global address hash table  */
+	struct eth_hash_t *p_multicast_addr_hash;
+	/* pointer to driver's individual address hash table  */
+	struct eth_hash_t *p_unicast_addr_hash;
+	uint8_t mac_id;
+	uint8_t tbi_phy_addr;
+	uint32_t exceptions;
+	bool ptp_tsu_enabled;
+	bool en_tsu_err_exeption;
+	struct dtsec_cfg *p_dtsec_drv_param;
+};
+
+#endif /* __DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c
new file mode 100644
index 0000000..0b2ef14
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM dtsec MII register access MAC ... */
+
+#include "service.h"
+#include "fm_mac.h"
+#include "dtsec.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+int dtsec_mii_write_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+			    uint16_t data)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	struct dtsec_mii_reg __iomem *miiregs;
+	uint16_t dtsec_freq;
+	int err;
+
+	dtsec_freq = (uint16_t)(p_dtsec->fm_mac_ctrl_drv.clk_freq >> 1);
+	miiregs = p_dtsec->p_mii_mem_map;
+
+	err =
+	    (int)fman_dtsec_mii_write_reg(miiregs, phy_addr, reg, data,
+					       dtsec_freq);
+
+	return err;
+}
+
+int dtsec_mii_read_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+			   uint16_t *p_data)
+{
+	struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+	struct dtsec_mii_reg __iomem *miiregs;
+	uint16_t dtsec_freq;
+	int err;
+
+	dtsec_freq = (uint16_t)(p_dtsec->fm_mac_ctrl_drv.clk_freq >> 1);
+	miiregs = p_dtsec->p_mii_mem_map;
+
+	err =
+	    (int)fman_dtsec_mii_read_reg(miiregs, phy_addr, reg, p_data,
+					      dtsec_freq);
+
+	if (*p_data == 0xffff) {
+		pr_warn("Read wrong data(0xffff):phy_addr 0x%x,reg 0x%x",
+			phy_addr, reg);
+		return -ENXIO;
+	}
+	if (err)
+		return err;
+
+	return err;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h
new file mode 100644
index 0000000..e599642
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DTSEC_MII_ACC_H
+#define __DTSEC_MII_ACC_H
+
+#include "service.h"
+
+int dtsec_mii_write_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+			    uint16_t data);
+int dtsec_mii_read_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+			   uint16_t *p_data);
+
+#endif /* __DTSEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/fm_mac.c b/drivers/net/ethernet/freescale/fman/mac/fm_mac.c
new file mode 100644
index 0000000..8048446
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fm_mac.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM MAC ... */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "fm_ext.h"
+
+#include "fm_common.h"
+#include "fm_mac.h"
+
+#include <linux/string.h>
+
+struct fm_mac_dev *fm_mac_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+	struct fm_mac_dev *fm_mac_dev;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv;
+	struct fm_revision_info_t fm_rev_info;
+
+	fm_get_revision(p_fm_mac_param->h_fm, &fm_rev_info);
+
+	if (fm_rev_info.major_rev >= 6) {
+		p_fm_mac_ctrl_drv = (struct fm_mac_ctrl_drv_t *)
+			memac_config(p_fm_mac_param);
+	} else {
+		if (ENET_SPEED_FROM_MODE(p_fm_mac_param->enet_mode) <
+			ENET_SPEED_10000)
+			p_fm_mac_ctrl_drv = (struct fm_mac_ctrl_drv_t *)
+				dtsec_config(p_fm_mac_param);
+		else if (ENET_SPEED_FROM_MODE(p_fm_mac_param->enet_mode) ==
+			ENET_SPEED_10000)
+			p_fm_mac_ctrl_drv = (struct fm_mac_ctrl_drv_t *)
+				tgec_config(p_fm_mac_param);
+		else
+			p_fm_mac_ctrl_drv = NULL;
+	}
+
+	if (!p_fm_mac_ctrl_drv)
+		return NULL;
+
+	p_fm_mac_ctrl_drv->h_fm = p_fm_mac_param->h_fm;
+	p_fm_mac_ctrl_drv->enet_mode = p_fm_mac_param->enet_mode;
+	p_fm_mac_ctrl_drv->mac_id = p_fm_mac_param->mac_id;
+	p_fm_mac_ctrl_drv->reset_on_init = DEFAULT_RESET_ON_INIT;
+	p_fm_mac_ctrl_drv->fm_rev_info.major_rev = fm_rev_info.major_rev;
+	p_fm_mac_ctrl_drv->fm_rev_info.minor_rev = fm_rev_info.minor_rev;
+	p_fm_mac_ctrl_drv->clk_freq =
+		fm_get_clock_freq(p_fm_mac_ctrl_drv->h_fm);
+
+	if (p_fm_mac_ctrl_drv->clk_freq  == 0) {
+		pr_err("Can't get clock for MAC!\n");
+		kfree(p_fm_mac_ctrl_drv);
+		return NULL;
+	}
+
+	fm_mac_dev = (void *)p_fm_mac_ctrl_drv;
+
+	return fm_mac_dev;
+}
+EXPORT_SYMBOL(fm_mac_config);
+
+int fm_mac_init(struct fm_mac_dev *fm_mac_dev)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->reset_on_init &&
+	    !p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init &&
+	    (fm_reset_mac(p_fm_mac_ctrl_drv->h_fm,
+			((ENET_INTERFACE_FROM_MODE
+			  (p_fm_mac_ctrl_drv->enet_mode) ==
+			  ENET_IF_XGMII) ? FM_MAC_10G : FM_MAC_1G),
+			p_fm_mac_ctrl_drv->mac_id) != 0)) {
+		pr_err("Can't reset MAC!\n");
+		return -ENOSYS;
+	}
+	if (p_fm_mac_ctrl_drv->f_fm_mac_init)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_init(fm_mac_dev);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_init() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_init);
+
+int fm_mac_free(struct fm_mac_dev *fm_mac_dev)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_free)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_free(fm_mac_dev);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_free() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_free);
+
+int fm_mac_cfg_reset_on_init(struct fm_mac_dev *fm_mac_dev, bool enable)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init(fm_mac_dev,
+								    enable);
+	else
+		err = 0;
+
+	p_fm_mac_ctrl_drv->reset_on_init = enable;
+	if (unlikely(err < 0))
+		pr_err("fm_mac_reset_on_init() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_reset_on_init);
+
+int fm_mac_cfg_max_frame_len(struct fm_mac_dev *fm_mac_dev, uint16_t new_val)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len(fm_mac_dev,
+								    new_val);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_cfg_max_frame_len() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_max_frame_len);
+
+int fm_mac_cfg_pad_and_crc(struct fm_mac_dev *fm_mac_dev, bool new_val)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc(fm_mac_dev,
+								  new_val);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_init() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_pad_and_crc);
+
+int fm_mac_cfg_tbi_phy_addr(struct fm_mac_dev *fm_mac_dev, uint8_t new_val)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_tbi_phy_addr)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_tbi_phy_addr(fm_mac_dev,
+								    new_val);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_cfg_tbi_phy_addr() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_tbi_phy_addr);
+
+int fm_mac_cfg_len_check(struct fm_mac_dev *fm_mac_dev, bool new_val)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check(fm_mac_dev,
+								new_val);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_cfg_len_check() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_len_check);
+
+int fm_mac_cfg_exception(struct fm_mac_dev *fm_mac_dev,
+			 enum fm_mac_exceptions ex,
+			 bool enable)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception(fm_mac_dev,
+								ex,
+								enable);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_cfg_exception() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_exception);
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_mac_cfg_skip_fman11_wa(struct fm_mac_dev *fm_mac_dev)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_skip_fman11_wa)
+		err = p_fm_mac_ctrl_drv->
+			f_fm_mac_cfg_skip_fman11_wa(fm_mac_dev);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_cfg_skip_fman11_wa() = 0x%08x\n",
+		       err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_skip_fman11_wa);
+
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* Run Time Control                                                          */
+
+int fm_mac_enable(struct fm_mac_dev *fm_mac_dev, enum comm_mode mode)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_enable)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_enable(fm_mac_dev, mode);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_enable() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_enable);
+
+int fm_mac_disable(struct fm_mac_dev *fm_mac_dev, enum comm_mode mode)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_disable)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_disable(fm_mac_dev, mode);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_disable() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_disable);
+
+int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev,
+			       uint8_t priority,
+			       uint16_t pause_time,
+			       uint16_t thresh_time)
+{
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames)
+		return p_fm_mac_ctrl_drv->
+		    f_fm_mac_set_tx_auto_pause_frames(fm_mac_dev, pause_time);
+
+	return -ENOSYS;
+}
+EXPORT_SYMBOL(fm_mac_set_tx_pause_frames);
+
+int fm_mac_set_rx_pause_frames(struct fm_mac_dev *fm_mac_dev, bool en)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames)
+		err = p_fm_mac_ctrl_drv->
+			f_fm_mac_set_rx_ignore_pause_frames(fm_mac_dev, !en);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_set_rx_ignore_pause_frames() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_set_rx_pause_frames);
+
+int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev,
+			 enum fm_mac_exceptions ex,
+			 bool enable)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_set_exception)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_set_exception(fm_mac_dev,
+								ex,
+								enable);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_set_exception() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_set_exception);
+
+int fm_mac_modify_mac_addr(struct fm_mac_dev *fm_mac_dev,
+			   enet_addr_t *p_enet_addr)
+{
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr)
+		return p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr(fm_mac_dev,
+								   p_enet_addr);
+
+	return -ENOSYS;
+}
+EXPORT_SYMBOL(fm_mac_modify_mac_addr);
+
+int fm_mac_add_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+			     enet_addr_t *p_enet_addr)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr)
+		err = p_fm_mac_ctrl_drv->
+			f_fm_mac_add_hash_mac_addr(fm_mac_dev, p_enet_addr);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_add_hash_mac_addr() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_add_hash_mac_addr);
+
+int fm_mac_remove_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+				enet_addr_t *p_enet_addr)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr)
+		err = p_fm_mac_ctrl_drv->
+			f_fm_mac_remove_hash_mac_addr(fm_mac_dev, p_enet_addr);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_remove_hash_mac_addr() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_remove_hash_mac_addr);
+
+int fm_mac_get_version(struct fm_mac_dev *fm_mac_dev, uint32_t *mac_version)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_get_version)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_get_version(fm_mac_dev,
+							      mac_version);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_get_version() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_get_version);
+
+int fm_mac_get_id(struct fm_mac_dev *fm_mac_dev, uint32_t *mac_id)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_get_id)
+		err = p_fm_mac_ctrl_drv->f_fm_mac_get_id(fm_mac_dev, mac_id);
+	else
+		err = -ENOSYS;
+	if (unlikely(err < 0))
+		pr_err("fm_mac_get_id() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_get_id);
+
+int fm_mac_set_promiscuous(struct fm_mac_dev *fm_mac_dev, bool new_val)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous)
+		err =  p_fm_mac_ctrl_drv->
+			f_fm_mac_set_promiscuous(fm_mac_dev, new_val);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_get_id() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_set_promiscuous);
+
+int fm_mac_adjust_link(struct fm_mac_dev *fm_mac_dev, int link,
+		       enum ethernet_speed speed)
+{
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (!link) {
+		if (p_fm_mac_ctrl_drv->fm_rev_info.major_rev < 6)
+			fm_mac_restart_autoneg(fm_mac_dev);
+
+		return 0;
+	}
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_adjust_link)
+		return p_fm_mac_ctrl_drv->f_fm_mac_adjust_link(fm_mac_dev,
+							       speed);
+
+	return -ENOSYS;
+}
+EXPORT_SYMBOL(fm_mac_adjust_link);
+
+int fm_mac_restart_autoneg(struct fm_mac_dev *fm_mac_dev)
+{
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg)
+		return p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg(fm_mac_dev);
+
+	return -ENOSYS;
+}
+
+uint16_t fm_mac_get_max_frame_length(struct fm_mac_dev *fm_mac_dev)
+{
+	int err;
+	struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+	if (p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length)
+		err = p_fm_mac_ctrl_drv->
+		f_fm_mac_get_max_frame_length(fm_mac_dev);
+	else
+		err = -ENOSYS;
+
+	if (unlikely(err < 0))
+		pr_err("fm_mac_get_max_frame_length() = 0x%08x\n", err);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_mac_get_max_frame_length);
diff --git a/drivers/net/ethernet/freescale/fman/mac/fm_mac.h b/drivers/net/ethernet/freescale/fman/mac/fm_mac.h
new file mode 100644
index 0000000..81fd563
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fm_mac.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM MAC ... */
+#ifndef __FM_MAC_H
+#define __FM_MAC_H
+
+#include "service.h"
+#include "fm_mac_ext.h"
+#include "fm_common.h"
+
+#include <linux/slab.h>
+
+/* defaults */
+
+#define DEFAULT_RESET_ON_INIT                 false
+
+struct eth_hash_entry_t {
+	uint64_t addr;		/* Ethernet Address  */
+	struct list_head node;
+};
+
+#define ETH_HASH_ENTRY_OBJ(ptr) list_object(ptr, struct eth_hash_entry_t, node)
+
+struct eth_hash_t {
+	uint16_t size;
+	struct list_head *p_lsts;
+};
+
+struct fm_mac_ctrl_drv_t {
+	int (*f_fm_mac_init)(void *h_fm_mac);
+	int (*f_fm_mac_free)(void *h_fm_mac);
+
+	int (*f_fm_mac_cfg_lb)(void *h_fm_mac, bool new_val);
+	int (*f_fm_mac_cfg_max_frame_len)(void *h_fm_mac, uint16_t new_val);
+	int (*f_fm_mac_cfg_pad_and_crc)(void *h_fm_mac, bool new_val);
+	int (*f_fm_mac_cfg_len_check)(void *h_fm_mac, bool new_val);
+	int (*f_fm_mac_cfg_tbi_phy_addr)(void *h_fm_mac, uint8_t new_val);
+	int (*f_fm_mac_cfg_exception)(void *h_fm_mac,
+				      enum fm_mac_exceptions, bool enable);
+	int (*f_fm_mac_cfg_reset_on_init)(void *h_fm_mac, bool enable);
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+	int (*f_fm_mac_cfg_skip_fman11_wa)(void *h_fm_mac);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+	int (*f_fm_mac_set_exception)(void *h_fm_mac,
+				      enum fm_mac_exceptions ex,
+				      bool enable);
+
+	int (*f_fm_mac_enable)(void *h_fm_mac, enum comm_mode mode);
+	int (*f_fm_mac_disable)(void *h_fm_mac, enum comm_mode mode);
+	int (*f_fm_mac_reset)(void *h_fm_mac, bool wait);
+
+	int (*f_fm_mac_set_tx_auto_pause_frames)(void *h_fm_mac,
+						 uint16_t pause_time);
+	int (*f_fm_mac_set_tx_pause_frames)(void *h_fm_mac,
+					    uint8_t priority,
+					    uint16_t pause_time,
+					    uint16_t thresh_time);
+	int (*f_fm_mac_set_rx_ignore_pause_frames)(void *h_fm_mac, bool en);
+
+	int (*f_fm_mac_modify_mac_addr)(void *h_fm_mac,
+					enet_addr_t *p_enet_addr);
+	int (*f_fm_mac_add_hash_mac_addr)(void *h_fm_mac,
+					  enet_addr_t *p_enet_addr);
+	int (*f_fm_mac_remove_hash_mac_addr)(void *h_fm_mac,
+					     enet_addr_t *p_enet_addr);
+	int (*f_fm_mac_set_promiscuous)(void *h_fm_mac, bool new_val);
+	int (*f_fm_mac_adjust_link)(void *h_fm_mac,
+				    enum ethernet_speed speed);
+	int (*f_fm_mac_restart_autoneg)(void *h_fm_mac);
+
+	int (*f_fm_mac_get_id)(void *h_fm_mac, uint32_t *mac_id);
+
+	int (*f_fm_mac_get_version)(void *h_fm_mac, uint32_t *mac_version);
+
+	uint16_t (*f_fm_mac_get_max_frame_length)(void *h_fm_mac);
+
+	void *h_fm;
+	struct fm_revision_info_t fm_rev_info;
+	enum e_enet_mode enet_mode;
+	uint8_t mac_id;
+	bool reset_on_init;
+	uint16_t clk_freq;
+};
+
+void *dtsec_config(struct fm_mac_params_t *p_fm_mac_param);
+void *tgec_config(struct fm_mac_params_t *p_fm_mac_params);
+void *memac_config(struct fm_mac_params_t *p_fm_mac_param);
+
+static inline struct eth_hash_entry_t
+*dequeue_addr_from_hash_entry(struct list_head *p_addr_lst)
+{
+	struct eth_hash_entry_t *p_hash_entry = NULL;
+
+	if (!list_empty(p_addr_lst)) {
+		p_hash_entry = ETH_HASH_ENTRY_OBJ(p_addr_lst->next);
+		list_del_init(&p_hash_entry->node);
+	}
+	return p_hash_entry;
+}
+
+static inline void free_hash_table(struct eth_hash_t *p_hash)
+{
+	struct eth_hash_entry_t *p_hash_entry;
+	int i = 0;
+
+	if (p_hash) {
+		if (p_hash->p_lsts) {
+			for (i = 0; i < p_hash->size; i++) {
+				p_hash_entry =
+				    dequeue_addr_from_hash_entry(&p_hash->
+							     p_lsts[i]);
+				while (p_hash_entry) {
+					kfree(p_hash_entry);
+					p_hash_entry =
+					    dequeue_addr_from_hash_entry
+					    (&p_hash->p_lsts[i]);
+				}
+			}
+
+			kfree(p_hash->p_lsts);
+		}
+
+		kfree(p_hash);
+	}
+}
+
+static inline struct eth_hash_t *alloc_hash_table(uint16_t size)
+{
+	uint32_t i;
+	struct eth_hash_t *p_hash;
+
+	/* Allocate address hash table */
+	p_hash = kmalloc_array(size, sizeof(struct eth_hash_t *), GFP_KERNEL);
+	if (!p_hash)
+		return NULL;
+
+	p_hash->size = size;
+
+	p_hash->p_lsts = kmalloc_array(p_hash->size, sizeof(struct list_head),
+				       GFP_KERNEL);
+	if (!p_hash->p_lsts) {
+		kfree(p_hash);
+		return NULL;
+	}
+
+	for (i = 0; i < p_hash->size; i++)
+		INIT_LIST_HEAD(&p_hash->p_lsts[i]);
+
+	return p_hash;
+}
+
+#endif /* __FM_MAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac.c b/drivers/net/ethernet/freescale/fman/mac/memac.c
new file mode 100644
index 0000000..0f6c615
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac.c
@@ -0,0 +1,837 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM mEMAC driver */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+
+#include "fm_common.h"
+#include "memac.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/* Internal routine */
+static uint32_t get_mac_addr_hash_code(uint64_t eth_addr)
+{
+	uint64_t mask1, mask2;
+	uint32_t xor_val = 0;
+	uint8_t i, j;
+
+	for (i = 0; i < 6; i++) {
+		mask1 = eth_addr & (uint64_t)0x01;
+		eth_addr >>= 1;
+
+		for (j = 0; j < 7; j++) {
+			mask2 = eth_addr & (uint64_t)0x01;
+			mask1 ^= mask2;
+			eth_addr >>= 1;
+		}
+
+		xor_val |= (mask1 << (5 - i));
+	}
+
+	return xor_val;
+}
+
+static void setup_sgmii_internal_phy(struct memac_t *p_memac, uint8_t phy_addr)
+{
+	uint16_t tmp_reg16;
+	enum e_enet_mode enet_mode;
+
+	/* In case the higher MACs are used (i.e. the MACs that should
+	 * support 10G), speed=10000 is provided for SGMII ports.
+	 * Temporary modify enet mode to 1G one, so MII functions can
+	 * work correctly.
+	 */
+	enet_mode = p_memac->enet_mode;
+	p_memac->enet_mode =
+	    MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_memac->enet_mode),
+			   ENET_SPEED_1000);
+
+	/* SGMII mode + AN enable */
+	tmp_reg16 = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII;
+	memac_mii_write_phy_reg(p_memac, phy_addr, 0x14, tmp_reg16);
+
+	/* Device ability according to SGMII specification */
+	tmp_reg16 = PHY_SGMII_DEV_ABILITY_SGMII;
+	memac_mii_write_phy_reg(p_memac, phy_addr, 0x4, tmp_reg16);
+
+	/* Adjust link timer for SGMII  -
+	 * According to Cisco SGMII specification the timer should be 1.6 ms.
+	 * The link_timer register is configured in units of the clock.
+	 * - When running as 1G SGMII, Serdes clock is 125 MHz, so
+	 * unit = 1 / (125*10^6 Hz) = 8 ns.
+	 * 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2*10^5 = 0x30d40
+	 * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
+	 * unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
+	 * 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5*10^5 = 0x7a120.
+	 * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
+	 * we always set up here a value of 2.5 SGMII.
+	 */
+	memac_mii_write_phy_reg(p_memac, phy_addr, 0x13, 0x0007);
+	memac_mii_write_phy_reg(p_memac, phy_addr, 0x12, 0xa120);
+
+	/* Restart AN */
+	tmp_reg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+	memac_mii_write_phy_reg(p_memac, phy_addr, 0x0, tmp_reg16);
+
+	/* Restore original enet mode */
+	p_memac->enet_mode = enet_mode;
+}
+
+static void setup_sgmii_internal_phy_base_x(struct memac_t *p_memac,
+					    uint8_t phy_addr)
+{
+	uint16_t tmp_reg16;
+	enum e_enet_mode enet_mode;
+
+	/* In case the higher MACs are used (i.e. the MACs that
+	 * should support 10G), speed=10000 is provided for SGMII ports.
+	 * Temporary modify enet mode to 1G one, so MII functions can
+	 * work correctly.
+	 */
+	enet_mode = p_memac->enet_mode;
+	p_memac->enet_mode =
+	    MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_memac->enet_mode),
+			   ENET_SPEED_1000);
+
+	/* 1000BaseX mode */
+	tmp_reg16 = PHY_SGMII_IF_MODE_1000X;
+	memac_mii_write_phy_reg(p_memac, phy_addr, 0x14, tmp_reg16);
+
+	/* AN Device capability  */
+	tmp_reg16 = PHY_SGMII_DEV_ABILITY_1000X;
+	memac_mii_write_phy_reg(p_memac, phy_addr, 0x4, tmp_reg16);
+
+	/* Adjust link timer for SGMII  -
+	 * For Serdes 1000BaseX auto-negotiation the timer should be 10 ms.
+	 * The link_timer register is configured in units of the clock.
+	 * - When running as 1G SGMII, Serdes clock is 125 MHz, so
+	 * unit = 1 / (125*10^6 Hz) = 8 ns.
+	 * 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0
+	 * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
+	 * unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
+	 * 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08.
+	 * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
+	 * we always set up here a value of 2.5 SGMII.
+	 */
+	memac_mii_write_phy_reg(p_memac, phy_addr, 0x13, 0x002f);
+	memac_mii_write_phy_reg(p_memac, phy_addr, 0x12, 0xaf08);
+
+	/* Restart AN */
+	tmp_reg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+	memac_mii_write_phy_reg(p_memac, phy_addr, 0x0, tmp_reg16);
+
+	/* Restore original enet mode */
+	p_memac->enet_mode = enet_mode;
+}
+
+static int check_init_parameters(struct memac_t *p_memac)
+{
+	if (p_memac->addr == 0) {
+		pr_err("Ethernet MAC must have a valid MAC address\n");
+		return -EDOM;
+	}
+	if (!p_memac->f_exception) {
+		pr_err("Uninitialized f_exception\n");
+		return -EDOM;
+	}
+	if (!p_memac->f_event) {
+		pr_warn("Uninitialize f_event\n");
+		return -EDOM;
+	}
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+	if (!p_memac->p_memac_drv_param->no_length_check_enable) {
+		pr_err("LengthCheck!\n");
+		return -ENOSYS;
+	}
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+
+	return 0;
+}
+
+static int get_exception_flag(enum fm_mac_exceptions exception)
+{
+	uint32_t bit_mask;
+
+	switch (exception) {
+	case FM_MAC_EX_10G_1TX_ECC_ER:
+		bit_mask = MEMAC_IMASK_TECC_ER;
+		break;
+	case FM_MAC_EX_10G_RX_ECC_ER:
+		bit_mask = MEMAC_IMASK_RECC_ER;
+		break;
+	case FM_MAC_EX_TS_FIFO_ECC_ERR:
+		bit_mask = MEMAC_IMASK_TSECC_ER;
+		break;
+	case FM_MAC_EX_MAGIC_PACKET_INDICATION:
+		bit_mask = MEMAC_IMASK_MGI;
+		break;
+	default:
+		bit_mask = 0;
+		break;
+	}
+
+	return bit_mask;
+}
+
+static void memac_err_exception(void *h_memac)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	uint32_t event, imask;
+
+	event = fman_memac_get_event(p_memac->p_mem_map, 0xffffffff);
+	imask = fman_memac_get_interrupt_mask(p_memac->p_mem_map);
+
+	/* Imask include both error and notification/event bits.
+	 * Leaving only error bits enabled by imask.
+	 * The imask error bits are shifted by 16 bits offset from
+	 * their corresponding location in the ievent - hence the >> 16
+	 */
+	event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
+
+	fman_memac_ack_event(p_memac->p_mem_map, event);
+
+	if (event & MEMAC_IEVNT_TS_ECC_ER)
+		p_memac->f_exception(p_memac->h_app,
+				     FM_MAC_EX_TS_FIFO_ECC_ERR);
+	if (event & MEMAC_IEVNT_TX_ECC_ER)
+		p_memac->f_exception(p_memac->h_app,
+				     FM_MAC_EX_10G_1TX_ECC_ER);
+	if (event & MEMAC_IEVNT_RX_ECC_ER)
+		p_memac->f_exception(p_memac->h_app,
+				     FM_MAC_EX_10G_RX_ECC_ER);
+}
+
+static void memac_exception(void *h_memac)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	uint32_t event, imask;
+
+	event = fman_memac_get_event(p_memac->p_mem_map, 0xffffffff);
+	imask = fman_memac_get_interrupt_mask(p_memac->p_mem_map);
+
+	/* Imask include both error and notification/event bits.
+	 * Leaving only error bits enabled by imask.
+	 * The imask error bits are shifted by 16 bits offset from
+	 * their corresponding location in the ievent - hence the >> 16
+	 */
+	event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
+
+	fman_memac_ack_event(p_memac->p_mem_map, event);
+
+	if (event & MEMAC_IEVNT_MGI)
+		p_memac->f_exception(p_memac->h_app,
+				     FM_MAC_EX_MAGIC_PACKET_INDICATION);
+}
+
+static void free_init_resources(struct memac_t *p_memac)
+{
+	fm_unregister_intr(p_memac->fm_mac_ctrl_drv.h_fm,
+			   FM_MOD_MAC,
+			   p_memac->mac_id,
+			   FM_INTR_TYPE_ERR);
+
+	/* release the driver's group hash table */
+	free_hash_table(p_memac->p_multicast_addr_hash);
+	p_memac->p_multicast_addr_hash = NULL;
+
+	/* release the driver's individual hash table */
+	free_hash_table(p_memac->p_unicast_addr_hash);
+	p_memac->p_unicast_addr_hash = NULL;
+}
+
+/* Checks if p_memac driver parameters were initialized
+ * returns 0 if success else returns error code
+ */
+static int is_init_done(struct memac_cfg *p_memac_drv_parameters)
+{
+	if (!p_memac_drv_parameters)
+		return 0;
+	return -ENOSYS;
+}
+
+/* mEMAC API routine */
+
+static int memac_enable(void *h_memac, enum comm_mode mode)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (ret)
+		return ret;
+
+	fman_memac_enable(p_memac->p_mem_map,
+			  (mode & COMM_MODE_RX),
+			  (mode & COMM_MODE_TX));
+
+	return 0;
+}
+
+static int memac_disable(void *h_memac, enum comm_mode mode)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (ret)
+		return ret;
+
+	fman_memac_disable(p_memac->p_mem_map,
+			   (mode & COMM_MODE_RX),
+			   (mode & COMM_MODE_TX));
+
+	return 0;
+}
+
+static int memac_set_promiscuous(void *h_memac, bool new_val)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (ret)
+		return ret;
+
+	fman_memac_set_promiscuous(p_memac->p_mem_map, new_val);
+
+	return 0;
+}
+
+static int memac_adjust_link(void *h_memac, enum ethernet_speed speed)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret, full_duplex = true;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (ret)
+		return ret;
+
+	fman_memac_adjust_link(p_memac->p_mem_map,
+			       (enum enet_interface)
+			       ENET_INTERFACE_FROM_MODE(p_memac->enet_mode),
+			       (enum enet_speed)speed, full_duplex);
+	return 0;
+}
+
+/* memac configs modification function */
+
+static int memac_cfg_lb(void *h_memac, bool new_val)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_memac->p_memac_drv_param->loopback_enable = new_val;
+
+	return 0;
+}
+
+static int memac_cfg_max_frame_len(void *h_memac, uint16_t new_val)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_memac->p_memac_drv_param->max_frame_length = new_val;
+
+	return 0;
+}
+
+static int memac_cfg_pad(void *h_memac, bool new_val)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_memac->p_memac_drv_param->pad_enable = new_val;
+
+	return 0;
+}
+
+static int memac_cfg_len_check(void *h_memac, bool new_val)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_memac->p_memac_drv_param->no_length_check_enable = !new_val;
+
+	return 0;
+}
+
+static int memac_cfg_exception(void *h_memac,
+			       enum fm_mac_exceptions exception, bool enable)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	uint32_t bit_mask = 0;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	bit_mask = get_exception_flag(exception);
+	if (bit_mask) {
+		if (enable)
+			p_memac->exceptions |= bit_mask;
+		else
+			p_memac->exceptions &= ~bit_mask;
+	} else {
+		pr_err("Undefined exception\n");
+		return -EDOM;
+	}
+	return 0;
+}
+
+static int memac_cfg_reset_on_init(void *h_memac, bool enable)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_memac->p_memac_drv_param->reset_on_init = enable;
+
+	return 0;
+}
+
+/* memac run time api functions */
+
+static int memac_set_tx_auto_pause_frames(void *h_memac,
+					  uint16_t pause_time)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+	fman_memac_set_tx_pause_frames(p_memac->p_mem_map, FM_MAC_NO_PFC,
+				       pause_time, 0);
+
+	return 0;
+}
+
+static int memac_set_rx_ignore_pause_frames(void *h_memac, bool en)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (ret)
+		return ret;
+
+	fman_memac_set_rx_ignore_pause_frames(p_memac->p_mem_map, en);
+
+	return 0;
+}
+
+static int memac_modify_mac_address(void *h_memac,
+				    enet_addr_t *p_enet_addr)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (ret)
+		return ret;
+
+	fman_memac_add_addr_in_paddr(p_memac->p_mem_map,
+				     (uint8_t *)(*p_enet_addr), 0);
+
+	return 0;
+}
+
+static int memac_add_hash_mac_address(void *h_memac,
+				      enet_addr_t *p_eth_addr)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	struct eth_hash_entry_t *p_hash_entry;
+	uint32_t hash;
+	uint64_t eth_addr;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (ret)
+		return ret;
+
+	eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+	if (!(eth_addr & GROUP_ADDRESS)) {
+		/* Unicast addresses not supported in hash */
+		pr_err("Unicast Address\n");
+		return -ENOSYS;
+	}
+	hash = get_mac_addr_hash_code(eth_addr) & HASH_CTRL_ADDR_MASK;
+
+	/* Create element to be added to the driver hash table */
+	p_hash_entry = kmalloc(sizeof(*p_hash_entry), GFP_KERNEL);
+	if (!p_hash_entry)
+		return -ENOMEM;
+	p_hash_entry->addr = eth_addr;
+	INIT_LIST_HEAD(&p_hash_entry->node);
+
+	list_add_tail(&p_hash_entry->node,
+		      &p_memac->p_multicast_addr_hash->p_lsts[hash]);
+	fman_memac_set_hash_table(p_memac->p_mem_map,
+				  (hash | HASH_CTRL_MCAST_EN));
+
+	return 0;
+}
+
+static int memac_del_hash_mac_address(void *h_memac,
+				      enet_addr_t *p_eth_addr)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	struct eth_hash_entry_t *p_hash_entry = NULL;
+	struct list_head *p_pos;
+	uint32_t hash;
+	uint64_t eth_addr;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (ret)
+		return ret;
+
+	eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+	hash = get_mac_addr_hash_code(eth_addr) & HASH_CTRL_ADDR_MASK;
+
+	list_for_each(p_pos, &p_memac->p_multicast_addr_hash->p_lsts[hash]) {
+		p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+		if (p_hash_entry->addr == eth_addr) {
+			list_del_init(&p_hash_entry->node);
+			kfree(p_hash_entry);
+			break;
+		}
+	}
+	if (list_empty(&p_memac->p_multicast_addr_hash->p_lsts[hash]))
+		fman_memac_set_hash_table(p_memac->p_mem_map,
+					  (hash & ~HASH_CTRL_MCAST_EN));
+
+	return 0;
+}
+
+static int memac_set_exception(void *h_memac,
+			       enum fm_mac_exceptions exception,
+				   bool enable)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	uint32_t bit_mask = 0;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (ret)
+		return ret;
+
+	bit_mask = get_exception_flag(exception);
+	if (bit_mask) {
+		if (enable)
+			p_memac->exceptions |= bit_mask;
+		else
+			p_memac->exceptions &= ~bit_mask;
+	} else {
+		pr_err("Undefined exception\n");
+		return -EDOM;
+	}
+	fman_memac_set_exception(p_memac->p_mem_map, bit_mask, enable);
+
+	return 0;
+}
+
+static uint16_t memac_get_max_frame_length(void *h_memac)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	int ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (ret)
+		return 0;
+
+	return fman_memac_get_max_frame_len(p_memac->p_mem_map);
+}
+
+/* mEMAC Init & Free API */
+static int memac_init(void *h_memac)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+	struct memac_cfg *p_memac_drv_param;
+	enum enet_interface enet_interface;
+	enum enet_speed enet_speed;
+	uint8_t i, phy_addr;
+	enet_addr_t eth_addr;
+	enum fm_mac_type port_type;
+	bool slow_10g_if = false;
+	int err, ret;
+
+	ret = is_init_done(p_memac->p_memac_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	err = check_init_parameters(p_memac);
+	if (err)
+		return err;
+
+	p_memac_drv_param = p_memac->p_memac_drv_param;
+
+	if (p_memac->fm_mac_ctrl_drv.fm_rev_info.major_rev == 6 &&
+	    p_memac->fm_mac_ctrl_drv.fm_rev_info.minor_rev == 4)
+		slow_10g_if = true;
+
+	port_type =
+	    ((ENET_SPEED_FROM_MODE(p_memac->enet_mode) <
+	      ENET_SPEED_10000) ? FM_MAC_1G : FM_MAC_10G);
+
+	/* First, reset the MAC if desired. */
+	if (p_memac_drv_param->reset_on_init)
+		fman_memac_reset(p_memac->p_mem_map);
+
+	/* MAC Address */
+	MAKE_ENET_ADDR_FROM_UINT64(p_memac->addr, eth_addr);
+	fman_memac_add_addr_in_paddr(p_memac->p_mem_map,
+				     (uint8_t *)eth_addr, 0);
+
+	enet_interface =
+	    (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_memac->enet_mode);
+	enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_memac->enet_mode);
+
+	fman_memac_init(p_memac->p_mem_map,
+			p_memac->p_memac_drv_param,
+			enet_interface,
+			enet_speed,
+			slow_10g_if,
+			p_memac->exceptions);
+
+#ifdef FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320
+	{
+		uint32_t tmp_reg = 0;
+
+		fm_get_revision(p_memac->fm_mac_ctrl_drv.h_fm,
+				&p_memac->fm_mac_ctrl_drv.fm_rev_info);
+		/* check the FMAN version - the bug exists only in rev1 */
+		if ((p_memac->fm_mac_ctrl_drv.fm_rev_info.major_rev == 6) &&
+		    ((p_memac->fm_mac_ctrl_drv.fm_rev_info.minor_rev == 0) ||
+		     (p_memac->fm_mac_ctrl_drv.fm_rev_info.minor_rev == 3))) {
+			/* MAC strips CRC from received frames - this
+			 * workaround should decrease the likelihood of bug
+			 * appearance
+			 */
+			tmp_reg = GET_UINT32(p_memac->p_mem_map->
+					     command_config);
+			tmp_reg &= ~CMD_CFG_CRC_FWD;
+			WRITE_UINT32(p_memac->p_mem_map->command_config,
+				     tmp_reg);
+		}
+	}
+#endif /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 */
+
+	if (ENET_INTERFACE_FROM_MODE(p_memac->enet_mode) == ENET_IF_SGMII) {
+		/* Configure internal SGMII PHY */
+		if (p_memac->enet_mode & ENET_IF_SGMII_BASEX)
+			setup_sgmii_internal_phy_base_x(p_memac, PHY_MDIO_ADDR);
+		else
+			setup_sgmii_internal_phy(p_memac, PHY_MDIO_ADDR);
+	} else if (ENET_INTERFACE_FROM_MODE(p_memac->enet_mode) ==
+		   ENET_IF_QSGMII) {
+		/* Configure 4 internal SGMII PHYs */
+		for (i = 0; i < 4; i++) {
+			/* QSGMII PHY address occupies 3 upper bits of 5-bit
+			 * phy_address; the lower 2 bits are used to extend
+			 * register address space and access each one of 4
+			 * ports inside QSGMII.
+			 */
+			phy_addr = (uint8_t)((PHY_MDIO_ADDR << 2) | i);
+			if (p_memac->enet_mode & ENET_IF_SGMII_BASEX)
+				setup_sgmii_internal_phy_base_x(p_memac,
+								phy_addr);
+			else
+				setup_sgmii_internal_phy(p_memac, phy_addr);
+		}
+	}
+
+	/* Max Frame Length */
+	err = fm_set_mac_max_frame(p_memac->fm_mac_ctrl_drv.h_fm,
+				   port_type,
+				   p_memac->fm_mac_ctrl_drv.mac_id,
+				   p_memac_drv_param->max_frame_length);
+	if (err) {
+		pr_err("settings Mac max frame length is FAILED\n");
+		return err;
+	}
+
+	p_memac->p_multicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+	if (!p_memac->p_multicast_addr_hash) {
+		free_init_resources(p_memac);
+		pr_err("allocation hash table is FAILED\n");
+		return -ENOMEM;
+	}
+
+	p_memac->p_unicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+	if (!p_memac->p_unicast_addr_hash) {
+		free_init_resources(p_memac);
+		pr_err("allocation hash table is FAILED\n");
+		return -ENOMEM;
+	}
+
+	fm_register_intr(p_memac->fm_mac_ctrl_drv.h_fm,
+			 FM_MOD_MAC,
+			 p_memac->mac_id,
+			 FM_INTR_TYPE_ERR,
+			 memac_err_exception,
+			 p_memac);
+
+	fm_register_intr(p_memac->fm_mac_ctrl_drv.h_fm,
+			 FM_MOD_MAC,
+			 p_memac->mac_id, FM_INTR_TYPE_NORMAL,
+			 memac_exception, p_memac);
+
+	kfree(p_memac_drv_param);
+	p_memac->p_memac_drv_param = NULL;
+
+	return 0;
+}
+
+static int memac_free(void *h_memac)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+	free_init_resources(p_memac);
+
+	kfree(p_memac->p_memac_drv_param);
+	kfree(p_memac);
+
+	return 0;
+}
+
+static void init_fm_mac_ctrl_drv(struct fm_mac_ctrl_drv_t *
+					  p_fm_mac_ctrl_drv)
+{
+	p_fm_mac_ctrl_drv->f_fm_mac_init = memac_init;
+	p_fm_mac_ctrl_drv->f_fm_mac_free = memac_free;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_lb = memac_cfg_lb;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len =
+	memac_cfg_max_frame_len;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc = memac_cfg_pad;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check = memac_cfg_len_check;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception = memac_cfg_exception;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init =
+	memac_cfg_reset_on_init;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_set_exception = memac_set_exception;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous = memac_set_promiscuous;
+	p_fm_mac_ctrl_drv->f_fm_mac_adjust_link = memac_adjust_link;
+	p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg = NULL;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_enable = memac_enable;
+	p_fm_mac_ctrl_drv->f_fm_mac_disable = memac_disable;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames =
+		memac_set_tx_auto_pause_frames;
+	p_fm_mac_ctrl_drv->f_fm_mac_set_tx_pause_frames = NULL;
+	p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames =
+		memac_set_rx_ignore_pause_frames;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr =
+		memac_modify_mac_address;
+	p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr =
+		memac_add_hash_mac_address;
+	p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr =
+		memac_del_hash_mac_address;
+	p_fm_mac_ctrl_drv->f_fm_mac_get_id = NULL;
+	p_fm_mac_ctrl_drv->f_fm_mac_get_version = NULL;
+	p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length =
+		memac_get_max_frame_length;
+}
+
+/* m_emac config main entry */
+
+void *memac_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+	struct memac_t *p_memac;
+	struct memac_cfg *p_memac_drv_param;
+	uintptr_t base_addr;
+
+	base_addr = p_fm_mac_param->base_addr;
+	/* allocate memory for the m_emac data structure */
+	p_memac = kzalloc(sizeof(*p_memac), GFP_KERNEL);
+	if (!p_memac)
+		return NULL;
+
+	init_fm_mac_ctrl_drv(&p_memac->fm_mac_ctrl_drv);
+
+	/* allocate memory for the m_emac driver parameters data structure */
+	p_memac_drv_param = kzalloc(sizeof(*p_memac_drv_param),
+				    GFP_KERNEL);
+	if (!p_memac_drv_param) {
+		memac_free(p_memac);
+		return NULL;
+	}
+
+	/* Plant parameter structure pointer */
+	p_memac->p_memac_drv_param = p_memac_drv_param;
+
+	fman_memac_defconfig(p_memac_drv_param);
+
+	p_memac->addr = ENET_ADDR_TO_UINT64(p_fm_mac_param->addr);
+
+	p_memac->p_mem_map =
+		(struct memac_regs __iomem *)UINT_TO_PTR(base_addr);
+	p_memac->p_mii_mem_map = (struct memac_mii_access_mem_map __iomem *)
+		UINT_TO_PTR(base_addr + MEMAC_TO_MII_OFFSET);
+
+	p_memac->enet_mode = p_fm_mac_param->enet_mode;
+	p_memac->mac_id = p_fm_mac_param->mac_id;
+	p_memac->exceptions = MEMAC_default_exceptions;
+	p_memac->f_exception = p_fm_mac_param->f_exception;
+	p_memac->f_event = p_fm_mac_param->f_event;
+	p_memac->h_app = p_fm_mac_param->h_app;
+
+	return p_memac;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac.h b/drivers/net/ethernet/freescale/fman/mac/memac.h
new file mode 100644
index 0000000..9f0c607
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM Multirate Ethernet MAC (mEMAC) */
+#ifndef __MEMAC_H
+#define __MEMAC_H
+
+#include "service.h"
+
+#include "fsl_fman_memac_mii_acc.h"
+#include "fm_mac.h"
+#include "fsl_fman_memac.h"
+
+#define MEMAC_default_exceptions\
+	((uint32_t)(MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER |\
+		MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI))
+
+struct memac_t {
+	/* Upper Mac control block */
+	struct fm_mac_ctrl_drv_t fm_mac_ctrl_drv;
+	/* Handle to the upper layer application  */
+	void *h_app;
+	/* Pointer to MAC memory mapped registers */
+	struct memac_regs __iomem *p_mem_map;
+	/* Pointer to MII memory mapped registers */
+	struct memac_mii_access_mem_map __iomem *p_mii_mem_map;
+	/* MAC address of device */
+	uint64_t addr;
+	/* Ethernet physical interface  */
+	enum e_enet_mode enet_mode;
+	fm_mac_exception_cb *f_exception;
+	int mdio_irq;
+	fm_mac_exception_cb *f_event;
+	/* Whether a particular individual address
+	 * recognition register is being used
+	 */
+	bool ind_addr_reg_used[MEMAC_NUM_OF_PADDRS];
+	/* MAC address for particular individual address
+	 * recognition register
+	 */
+	uint64_t paddr[MEMAC_NUM_OF_PADDRS];
+	/* Number of individual addresses in registers for this station. */
+	uint8_t num_of_ind_addr_in_regs;
+	/* Pointer to driver's global address hash table  */
+	struct eth_hash_t *p_multicast_addr_hash;
+	/* Pointer to driver's individual address hash table  */
+	struct eth_hash_t *p_unicast_addr_hash;
+	bool debug_mode;
+	uint8_t mac_id;
+	uint32_t exceptions;
+	struct memac_cfg *p_memac_drv_param;
+};
+
+/* Internal PHY access */
+#define PHY_MDIO_ADDR               0
+
+/* Internal PHY Registers - SGMII */
+#define PHY_SGMII_CR_RESET_AN           0x0200
+#define PHY_SGMII_CR_DEF_VAL            0x1140
+#define PHY_SGMII_DEV_ABILITY_SGMII     0x4001
+#define PHY_SGMII_DEV_ABILITY_1000X     0x01A0
+#define PHY_SGMII_IF_MODE_AN            0x0002
+#define PHY_SGMII_IF_MODE_SGMII         0x0001
+#define PHY_SGMII_IF_MODE_1000X         0x0000
+
+/* Offset from the MEM map to the MDIO mem map */
+#define MEMAC_TO_MII_OFFSET         0x030
+
+int memac_mii_write_phy_reg(void *h_memac, uint8_t phy_addr, uint8_t reg,
+			    uint16_t data);
+int memac_mii_read_phy_reg(void *h_memac, uint8_t phy_addr, uint8_t reg,
+			   uint16_t *p_data);
+
+#endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c
new file mode 100644
index 0000000..0150e9d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "service.h"
+#include "fm_mac.h"
+#include "memac.h"
+
+#include "fm_common.h"
+#include "memac_mii_acc.h"
+
+int memac_mii_write_phy_reg(void *h_memac,
+			    uint8_t phy_addr, uint8_t reg, uint16_t data)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+	return (int)fman_memac_mii_write_phy_reg(p_memac->p_mii_mem_map,
+						 phy_addr,
+						     reg,
+						     data,
+						     (enum enet_speed)
+						     ENET_SPEED_FROM_MODE
+						     (p_memac->enet_mode));
+}
+
+int memac_mii_read_phy_reg(void *h_memac,
+			   uint8_t phy_addr, uint8_t reg, uint16_t *p_data)
+{
+	struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+	return fman_memac_mii_read_phy_reg(p_memac->p_mii_mem_map,
+					   phy_addr,
+					   reg,
+					   p_data,
+					   (enum enet_speed)
+					   ENET_SPEED_FROM_MODE(p_memac->
+								enet_mode));
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h
new file mode 100644
index 0000000..f38572c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MEMAC_MII_ACC_H
+#define __MEMAC_MII_ACC_H
+
+#include "service.h"
+
+/* MII Management Registers */
+#define MDIO_CFG_CLK_DIV_MASK       0x0080ff80
+#define MDIO_CFG_HOLD_MASK          0x0000001c
+#define MDIO_CFG_ENC45              0x00000040
+#define MDIO_CFG_READ_ERR           0x00000002
+#define MDIO_CFG_BSY                0x00000001
+
+#define MDIO_CTL_PHY_ADDR_SHIFT     5
+#define MDIO_CTL_READ               0x00008000
+
+#define MDIO_DATA_BSY               0x80000000
+
+#endif /* __MEMAC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/tgec.c b/drivers/net/ethernet/freescale/fman/mac/tgec.c
new file mode 100644
index 0000000..30b0078
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/tgec.c
@@ -0,0 +1,797 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* TGEC MAC ... */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "crc_mac_addr_ext.h"
+
+#include "fm_common.h"
+#include "fsl_fman_tgec.h"
+#include "tgec.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/bitrev.h>
+
+/* Internal routines */
+
+static int check_init_parameters(struct tgec_t *p_tgec)
+{
+	if (ENET_SPEED_FROM_MODE(p_tgec->enet_mode) < ENET_SPEED_10000) {
+		pr_err("10G MAC driver only support 10G speed\n");
+		return -EDOM;
+	}
+	if (p_tgec->addr == 0) {
+		pr_err("Ethernet 10G MAC Must have valid MAC Address\n");
+		return -EDOM;
+	}
+	if (!p_tgec->f_exception) {
+		pr_err("uninitialized f_exception\n");
+		return -EDOM;
+	}
+	if (!p_tgec->f_event) {
+		pr_err("uninitialized f_event\n");
+		return -EDOM;
+	}
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+	if (!p_tgec->p_tgec_drv_param->no_length_check_enable) {
+		pr_warn("LengthCheck!\n");
+		return -EDOM;
+	}
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+	return 0;
+}
+
+static int get_exception_flag(enum fm_mac_exceptions exception)
+{
+	uint32_t bit_mask;
+
+	switch (exception) {
+	case FM_MAC_EX_10G_MDIO_SCAN_EVENT:
+		bit_mask = TGEC_IMASK_MDIO_SCAN_EVENT;
+		break;
+	case FM_MAC_EX_10G_MDIO_CMD_CMPL:
+		bit_mask = TGEC_IMASK_MDIO_CMD_CMPL;
+		break;
+	case FM_MAC_EX_10G_REM_FAULT:
+		bit_mask = TGEC_IMASK_REM_FAULT;
+		break;
+	case FM_MAC_EX_10G_LOC_FAULT:
+		bit_mask = TGEC_IMASK_LOC_FAULT;
+		break;
+	case FM_MAC_EX_10G_1TX_ECC_ER:
+		bit_mask = TGEC_IMASK_TX_ECC_ER;
+		break;
+	case FM_MAC_EX_10G_TX_FIFO_UNFL:
+		bit_mask = TGEC_IMASK_TX_FIFO_UNFL;
+		break;
+	case FM_MAC_EX_10G_TX_FIFO_OVFL:
+		bit_mask = TGEC_IMASK_TX_FIFO_OVFL;
+		break;
+	case FM_MAC_EX_10G_TX_ER:
+		bit_mask = TGEC_IMASK_TX_ER;
+		break;
+	case FM_MAC_EX_10G_RX_FIFO_OVFL:
+		bit_mask = TGEC_IMASK_RX_FIFO_OVFL;
+		break;
+	case FM_MAC_EX_10G_RX_ECC_ER:
+		bit_mask = TGEC_IMASK_RX_ECC_ER;
+		break;
+	case FM_MAC_EX_10G_RX_JAB_FRM:
+		bit_mask = TGEC_IMASK_RX_JAB_FRM;
+		break;
+	case FM_MAC_EX_10G_RX_OVRSZ_FRM:
+		bit_mask = TGEC_IMASK_RX_OVRSZ_FRM;
+		break;
+	case FM_MAC_EX_10G_RX_RUNT_FRM:
+		bit_mask = TGEC_IMASK_RX_RUNT_FRM;
+		break;
+	case FM_MAC_EX_10G_RX_FRAG_FRM:
+		bit_mask = TGEC_IMASK_RX_FRAG_FRM;
+		break;
+	case FM_MAC_EX_10G_RX_LEN_ER:
+		bit_mask = TGEC_IMASK_RX_LEN_ER;
+		break;
+	case FM_MAC_EX_10G_RX_CRC_ER:
+		bit_mask = TGEC_IMASK_RX_CRC_ER;
+		break;
+	case FM_MAC_EX_10G_RX_ALIGN_ER:
+		bit_mask = TGEC_IMASK_RX_ALIGN_ER;
+		break;
+	default:
+		bit_mask = 0;
+		break;
+	}
+
+	return bit_mask;
+}
+
+static uint32_t get_mac_addr_hash_code(uint64_t eth_addr)
+{
+	uint32_t crc;
+
+	/* CRC calculation */
+	GET_MAC_ADDR_CRC(eth_addr, crc);
+
+	crc = bitrev32(crc);
+
+	return crc;
+}
+
+static void tgec_err_exception(void *h_tgec)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	uint32_t event;
+	struct tgec_regs __iomem *p_tgec_mem_map = p_tgec->p_mem_map;
+
+	/* do not handle MDIO events */
+	event =
+	    fman_tgec_get_event(p_tgec_mem_map,
+				~(TGEC_IMASK_MDIO_SCAN_EVENT |
+				  TGEC_IMASK_MDIO_CMD_CMPL));
+	event &= fman_tgec_get_interrupt_mask(p_tgec_mem_map);
+
+	fman_tgec_ack_event(p_tgec_mem_map, event);
+
+	if (event & TGEC_IMASK_REM_FAULT)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_REM_FAULT);
+	if (event & TGEC_IMASK_LOC_FAULT)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_LOC_FAULT);
+	if (event & TGEC_IMASK_TX_ECC_ER)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_1TX_ECC_ER);
+	if (event & TGEC_IMASK_TX_FIFO_UNFL)
+		p_tgec->f_exception(p_tgec->h_app,
+				    FM_MAC_EX_10G_TX_FIFO_UNFL);
+	if (event & TGEC_IMASK_TX_FIFO_OVFL)
+		p_tgec->f_exception(p_tgec->h_app,
+				    FM_MAC_EX_10G_TX_FIFO_OVFL);
+	if (event & TGEC_IMASK_TX_ER)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_TX_ER);
+	if (event & TGEC_IMASK_RX_FIFO_OVFL)
+		p_tgec->f_exception(p_tgec->h_app,
+				    FM_MAC_EX_10G_RX_FIFO_OVFL);
+	if (event & TGEC_IMASK_RX_ECC_ER)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_ECC_ER);
+	if (event & TGEC_IMASK_RX_JAB_FRM)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_JAB_FRM);
+	if (event & TGEC_IMASK_RX_OVRSZ_FRM)
+		p_tgec->f_exception(p_tgec->h_app,
+				    FM_MAC_EX_10G_RX_OVRSZ_FRM);
+	if (event & TGEC_IMASK_RX_RUNT_FRM)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_RUNT_FRM);
+	if (event & TGEC_IMASK_RX_FRAG_FRM)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_FRAG_FRM);
+	if (event & TGEC_IMASK_RX_LEN_ER)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_LEN_ER);
+	if (event & TGEC_IMASK_RX_CRC_ER)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_CRC_ER);
+	if (event & TGEC_IMASK_RX_ALIGN_ER)
+		p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_ALIGN_ER);
+}
+
+static void free_init_resources(struct tgec_t *p_tgec)
+{
+	fm_unregister_intr(p_tgec->fm_mac_ctrl_drv.h_fm,
+			   FM_MOD_MAC, p_tgec->mac_id, FM_INTR_TYPE_ERR);
+
+	/* release the driver's group hash table */
+	free_hash_table(p_tgec->p_multicast_addr_hash);
+	p_tgec->p_multicast_addr_hash = NULL;
+
+	/* release the driver's individual hash table */
+	free_hash_table(p_tgec->p_unicast_addr_hash);
+	p_tgec->p_unicast_addr_hash = NULL;
+}
+
+/* Checks if p_tgec driver parameters were initialized
+ * returns 0 if success else returns error
+ */
+static int is_init_done(struct tgec_cfg *p_tgec_drv_parameters)
+{
+	if (!p_tgec_drv_parameters)
+		return 0;
+	return -ENOSYS;
+}
+
+/* TGEC MAC API routines */
+static int tgec_enable(void *h_tgec, enum comm_mode mode)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	fman_tgec_enable(p_tgec->p_mem_map,
+			 (mode & COMM_MODE_RX),
+			 (mode & COMM_MODE_TX));
+
+	return 0;
+}
+
+static int tgec_disable(void *h_tgec, enum comm_mode mode)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	fman_tgec_disable(p_tgec->p_mem_map,
+			  (mode & COMM_MODE_RX),
+			  (mode & COMM_MODE_TX));
+
+	return 0;
+}
+
+static int tgec_set_promiscuous(void *h_tgec, bool new_val)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	fman_tgec_set_promiscuous(p_tgec->p_mem_map, new_val);
+
+	return 0;
+}
+
+/* tgec configs modification functions */
+
+static int tgec_cfg_lb(void *h_tgec, bool new_val)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_tgec->p_tgec_drv_param->loopback_enable = new_val;
+
+	return 0;
+}
+
+static int tgec_cfg_max_frame_len(void *h_tgec, uint16_t new_val)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_tgec->p_tgec_drv_param->max_frame_length = new_val;
+
+	return 0;
+}
+
+static int tgec_cfg_len_check(void *h_tgec, bool __maybe_unused new_val)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_tgec->p_tgec_drv_param->no_length_check_enable = !new_val;
+
+	return 0;
+}
+
+static int tgec_cfg_exception(void *h_tgec,
+			      enum fm_mac_exceptions exception, bool enable)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	uint32_t bit_mask = 0;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	bit_mask = get_exception_flag(exception);
+	if (bit_mask) {
+		if (enable)
+			p_tgec->exceptions |= bit_mask;
+		else
+			p_tgec->exceptions &= ~bit_mask;
+	} else {
+		pr_err("Undefined exception\n");
+		return -EDOM;
+	}
+	return 0;
+}
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+
+static int tgec_cfg_skip_fman11_wa(void *h_tgec)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_tgec->p_tgec_drv_param->skip_fman11_workaround = true;
+
+	return 0;
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* tgec run time api functions */
+
+/* backward compatibility. will be removed in the future. */
+static int tgec_tx_mac_pause(void *h_tgec, uint16_t pause_time)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	fman_tgec_set_tx_pause_frames(p_tgec->p_mem_map, pause_time);
+
+	return 0;
+}
+
+static int tgec_set_tx_pause_frames(void *h_tgec,
+				    uint8_t __maybe_unused priority,
+				    uint16_t pause_time,
+				    uint16_t __maybe_unused thresh_time)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	fman_tgec_set_tx_pause_frames(p_tgec->p_mem_map, pause_time);
+
+	return 0;
+}
+
+static int tgec_rx_ignore_mac_pause(void *h_tgec, bool en)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	fman_tgec_set_rx_ignore_pause_frames(p_tgec->p_mem_map, en);
+
+	return 0;
+}
+
+static int tgec_modify_mac_address(void *h_tgec, enet_addr_t
+				       *p_enet_addr)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	p_tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr);
+	fman_tgec_set_mac_address(p_tgec->p_mem_map, (uint8_t *)(*p_enet_addr));
+
+	return 0;
+}
+
+static int tgec_add_hash_mac_address(void *h_tgec, enet_addr_t
+					 *p_eth_addr)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	struct eth_hash_entry_t *p_hash_entry;
+	uint32_t crc;
+	uint32_t hash;
+	uint64_t eth_addr;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+	if (!(eth_addr & GROUP_ADDRESS)) {
+		/* Unicast addresses not supported in hash */
+		pr_err("Unicast Address\n");
+		return -ENOSYS;
+	}
+	/* CRC calculation */
+	crc = get_mac_addr_hash_code(eth_addr);
+
+	/* Take 9 MSB bits */
+	hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK;
+
+	/* Create element to be added to the driver hash table */
+	p_hash_entry = kmalloc(sizeof(*p_hash_entry), GFP_KERNEL);
+	if (!p_hash_entry)
+		return -ENOMEM;
+	p_hash_entry->addr = eth_addr;
+	INIT_LIST_HEAD(&p_hash_entry->node);
+
+	list_add_tail(&p_hash_entry->node,
+		      &p_tgec->p_multicast_addr_hash->p_lsts[hash]);
+	fman_tgec_set_hash_table(p_tgec->p_mem_map,
+				 (hash | TGEC_HASH_MCAST_EN));
+
+	return 0;
+}
+
+static int tgec_del_hash_mac_address(void *h_tgec, enet_addr_t
+					 *p_eth_addr)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	struct eth_hash_entry_t *p_hash_entry = NULL;
+	struct list_head *p_pos;
+	uint32_t crc;
+	uint32_t hash;
+	uint64_t eth_addr;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	eth_addr = ((*(uint64_t *)p_eth_addr) >> 16);
+
+	/* CRC calculation */
+	crc = get_mac_addr_hash_code(eth_addr);
+	/* Take 9 MSB bits */
+	hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK;
+
+	list_for_each(p_pos, &p_tgec->p_multicast_addr_hash->p_lsts[hash]) {
+		p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+		if (p_hash_entry->addr == eth_addr) {
+			list_del_init(&p_hash_entry->node);
+			kfree(p_hash_entry);
+			break;
+		}
+	}
+	if (list_empty(&p_tgec->p_multicast_addr_hash->p_lsts[hash]))
+		fman_tgec_set_hash_table(p_tgec->p_mem_map,
+					 (hash & ~TGEC_HASH_MCAST_EN));
+
+	return 0;
+}
+
+static int tgec_get_id(void *h_tgec,
+		       uint32_t __maybe_unused *mac_id)
+{
+	struct tgec_t __maybe_unused *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	pr_warn("tgec_get_id not supported\n");
+	return -ENOSYS;
+}
+
+static int tgec_get_version(void *h_tgec, uint32_t *mac_version)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	*mac_version = fman_tgec_get_revision(p_tgec->p_mem_map);
+
+	return 0;
+}
+
+static int tgec_set_excpetion(void *h_tgec,
+			      enum fm_mac_exceptions exception,
+				  bool enable)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	uint32_t bit_mask = 0;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return ret;
+
+	bit_mask = get_exception_flag(exception);
+	if (bit_mask) {
+		if (enable)
+			p_tgec->exceptions |= bit_mask;
+		else
+			p_tgec->exceptions &= ~bit_mask;
+	} else {
+		pr_err("Undefined exception\n");
+		return -EDOM;
+	}
+	if (enable)
+		fman_tgec_enable_interrupt(p_tgec->p_mem_map, bit_mask);
+	else
+		fman_tgec_disable_interrupt(p_tgec->p_mem_map, bit_mask);
+
+	return 0;
+}
+
+static uint16_t tgec_get_max_frame_length(void *h_tgec)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	int ret;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (ret)
+		return 0;
+
+	return fman_tgec_get_max_frame_len(p_tgec->p_mem_map);
+}
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+static int tgec_tx_ecc_workaround(struct tgec_t *p_tgec)
+{
+	int err;
+
+	pr_info("Applying 10G TX ECC workaround (10GMAC-A004) ... ");
+
+	/* enable and set promiscuous */
+	fman_tgec_enable(p_tgec->p_mem_map, true, true);
+	fman_tgec_set_promiscuous(p_tgec->p_mem_map, true);
+	err =
+	    fm_10g_tx_ecc_workaround(p_tgec->fm_mac_ctrl_drv.h_fm,
+				     p_tgec->mac_id);
+	/* disable */
+	fman_tgec_set_promiscuous(p_tgec->p_mem_map, false);
+	fman_tgec_enable(p_tgec->p_mem_map, false, false);
+	fman_tgec_ack_event(p_tgec->p_mem_map, 0xffffffff);
+
+	if (err)
+		pr_err("FAILED!\n");
+	else
+		pr_info("done.\n");
+
+	return err;
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* FM Init&Free API */
+
+static int tgec_init(void *h_tgec)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+	struct tgec_cfg *p_tgec_drv_param;
+	enet_addr_t eth_addr;
+	int err, ret, ret_err;
+
+	ret = is_init_done(p_tgec->p_tgec_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	fm_get_revision(p_tgec->fm_mac_ctrl_drv.h_fm,
+			&p_tgec->fm_mac_ctrl_drv.fm_rev_info);
+	ret_err = check_init_parameters(p_tgec);
+	if (ret_err)
+		return ret_err;
+
+	p_tgec_drv_param = p_tgec->p_tgec_drv_param;
+
+	MAKE_ENET_ADDR_FROM_UINT64(p_tgec->addr, eth_addr);
+	fman_tgec_set_mac_address(p_tgec->p_mem_map, (uint8_t *)eth_addr);
+
+	/* interrupts */
+#ifdef FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005
+	{
+		if (p_tgec->fm_mac_ctrl_drv.fm_rev_info.major_rev <= 2)
+			p_tgec->exceptions &=
+			    ~(TGEC_IMASK_REM_FAULT | TGEC_IMASK_LOC_FAULT);
+	}
+#endif /* FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 */
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+	if (!p_tgec->p_tgec_drv_param->skip_fman11_workaround) {
+		err = tgec_tx_ecc_workaround(p_tgec);
+		if (err != 0) {
+			free_init_resources(p_tgec);
+			pr_warn("tgec_tx_ecc_workaround failed\n");
+		}
+	}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+	err =
+	    fman_tgec_init(p_tgec->p_mem_map, p_tgec_drv_param,
+			   p_tgec->exceptions);
+	if (err) {
+		free_init_resources(p_tgec);
+		pr_err("TGEC version doesn't support this i/f mode\n");
+		return err;
+	}
+
+	/* Max Frame Length */
+	err = fm_set_mac_max_frame(p_tgec->fm_mac_ctrl_drv.h_fm,
+				   FM_MAC_10G,
+				   p_tgec->fm_mac_ctrl_drv.mac_id,
+				   p_tgec_drv_param->max_frame_length);
+	if (err) {
+		pr_err("Setting max frame length FAILED\n");
+		free_init_resources(p_tgec);
+		return -EINVAL;
+	}
+
+#ifdef FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007
+	if (p_tgec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+		fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(p_tgec->
+								     p_mem_map);
+#endif /* FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 */
+
+	p_tgec->p_multicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+	if (!p_tgec->p_multicast_addr_hash) {
+		free_init_resources(p_tgec);
+		pr_err("allocation hash table is FAILED\n");
+		return -ENOMEM;
+	}
+
+	p_tgec->p_unicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+	if (!p_tgec->p_unicast_addr_hash) {
+		free_init_resources(p_tgec);
+		pr_err("allocation hash table is FAILED\n");
+		return -ENOMEM;
+	}
+
+	fm_register_intr(p_tgec->fm_mac_ctrl_drv.h_fm,
+			 FM_MOD_MAC,
+			 p_tgec->mac_id,
+			 FM_INTR_TYPE_ERR, tgec_err_exception, p_tgec);
+
+	kfree(p_tgec_drv_param);
+	p_tgec->p_tgec_drv_param = NULL;
+
+	return 0;
+}
+
+static int tgec_free(void *h_tgec)
+{
+	struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+
+	free_init_resources(p_tgec);
+
+	if (p_tgec->p_tgec_drv_param)
+		p_tgec->p_tgec_drv_param = NULL;
+
+	kfree(p_tgec->p_tgec_drv_param);
+	kfree(p_tgec);
+
+	return 0;
+}
+
+static void init_fm_mac_ctrl_drv(struct fm_mac_ctrl_drv_t *
+					  p_fm_mac_ctrl_drv)
+{
+	p_fm_mac_ctrl_drv->f_fm_mac_init = tgec_init;
+	p_fm_mac_ctrl_drv->f_fm_mac_free = tgec_free;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_lb = tgec_cfg_lb;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len = tgec_cfg_max_frame_len;
+
+	/* tgec always works with pad+crc */
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc = NULL;
+	/* half-duplex is not supported in xgec */
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check = tgec_cfg_len_check;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception = tgec_cfg_exception;
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init = NULL;
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+	p_fm_mac_ctrl_drv->f_fm_mac_cfg_skip_fman11_wa =
+	    tgec_cfg_skip_fman11_wa;
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+	p_fm_mac_ctrl_drv->f_fm_mac_set_exception = tgec_set_excpetion;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous = tgec_set_promiscuous;
+	p_fm_mac_ctrl_drv->f_fm_mac_adjust_link = NULL;
+	p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg = NULL;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_enable = tgec_enable;
+	p_fm_mac_ctrl_drv->f_fm_mac_disable = tgec_disable;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames =
+	tgec_tx_mac_pause;
+	p_fm_mac_ctrl_drv->f_fm_mac_set_tx_pause_frames =
+	    tgec_set_tx_pause_frames;
+	p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames =
+	    tgec_rx_ignore_mac_pause;
+
+	p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr = tgec_modify_mac_address;
+	p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr =
+	    tgec_add_hash_mac_address;
+	p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr =
+	    tgec_del_hash_mac_address;
+	p_fm_mac_ctrl_drv->f_fm_mac_get_id = tgec_get_id;
+	p_fm_mac_ctrl_drv->f_fm_mac_get_version = tgec_get_version;
+	p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length =
+	    tgec_get_max_frame_length;
+}
+
+/*  tgec config  main entry */
+
+void *tgec_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+	struct tgec_t *p_tgec;
+	struct tgec_cfg *p_tgec_drv_param;
+	uintptr_t base_addr;
+
+	base_addr = p_fm_mac_param->base_addr;
+	/* allocate memory for the UCC GETH data structure. */
+	p_tgec = kzalloc(sizeof(*p_tgec), GFP_KERNEL);
+	if (!p_tgec)
+		return NULL;
+
+	init_fm_mac_ctrl_drv(&p_tgec->fm_mac_ctrl_drv);
+
+	/* allocate memory for the 10G MAC driver parameters data structure. */
+	p_tgec_drv_param = kzalloc(sizeof(*p_tgec_drv_param), GFP_KERNEL);
+	if (!p_tgec_drv_param) {
+		tgec_free(p_tgec);
+		return NULL;
+	}
+
+	/* Plant parameter structure pointer */
+	p_tgec->p_tgec_drv_param = p_tgec_drv_param;
+
+	fman_tgec_defconfig(p_tgec_drv_param);
+
+	p_tgec->p_mem_map = (struct tgec_regs __iomem *)UINT_TO_PTR(base_addr);
+	p_tgec->p_mii_mem_map = (struct tgec_mii_access_mem_map_t *)
+		UINT_TO_PTR(base_addr + TGEC_TO_MII_OFFSET);
+	p_tgec->addr = ENET_ADDR_TO_UINT64(p_fm_mac_param->addr);
+	p_tgec->enet_mode = p_fm_mac_param->enet_mode;
+	p_tgec->mac_id = p_fm_mac_param->mac_id;
+	p_tgec->exceptions = DEFAULT_exceptions;
+	p_tgec->f_exception = p_fm_mac_param->f_exception;
+	p_tgec->f_event = p_fm_mac_param->f_event;
+	p_tgec->h_app = p_fm_mac_param->h_app;
+
+	return p_tgec;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/tgec.h b/drivers/net/ethernet/freescale/fman/mac/tgec.h
new file mode 100644
index 0000000..f839250
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/tgec.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* TGEC MAC ... */
+#ifndef __TGEC_H
+#define __TGEC_H
+
+#include "service.h"
+#include "enet_ext.h"
+
+#include "tgec_mii_acc.h"
+#include "fm_mac.h"
+
+#define DEFAULT_exceptions\
+	((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT     |\
+		TGEC_IMASK_REM_FAULT           |\
+		TGEC_IMASK_LOC_FAULT           |\
+		TGEC_IMASK_TX_ECC_ER           |\
+		TGEC_IMASK_TX_FIFO_UNFL        |\
+		TGEC_IMASK_TX_FIFO_OVFL        |\
+		TGEC_IMASK_TX_ER               |\
+		TGEC_IMASK_RX_FIFO_OVFL        |\
+		TGEC_IMASK_RX_ECC_ER           |\
+		TGEC_IMASK_RX_JAB_FRM          |\
+		TGEC_IMASK_RX_OVRSZ_FRM        |\
+		TGEC_IMASK_RX_RUNT_FRM         |\
+		TGEC_IMASK_RX_FRAG_FRM         |\
+		TGEC_IMASK_RX_CRC_ER           |\
+		TGEC_IMASK_RX_ALIGN_ER))
+
+#define MAX_PACKET_ALIGNMENT        31
+#define MAX_INTER_PACKET_GAP        0x7f
+#define MAX_INTER_PALTERNATE_BEB    0x0f
+#define MAX_RETRANSMISSION          0x0f
+#define MAX_COLLISION_WINDOW        0x03ff
+
+/* number of pattern match registers (entries) */
+#define TGEC_NUM_OF_PADDRS          1
+
+/* Group address bit indication */
+#define GROUP_ADDRESS               0x0000010000000000LL
+
+#define HASH_TABLE_SIZE             512	/* Hash table size (= 32 bits*8 regs)*/
+
+/* Offset from the MEM map to the MDIO mem map */
+#define TGEC_TO_MII_OFFSET          0x1030
+
+struct tgec_t {
+	/* Upper Mac control block */
+	struct fm_mac_ctrl_drv_t fm_mac_ctrl_drv;
+	/* Handle to the upper layer application  */
+	void *h_app;
+	/* pointer to 10G memory mapped registers. */
+	struct tgec_regs __iomem *p_mem_map;
+	/* pointer to MII memory mapped registers. */
+	struct tgec_mii_access_mem_map_t *p_mii_mem_map;
+	/* MAC address of device; */
+	uint64_t addr;
+	/* Ethernet physical interface  */
+	enum e_enet_mode enet_mode;
+	fm_mac_exception_cb *f_exception;
+	fm_mac_exception_cb *f_event;
+	/* Whether a particular individual address recognition
+	 * register is being used
+	 */
+	bool ind_addr_reg_used[TGEC_NUM_OF_PADDRS];
+	/* MAC address for particular individual address
+	 * recognition register
+	 */
+	uint64_t paddr[TGEC_NUM_OF_PADDRS];
+	/* Number of individual addresses in registers for this station. */
+	uint8_t num_of_ind_addr_in_regs;
+	/* pointer to driver's global address hash table  */
+	struct eth_hash_t *p_multicast_addr_hash;
+	/* pointer to driver's individual address hash table  */
+	struct eth_hash_t *p_unicast_addr_hash;
+	bool debug_mode;
+	uint8_t mac_id;
+	uint32_t exceptions;
+	struct tgec_cfg *p_tgec_drv_param;
+};
+
+#endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h b/drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h
new file mode 100644
index 0000000..4ea9b35
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TGEC_MII_ACC_H
+#define __TGEC_MII_ACC_H
+
+#include "service.h"
+
+/* MII  Management Command Register */
+#define MIIMCOM_READ_POST_INCREMENT 0x00004000
+#define MIIMCOM_READ_CYCLE          0x00008000
+#define MIIMCOM_SCAN_CYCLE          0x00000800
+#define MIIMCOM_PREAMBLE_DISABLE    0x00000400
+
+#define MIIMCOM_MDIO_HOLD_1_REG_CLK 0
+#define MIIMCOM_MDIO_HOLD_2_REG_CLK 1
+#define MIIMCOM_MDIO_HOLD_3_REG_CLK 2
+#define MIIMCOM_MDIO_HOLD_4_REG_CLK 3
+
+#define MIIMCOM_DIV_MASK            0x0000ff00
+#define MIIMCOM_DIV_SHIFT           8
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY                0x00000001
+#define MIIMIND_READ_ERROR          0x00000002
+
+#define MIIDATA_BUSY                0x80000000
+
+/* MII Configuration Control Memory Map Registers     */
+struct tgec_mii_access_mem_map_t {
+	uint32_t mdio_cfg_status;	/* 0x030  */
+	uint32_t mdio_command;		/* 0x034  */
+	uint32_t mdio_data;		/* 0x038 */
+	uint32_t mdio_regaddr;		/* 0x03c */
+} __attribute__((__packed__));
+
+#endif /* __TGEC_MII_ACC_H */
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 10/12] fsl/fman: Add FMan SP support
  2015-05-07 13:05               ` [RFC,v3 09/12] fsl/fman: Add FMan MAC support Madalin Bucur
@ 2015-05-07 13:05                 ` Madalin Bucur
  2015-05-07 13:05                   ` [RFC,v3 11/12] fsl/fman: Add FMan Port Support Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

Add Storage Profiles support.
The Storage Profiles contain parameters that are used by the FMan in
order to store frames being received on the Rx ports, or to
determine the parameters that affect writing the Internal Context
in the frame margin on Tx.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 drivers/net/ethernet/freescale/fman/Makefile       |   2 +
 drivers/net/ethernet/freescale/fman/fm_sp_common.h | 104 ++++++
 drivers/net/ethernet/freescale/fman/sp/Makefile    |   3 +
 drivers/net/ethernet/freescale/fman/sp/fm_sp.c     | 398 +++++++++++++++++++++
 4 files changed, 507 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/fman/fm_sp_common.h
 create mode 100644 drivers/net/ethernet/freescale/fman/sp/Makefile
 create mode 100644 drivers/net/ethernet/freescale/fman/sp/fm_sp.c

diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index f61d3a6..c6c3e24 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -8,3 +8,5 @@ fsl_fman-objs	:= fman.o fm_muram.o fm.o fm_drv.o
 
 obj-y	+= port/
 obj-y	+= mac/
+obj-y	+= sp/
+
diff --git a/drivers/net/ethernet/freescale/fman/fm_sp_common.h b/drivers/net/ethernet/freescale/fman/fm_sp_common.h
new file mode 100644
index 0000000..a99d795
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm_sp_common.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM SP  ... */
+#ifndef __FM_SP_COMMON_H
+#define __FM_SP_COMMON_H
+
+#include "service.h"
+#include "fm_ext.h"
+#include "fsl_fman.h"
+
+/* defaults */
+#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTENT_PRIV_DATA_SIZE      0
+#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTENT_PRIV_PASS_PRS_RESULT     false
+#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTEXT_PASS_TIME_STAMP     false
+#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTEXT_DATA_ALIGN         64
+
+/* structure for defining internal context copying */
+struct fm_sp_int_context_data_copy_t {
+	/* < Offset in External buffer to which internal
+	 *  context is copied to (Rx) or taken from (Tx, Op).
+	 */
+	uint16_t ext_buf_offset;
+	/* Offset within internal context to copy from
+	 * (Rx) or to copy to (Tx, Op).
+	 */
+	uint8_t int_context_offset;
+	/* Internal offset size to be copied */
+	uint16_t size;
+};
+
+/*  struct for defining external buffer margins */
+struct fm_sp_buf_margins_t {
+	/* Number of bytes to be left at the beginning
+	 * of the external buffer (must be divisible by 16)
+	 */
+	uint16_t start_margins;
+	/* number of bytes to be left at the end
+	 * of the external buffer(must be divisible by 16)
+	 */
+	uint16_t end_margins;
+};
+
+struct fm_sp_buffer_offsets_t {
+	uint32_t data_offset;
+	uint32_t prs_result_offset;
+	uint32_t time_stamp_offset;
+	uint32_t hash_result_offset;
+};
+
+int fm_sp_build_buffer_structure(struct fm_sp_int_context_data_copy_t
+				 *p_fm_port_int_context_data_copy,
+				 struct fm_buffer_prefix_content_t
+				 *p_buffer_prefix_content,
+				 struct fm_sp_buf_margins_t
+				 *p_fm_port_buf_margins,
+				 struct fm_sp_buffer_offsets_t
+				 *p_fm_port_buffer_offsets,
+				 uint8_t *internal_buf_offset);
+
+int fm_sp_check_int_context_params(struct fm_sp_int_context_data_copy_t *
+				   p_fm_sp_int_context_data_copy);
+int fm_sp_check_buf_pools_params(struct fm_ext_pools_t *p_fm_ext_pools,
+				 struct fm_backup_bm_pools_t
+				 *p_fm_backup_bm_pools,
+				 struct fm_buf_pool_depletion_t
+				 *p_fm_buf_pool_depletion,
+				 uint32_t max_num_of_ext_pools,
+				 uint32_t bm_max_num_of_pools);
+int fm_sp_check_buf_margins(struct fm_sp_buf_margins_t *p_fm_sp_buf_margins);
+void fm_sp_set_buf_pools_in_asc_order_of_buf_sizes(struct fm_ext_pools_t
+						   *p_fm_ext_pools,
+						   uint8_t *ordered_array,
+						   uint16_t *sizes_array);
+#endif /* __FM_SP_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/sp/Makefile b/drivers/net/ethernet/freescale/fman/sp/Makefile
new file mode 100644
index 0000000..545e686
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/sp/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_FSL_FMAN)	+= fsl_fman_sp.o
+
+fsl_fman_sp-objs	:= fm_sp.o
diff --git a/drivers/net/ethernet/freescale/fman/sp/fm_sp.c b/drivers/net/ethernet/freescale/fman/sp/fm_sp.c
new file mode 100644
index 0000000..85b7a47
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/sp/fm_sp.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM PCD Storage profile  ... */
+
+#include "service.h"
+#include "net_ext.h"
+
+#include "fm_sp_common.h"
+#include "fm_common.h"
+#include "fsl_fman_sp.h"
+
+#include <linux/string.h>
+
+/* Inter-module API routines */
+
+void fm_sp_set_buf_pools_in_asc_order_of_buf_sizes(struct fm_ext_pools_t
+						   *p_fm_ext_pools,
+						   uint8_t *ordered_array,
+						   uint16_t *sizes_array)
+{
+	uint16_t buf_size = 0;
+	int i = 0, j = 0, k = 0;
+
+	/* First we copy the external buffers pools information
+	 * to an ordered local array
+	 */
+	for (i = 0; i < p_fm_ext_pools->num_of_pools_used; i++) {
+		/* get pool size */
+		buf_size = p_fm_ext_pools->ext_buf_pool[i].size;
+
+		/* keep sizes in an array according to poolId
+		 * for direct access
+		 */
+		sizes_array[p_fm_ext_pools->ext_buf_pool[i].id] = buf_size;
+
+		/* save poolId in an ordered array according to size */
+		for (j = 0; j <= i; j++) {
+			/* this is the next free place in the array */
+			if (j == i)
+				ordered_array[i] =
+				    p_fm_ext_pools->ext_buf_pool[i].id;
+			else {
+				/* find the right place for this poolId */
+				if (buf_size < sizes_array[ordered_array[j]]) {
+					/* move the pool_ids one place ahead
+					 * to make room for this poolId
+					 */
+					for (k = i; k > j; k--)
+						ordered_array[k] =
+						    ordered_array[k - 1];
+
+					/* now k==j, this is the place for
+					 * the new size
+					 */
+					ordered_array[k] =
+					    p_fm_ext_pools->ext_buf_pool[i].id;
+					break;
+				}
+			}
+		}
+	}
+}
+
+int fm_sp_check_buf_pools_params(struct fm_ext_pools_t *p_fm_ext_pools,
+				 struct fm_backup_bm_pools_t
+				 *p_fm_backup_bm_pools,
+				 struct fm_buf_pool_depletion_t
+				 *p_fm_buf_pool_depletion,
+				 uint32_t max_num_of_ext_pools,
+				 uint32_t bm_max_num_of_pools)
+{
+	int i = 0, j = 0;
+	bool found;
+	uint8_t count = 0;
+
+	if (p_fm_ext_pools) {
+		if (p_fm_ext_pools->num_of_pools_used > max_num_of_ext_pools) {
+			pr_err("num_of_pools_used can't be larger than %d\n",
+			       max_num_of_ext_pools);
+			return -EDOM;
+		}
+		for (i = 0; i < p_fm_ext_pools->num_of_pools_used; i++) {
+			if (p_fm_ext_pools->ext_buf_pool[i].id >=
+			    bm_max_num_of_pools) {
+				pr_err("ext_buf_pools.ext_buf_pool[%d].id can't be larger than %d\n",
+				       i, bm_max_num_of_pools);
+				return -EDOM;
+			}
+			if (!p_fm_ext_pools->ext_buf_pool[i].size) {
+				pr_err("ext_buf_pools.ext_buf_pool[%d].size is 0\n",
+				       i);
+				return -EDOM;
+			}
+		}
+	}
+	if (!p_fm_ext_pools && (p_fm_backup_bm_pools ||
+				p_fm_buf_pool_depletion)) {
+		pr_err("backupBmPools ot buf_pool_depletion can not be defined without external pools\n");
+		return -EDOM;
+	}
+	/* backup BM pools indication is valid only for some chip derivatives
+	 * (limited by the config routine)
+	 */
+	if (p_fm_backup_bm_pools) {
+		if (p_fm_backup_bm_pools->num_of_backup_pools >=
+		    p_fm_ext_pools->num_of_pools_used) {
+			pr_err("p_backup_bm_pools must be smaller than ext_buf_pools.num_of_pools_used\n");
+			return -EDOM;
+		}
+		found = false;
+		for (i = 0; i < p_fm_backup_bm_pools->
+		     num_of_backup_pools; i++) {
+			for (j = 0; j < p_fm_ext_pools->
+			     num_of_pools_used; j++) {
+				if (p_fm_backup_bm_pools->pool_ids[i] ==
+				    p_fm_ext_pools->ext_buf_pool[j].id) {
+					found = true;
+					break;
+				}
+			}
+			if (!found) {
+				pr_err("All p_backup_bm_pools.pool_ids must be included in ext_buf_pools.ext_buf_pool[n].id\n");
+				return -EDOM;
+			}
+			found = false;
+		}
+	}
+
+	/* up to ext_buf_pools.num_of_pools_used pools may be defined */
+	if (p_fm_buf_pool_depletion && p_fm_buf_pool_depletion->
+	    pools_grp_mode_enable) {
+		if ((p_fm_buf_pool_depletion->num_of_pools >
+		     p_fm_ext_pools->num_of_pools_used)) {
+			pr_err("buf_pool_depletion.num_of_pools can't be larger than %d and can't be larger than num_of_pools_used\n",
+			       max_num_of_ext_pools);
+			return -EDOM;
+		}
+		if (!p_fm_buf_pool_depletion->num_of_pools) {
+			pr_err("buf_pool_depletion.num_of_pools_to_consider can not be 0 when pools_grp_mode_enable=true\n");
+			return -EDOM;
+		}
+		found = false;
+		count = 0;
+		/* for each pool that is in pools_to_consider, check if it
+		 * is defined in ext_buf_pool
+		 */
+		for (i = 0; i < bm_max_num_of_pools; i++) {
+			if (p_fm_buf_pool_depletion->pools_to_consider[i]) {
+				for (j = 0; j < p_fm_ext_pools->
+				     num_of_pools_used; j++) {
+					if (i == p_fm_ext_pools->
+					    ext_buf_pool[j].id) {
+						found = true;
+						count++;
+						break;
+					}
+				}
+				if (!found) {
+					pr_err("Pools selected for depletion are not used.\n");
+					return -ENOSYS;
+				}
+				found = false;
+			}
+		}
+		/* check that the number of pools that we have checked is
+		 * equal to the number announced by the user
+		 */
+		if (count != p_fm_buf_pool_depletion->num_of_pools) {
+			pr_err("buf_pool_depletion.num_of_pools is larger than the number of pools defined.\n");
+			return -EDOM;
+		}
+	}
+
+	if (p_fm_buf_pool_depletion && p_fm_buf_pool_depletion->
+	    single_pool_mode_enable) {
+		/* calculate vector for number of pools depletion */
+		found = false;
+		count = 0;
+		for (i = 0; i < bm_max_num_of_pools; i++) {
+			if (p_fm_buf_pool_depletion->
+			    pools_to_consider_for_single_mode[i]) {
+				for (j = 0; j < p_fm_ext_pools->
+				     num_of_pools_used;
+				     j++) {
+					if (i == p_fm_ext_pools->
+					    ext_buf_pool[j].id) {
+						found = true;
+						count++;
+						break;
+					}
+				}
+				if (!found) {
+					pr_err("Pools selected for depletion are not used.\n");
+					return -ENOSYS;
+				}
+				found = false;
+			}
+		}
+		if (!count) {
+			pr_err("No pools defined for single buffer mode pool depletion.\n");
+			return -EDOM;
+		}
+	}
+
+	return 0;
+}
+
+int fm_sp_check_int_context_params(struct fm_sp_int_context_data_copy_t *
+				  p_fm_sp_int_context_data_copy)
+{
+	/* Check that divisible by 16 and not larger than 240 */
+	if (p_fm_sp_int_context_data_copy->int_context_offset >
+	    MAX_INT_OFFSET) {
+		pr_err("int_context.int_context_offset can't be larger than %d\n",
+		       MAX_INT_OFFSET);
+		return -EDOM;
+	}
+	if (p_fm_sp_int_context_data_copy->int_context_offset %
+	      OFFSET_UNITS) {
+		pr_err("int_context.int_context_offset has to be divisible by %d\n",
+		       OFFSET_UNITS);
+		return -EDOM;
+
+	/* check that ic size+ic internal offset, does not exceed
+	 * ic block size
+	 */
+	}
+	if (p_fm_sp_int_context_data_copy->size +
+	      p_fm_sp_int_context_data_copy->int_context_offset >
+	      MAX_IC_SIZE) {
+		pr_err("int_context.size + int_context.int_context_offset has to be smaller than %d\n",
+		       MAX_IC_SIZE);
+		return -EDOM;
+	/* Check that divisible by 16 and not larger than 256 */
+	}
+	if (p_fm_sp_int_context_data_copy->size % OFFSET_UNITS) {
+		pr_err("int_context.size  has to be divisible by %d\n",
+		       OFFSET_UNITS);
+		return -EDOM;
+
+	/* Check that divisible by 16 and not larger than 4K */
+	}
+	if (p_fm_sp_int_context_data_copy->ext_buf_offset > MAX_EXT_OFFSET) {
+		pr_err("int_context.ext_buf_offset can't be larger than %d\n",
+		       MAX_EXT_OFFSET);
+		return -EDOM;
+	}
+	if (p_fm_sp_int_context_data_copy->ext_buf_offset % OFFSET_UNITS) {
+		pr_err("int_context.ext_buf_offset has to be divisible by %d\n",
+		       OFFSET_UNITS);
+		return -EDOM;
+	}
+	return 0;
+}
+
+int fm_sp_check_buf_margins(struct fm_sp_buf_margins_t
+				*p_fm_sp_buf_margins)
+{
+	/* Check the margin definition */
+	if (p_fm_sp_buf_margins->start_margins > MAX_EXT_BUFFER_OFFSET) {
+		pr_err("buf_margins.start_margins can't be larger than %d\n",
+		       MAX_EXT_BUFFER_OFFSET);
+		return -EDOM;
+	}
+	if (p_fm_sp_buf_margins->end_margins > MAX_EXT_BUFFER_OFFSET) {
+		pr_err("buf_margins.end_margins can't be larger than %d\n",
+		       MAX_EXT_BUFFER_OFFSET);
+		return -EDOM;
+	}
+	return 0;
+}
+
+int fm_sp_build_buffer_structure(struct fm_sp_int_context_data_copy_t *
+				 p_fm_sp_int_context_data_copy,
+				 struct fm_buffer_prefix_content_t *
+				 p_buffer_prefix_content,
+				 struct fm_sp_buf_margins_t
+				 *p_fm_sp_buf_margins,
+				 struct fm_sp_buffer_offsets_t
+				 *p_fm_sp_buffer_offsets,
+				 uint8_t *internal_buf_offset)
+{
+	uint32_t tmp;
+
+	/* Align start of internal context data to 16 byte */
+	p_fm_sp_int_context_data_copy->ext_buf_offset = (uint16_t)
+		((p_buffer_prefix_content->priv_data_size &
+			(OFFSET_UNITS - 1)) ?
+		((p_buffer_prefix_content->priv_data_size + OFFSET_UNITS) &
+			~(uint16_t)(OFFSET_UNITS - 1)) :
+		p_buffer_prefix_content->priv_data_size);
+
+	/* Translate margin and int_context params to FM parameters */
+	/* Initialize with illegal value. Later we'll set legal values. */
+	p_fm_sp_buffer_offsets->prs_result_offset = (uint32_t)ILLEGAL_BASE;
+	p_fm_sp_buffer_offsets->time_stamp_offset = (uint32_t)ILLEGAL_BASE;
+	p_fm_sp_buffer_offsets->hash_result_offset = (uint32_t)ILLEGAL_BASE;
+
+	/* Internally the driver supports 4 options
+	 * 1. prsResult/timestamp/hashResult selection (in fact 8 options,
+	 * but for simplicity we'll
+	 * relate to it as 1).
+	 * 2. All IC context (from AD) not including debug.
+	 */
+
+	/* This case covers the options under 1 */
+	/* Copy size must be in 16-byte granularity. */
+	p_fm_sp_int_context_data_copy->size =
+	    (uint16_t)((p_buffer_prefix_content->
+			 pass_prs_result ? 32 : 0) +
+			((p_buffer_prefix_content->pass_time_stamp ||
+			  p_buffer_prefix_content->
+			  pass_hash_result) ? 16 : 0));
+
+	/* Align start of internal context data to 16 byte */
+	p_fm_sp_int_context_data_copy->int_context_offset =
+	    (uint8_t)(p_buffer_prefix_content->pass_prs_result ? 32 :
+		       ((p_buffer_prefix_content->pass_time_stamp ||
+			 p_buffer_prefix_content->
+			 pass_hash_result) ? 64 : 0));
+
+	if (p_buffer_prefix_content->pass_prs_result)
+		p_fm_sp_buffer_offsets->prs_result_offset =
+		    p_fm_sp_int_context_data_copy->ext_buf_offset;
+	if (p_buffer_prefix_content->pass_time_stamp)
+		p_fm_sp_buffer_offsets->time_stamp_offset =
+		    p_buffer_prefix_content->
+		    pass_prs_result ? (p_fm_sp_int_context_data_copy->
+				     ext_buf_offset +
+				     sizeof(struct fm_prs_result_t)) :
+		    p_fm_sp_int_context_data_copy->ext_buf_offset;
+	if (p_buffer_prefix_content->pass_hash_result)
+		/* If PR is not requested, whether TS is
+		 * requested or not, IC will be copied from TS
+			 */
+		p_fm_sp_buffer_offsets->hash_result_offset =
+		    p_buffer_prefix_content->
+		    pass_prs_result ? (p_fm_sp_int_context_data_copy->
+				     ext_buf_offset +
+				     sizeof(struct fm_prs_result_t) + 8) :
+				     p_fm_sp_int_context_data_copy->
+		    ext_buf_offset + 8;
+
+	if (p_fm_sp_int_context_data_copy->size)
+		p_fm_sp_buf_margins->start_margins =
+		    (uint16_t)(p_fm_sp_int_context_data_copy->ext_buf_offset +
+				p_fm_sp_int_context_data_copy->size);
+	else
+		/* No Internal Context passing, STartMargin is
+		 * immediately after private_info
+		 */
+		p_fm_sp_buf_margins->start_margins =
+		    p_buffer_prefix_content->priv_data_size;
+
+	/* align data start */
+	tmp =
+	    (uint32_t)(p_fm_sp_buf_margins->start_margins %
+			p_buffer_prefix_content->data_align);
+	if (tmp)
+		p_fm_sp_buf_margins->start_margins +=
+		    (p_buffer_prefix_content->data_align - tmp);
+	p_fm_sp_buffer_offsets->data_offset = p_fm_sp_buf_margins->
+					      start_margins;
+
+	return 0;
+}
+
+/* End of inter-module routines */
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 11/12] fsl/fman: Add FMan Port Support
  2015-05-07 13:05                 ` [RFC,v3 10/12] fsl/fman: Add FMan SP support Madalin Bucur
@ 2015-05-07 13:05                   ` Madalin Bucur
  2015-05-07 13:05                     ` [RFC,v3 12/12] fsl/fman: Add FMan MAC driver Madalin Bucur
  0 siblings, 1 reply; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

This patch adds The FMan Port configuration, initialization and
runtime control routines.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 drivers/net/ethernet/freescale/fman/Makefile       |    2 +-
 drivers/net/ethernet/freescale/fman/fm.c           |  492 ++++++-
 drivers/net/ethernet/freescale/fman/fm_common.h    |  172 ++-
 drivers/net/ethernet/freescale/fman/fm_drv.c       |  119 +-
 drivers/net/ethernet/freescale/fman/fm_drv.h       |    2 +
 drivers/net/ethernet/freescale/fman/fm_port_drv.c  |  536 +++++++
 drivers/net/ethernet/freescale/fman/inc/fm_ext.h   |   58 +
 .../net/ethernet/freescale/fman/inc/fm_port_ext.h  |  397 ++++++
 .../net/ethernet/freescale/fman/inc/fsl_fman_drv.h |   98 ++
 drivers/net/ethernet/freescale/fman/port/Makefile  |    2 +-
 drivers/net/ethernet/freescale/fman/port/fm_port.c | 1484 ++++++++++++++++++++
 drivers/net/ethernet/freescale/fman/port/fm_port.h |  711 ++++++++++
 12 files changed, 4066 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/ethernet/freescale/fman/fm_port_drv.c
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_port_ext.h
 create mode 100644 drivers/net/ethernet/freescale/fman/port/fm_port.c
 create mode 100644 drivers/net/ethernet/freescale/fman/port/fm_port.h

diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index c6c3e24..8d637e2 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -4,7 +4,7 @@ subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib \
 
 obj-y		+= fsl_fman.o
 
-fsl_fman-objs	:= fman.o fm_muram.o fm.o fm_drv.o
+fsl_fman-objs	:= fman.o fm_muram.o fm.o fm_drv.o fm_port_drv.o
 
 obj-y	+= port/
 obj-y	+= mac/
diff --git a/drivers/net/ethernet/freescale/fman/fm.c b/drivers/net/ethernet/freescale/fman/fm.c
index c8889bd..7670fef 100644
--- a/drivers/net/ethernet/freescale/fman/fm.c
+++ b/drivers/net/ethernet/freescale/fman/fm.c
@@ -459,11 +459,36 @@ static void qmi_err_event(struct fm_t *p_fm)
 
 static void dma_err_event(struct fm_t *p_fm)
 {
-	uint32_t status;
+	uint32_t status, com_id;
+	uint8_t tnum;
+	uint8_t port_id;
+	uint8_t relative_port_id;
+	uint16_t liodn;
 	struct fman_dma_regs __iomem *dma_rg = p_fm->p_fm_dma_regs;
 
 	status = fman_get_dma_err_event(dma_rg);
 
+	if (status & DMA_STATUS_BUS_ERR) {
+		com_id = fman_get_dma_com_id(dma_rg);
+		port_id = (uint8_t)(((com_id & DMA_TRANSFER_PORTID_MASK) >>
+						DMA_TRANSFER_PORTID_SHIFT));
+		HW_PORT_ID_TO_SW_PORT_ID(p_fm->p_fm_state_struct->rev_info.
+					 major_rev,
+					 relative_port_id,
+					 port_id);
+		tnum =
+		    (uint8_t)((com_id & DMA_TRANSFER_TNUM_MASK) >>
+			       DMA_TRANSFER_TNUM_SHIFT);
+		liodn = (uint16_t)(com_id & DMA_TRANSFER_LIODN_MASK);
+		ASSERT(p_fm->p_fm_state_struct->
+			    ports_types[port_id] !=
+			    FM_PORT_TYPE_DUMMY);
+		p_fm->f_bus_error(p_fm->h_app,
+				 p_fm->p_fm_state_struct->
+				 ports_types[port_id],
+				 relative_port_id,
+				 fman_get_dma_addr(dma_rg), tnum, liodn);
+	}
 	if (status & DMA_STATUS_FM_SPDAT_ECC)
 		p_fm->f_exception(p_fm->h_app, FM_EX_DMA_SINGLE_PORT_ECC);
 	if (status & DMA_STATUS_READ_ECC)
@@ -769,6 +794,467 @@ uint8_t fm_get_id(void *h_fm)
 	return p_fm->p_fm_state_struct->fm_id;
 }
 
+int fm_get_set_port_params(void *h_fm,
+			   struct fm_inter_module_port_init_params_t
+			   *p_port_params)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	int err;
+	unsigned long int_flags;
+	uint8_t port_id = p_port_params->port_id, mac_id;
+	struct fman_rg fman_rg;
+
+	fman_rg.bmi_rg = p_fm->p_fm_bmi_regs;
+	fman_rg.qmi_rg = p_fm->p_fm_qmi_regs;
+	fman_rg.fpm_rg = p_fm->p_fm_fpm_regs;
+	fman_rg.dma_rg = p_fm->p_fm_dma_regs;
+
+	ASSERT(IN_RANGE(1, port_id, 63));
+
+	spin_lock_irqsave(p_fm->spinlock, int_flags);
+
+	p_fm->p_fm_state_struct->ports_types[port_id] =
+	    p_port_params->port_type;
+
+	err =
+	    fm_set_num_of_tasks(p_fm, p_port_params->port_id,
+				&p_port_params->num_of_tasks,
+				&p_port_params->num_of_extra_tasks, true);
+	if (err) {
+		spin_unlock_irqrestore(p_fm->spinlock, int_flags);
+		return err;
+	}
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+	if (p_fm->p_fm_state_struct->rev_info.major_rev != 4)
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+		/* for transmit&O/H ports */
+		if (p_port_params->port_type != FM_PORT_TYPE_RX) {
+			uint8_t enq_th;
+			uint8_t deq_th;
+
+			/* update qmi ENQ/DEQ threshold */
+			p_fm->p_fm_state_struct->accumulated_num_of_deq_tnums +=
+			    p_port_params->deq_pipeline_depth;
+			enq_th = fman_get_qmi_enq_th(fman_rg.qmi_rg);
+			/* if enq_th is too big, we reduce it to the max value
+			 * that is still 0
+			 */
+			if (enq_th >=
+			    (p_fm->intg->qmi_max_num_of_tnums -
+			     p_fm->p_fm_state_struct->
+			     accumulated_num_of_deq_tnums)) {
+				enq_th = (uint8_t)(
+					p_fm->intg->
+						qmi_max_num_of_tnums -
+					p_fm->p_fm_state_struct->
+					accumulated_num_of_deq_tnums - 1);
+				fman_set_qmi_enq_th(fman_rg.qmi_rg, enq_th);
+			}
+
+			deq_th = fman_get_qmi_deq_th(fman_rg.qmi_rg);
+			/* if deq_th is too small, we enlarge it to the min
+			 * value that is still 0.
+			 * depTh may not be larger than 63
+			 * (p_fm->intg->qmi_max_num_of_tnums-1).
+			 */
+			if ((deq_th <=
+				p_fm->p_fm_state_struct->
+						accumulated_num_of_deq_tnums) &&
+				(deq_th <
+					p_fm->intg->
+						qmi_max_num_of_tnums - 1)) {
+					deq_th = (uint8_t)(p_fm->
+						  p_fm_state_struct->
+						  accumulated_num_of_deq_tnums
+						  + 1);
+				fman_set_qmi_deq_th(fman_rg.qmi_rg, deq_th);
+			}
+		}
+#ifdef FM_LOW_END_RESTRICTION
+	if (p_fm->p_fm_state_struct->rev_info.major_rev == 0x4) {
+		if ((port_id == 0x1) || (port_id == 0x29)) {
+			if (p_fm->p_fm_state_struct->low_end_restriction) {
+				spin_unlock_irqrestore(p_fm->spinlock,
+						       int_flags);
+				pr_err("OP#0 can't work with Tx Port1\n");
+				return -EAGAIN;
+			}
+			p_fm->p_fm_state_struct->low_end_restriction = true;
+			}
+		}
+#endif /* FM_LOW_END_RESTRICTION */
+
+	err = fm_set_size_of_fifo(p_fm,
+				  p_port_params->port_id,
+				  &p_port_params->size_of_fifo,
+				  &p_port_params->extra_size_of_fifo, true);
+	if (err) {
+		spin_unlock_irqrestore(p_fm->spinlock, int_flags);
+		return err;
+	}
+
+	err = fm_set_num_of_open_dmas(p_fm,
+				      p_port_params->port_id,
+				      &p_port_params->num_of_open_dmas,
+				      &p_port_params->num_of_extra_open_dmas,
+				      true);
+	if (err) {
+		spin_unlock_irqrestore(p_fm->spinlock,
+				       (unsigned long)int_flags);
+		return err;
+	}
+
+	fman_set_liodn_per_port(&fman_rg,
+				port_id,
+				p_port_params->liodn_base,
+				p_port_params->liodn_offset);
+
+	if (p_fm->p_fm_state_struct->rev_info.major_rev < 6)
+		fman_set_order_restoration_per_port(fman_rg.fpm_rg,
+						    port_id,
+						    !!((p_port_params->
+							 port_type ==
+							 FM_PORT_TYPE_RX)));
+
+	HW_PORT_ID_TO_SW_PORT_ID(p_fm->p_fm_state_struct->rev_info.major_rev,
+				 mac_id,
+				 port_id);
+
+	if (p_port_params->max_frame_length >=
+	    p_fm->p_fm_state_struct->mac_max_frame_lengths[mac_id]) {
+		p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id] =
+					p_port_params->max_frame_length;
+	} else {
+		pr_warn("Port max_frame_length is smaller than MAC current MTU\n");
+		spin_unlock_irqrestore(p_fm->spinlock,
+				       (unsigned long)int_flags);
+		return -EDOM;
+	}
+
+	spin_unlock_irqrestore(p_fm->spinlock, (unsigned long)int_flags);
+
+	return 0;
+}
+
+void fm_free_port_params(void *h_fm,
+			 struct fm_inter_module_port_free_params_t
+			 *p_port_params)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	unsigned long int_flags;
+	uint8_t port_id = p_port_params->port_id;
+	uint8_t num_of_tasks, num_of_dmas, mac_id;
+	uint16_t size_of_fifo;
+	struct fman_qmi_regs __iomem *qmi_rg = p_fm->p_fm_qmi_regs;
+	struct fman_bmi_regs __iomem *bmi_rg = p_fm->p_fm_bmi_regs;
+
+	ASSERT(IN_RANGE(1, port_id, 63));
+
+	spin_lock_irqsave(p_fm->spinlock, int_flags);
+
+	p_fm->p_fm_state_struct->ports_types[port_id] =
+	    FM_PORT_TYPE_DUMMY;
+
+	/* free num_of_tasks */
+	num_of_tasks = fman_get_num_of_tasks(bmi_rg, port_id);
+	ASSERT(p_fm->p_fm_state_struct->accumulated_num_of_tasks >=
+		    num_of_tasks);
+	p_fm->p_fm_state_struct->accumulated_num_of_tasks -= num_of_tasks;
+
+	/* free num_of_open_dmas */
+	num_of_dmas = fman_get_num_of_dmas(bmi_rg, port_id);
+	ASSERT(p_fm->p_fm_state_struct->accumulated_num_of_open_dmas >=
+		    num_of_dmas);
+	p_fm->p_fm_state_struct->accumulated_num_of_open_dmas -= num_of_dmas;
+
+#ifdef FM_HAS_TOTAL_DMAS
+	if (p_fm->p_fm_state_struct->rev_info.major_rev < 6) {
+		/* update total num of DMA's with committed number
+		 * of open DMAS, and max uncommitted pool.
+		 */
+		fman_set_num_of_open_dmas(bmi_rg,
+					  port_id,
+					  1,
+					  0,
+					  (uint8_t)
+					  (p_fm->p_fm_state_struct->
+					   accumulated_num_of_open_dmas +
+						     p_fm->p_fm_state_struct->
+						     extra_open_dmas_pool_size
+						     ));
+	}
+#endif /* FM_HAS_TOTAL_DMAS */
+
+	/* free size_of_fifo */
+	size_of_fifo = fman_get_size_of_fifo(bmi_rg, port_id);
+	ASSERT(p_fm->p_fm_state_struct->accumulated_fifo_size >=
+		(size_of_fifo * BMI_FIFO_UNITS));
+	p_fm->p_fm_state_struct->accumulated_fifo_size -=
+		(size_of_fifo * BMI_FIFO_UNITS);
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+	if (p_fm->p_fm_state_struct->rev_info.major_rev != 4)
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+		/* for transmit&O/H ports */
+		if (p_port_params->port_type != FM_PORT_TYPE_RX) {
+			uint8_t enq_th;
+			uint8_t deq_th;
+
+			/* update qmi ENQ/DEQ threshold */
+			p_fm->p_fm_state_struct->accumulated_num_of_deq_tnums -=
+			    p_port_params->deq_pipeline_depth;
+
+			/* p_fm->p_fm_state_struct->
+			 * accumulated_num_of_deq_tnums is now smaller,
+			 * so we can enlarge enq_th
+			 */
+			enq_th =
+			    (uint8_t)(p_fm->intg->qmi_max_num_of_tnums -
+				       p_fm->p_fm_state_struct->
+				       accumulated_num_of_deq_tnums - 1);
+
+			/* p_fm->p_fm_state_struct->
+			 * accumulated_num_of_deq_tnums is now smaller,
+			 * so we can reduce deq_th
+			 */
+			deq_th =
+			    (uint8_t)(p_fm->p_fm_state_struct->
+				       accumulated_num_of_deq_tnums + 1);
+
+			fman_set_qmi_enq_th(qmi_rg, enq_th);
+			fman_set_qmi_deq_th(qmi_rg, deq_th);
+		}
+
+	HW_PORT_ID_TO_SW_PORT_ID(p_fm->p_fm_state_struct->rev_info.major_rev,
+				 mac_id,
+				 port_id);
+
+	p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id] = 0;
+
+#ifdef FM_LOW_END_RESTRICTION
+	if (p_fm->p_fm_state_struct->rev_info.major_rev == 0x4) {
+		if ((port_id == 0x1) || (port_id == 0x29))
+			p_fm->p_fm_state_struct->low_end_restriction = false;
+	}
+#endif /* FM_LOW_END_RESTRICTION */
+	spin_unlock_irqrestore(p_fm->spinlock, int_flags);
+}
+
+int fm_set_size_of_fifo(void *h_fm,
+			uint8_t port_id,
+			uint32_t *p_size_of_fifo,
+			uint32_t *p_extra_size_of_fifo,
+			bool initial_config)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	struct fman_bmi_regs __iomem *bmi_rg = p_fm->p_fm_bmi_regs;
+	uint32_t size_of_fifo = *p_size_of_fifo, extra_size_of_fifo =
+	    *p_extra_size_of_fifo;
+	uint16_t current_val = 0, current_extra_val = 0;
+
+	ASSERT(IN_RANGE(1, port_id, 63));
+
+	if (!initial_config) {
+		/* !initial_config - runtime change of existing value.
+		 * - read the current FIFO and extra FIFO size
+		 */
+		current_extra_val =
+		    fman_get_size_of_extra_fifo(bmi_rg, port_id);
+		current_val = fman_get_size_of_fifo(bmi_rg, port_id);
+	}
+
+	if (extra_size_of_fifo > current_extra_val) {
+		if (extra_size_of_fifo &&
+		    !p_fm->p_fm_state_struct->extra_fifo_pool_size)
+			/* if this is the first time a port
+			 * requires extra_fifo_pool_size,
+			 * the total extra_fifo_pool_size
+			 * must be initialized to 1 buffer per port
+			 */
+			p_fm->p_fm_state_struct->extra_fifo_pool_size =
+			p_fm->intg->num_of_rx_ports * BMI_FIFO_UNITS;
+
+		p_fm->p_fm_state_struct->extra_fifo_pool_size =
+			max(p_fm->p_fm_state_struct->extra_fifo_pool_size,
+			    extra_size_of_fifo);
+	}
+
+	/* check that there are enough uncommitted fifo size */
+	if ((p_fm->p_fm_state_struct->accumulated_fifo_size - current_val +
+	     size_of_fifo) >
+	    (p_fm->p_fm_state_struct->total_fifo_size -
+	     p_fm->p_fm_state_struct->extra_fifo_pool_size)) {
+		pr_err("Requested fifo size and extra size exceed total FIFO size.\n");
+		return -EAGAIN;
+	}
+	/* update accumulated */
+	ASSERT(p_fm->p_fm_state_struct->accumulated_fifo_size >=
+		    current_val);
+	p_fm->p_fm_state_struct->accumulated_fifo_size -= current_val;
+	p_fm->p_fm_state_struct->accumulated_fifo_size += size_of_fifo;
+	fman_set_size_of_fifo(bmi_rg, port_id, size_of_fifo,
+			      extra_size_of_fifo);
+
+	return 0;
+}
+
+int fm_set_num_of_tasks(void *h_fm,
+			uint8_t port_id,
+			uint8_t *p_num_of_tasks,
+			uint8_t *p_num_of_extra_tasks, bool initial_config)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	struct fman_bmi_regs __iomem *bmi_rg = p_fm->p_fm_bmi_regs;
+	uint8_t current_val = 0, current_extra_val = 0, num_of_tasks =
+	    *p_num_of_tasks, num_of_extra_tasks = *p_num_of_extra_tasks;
+
+	ASSERT(IN_RANGE(1, port_id, 63));
+
+	if (!initial_config) {
+		/* !initial_config - runtime change of existing value.
+		 * - read the current number of tasks
+		 */
+		current_val = fman_get_num_of_tasks(bmi_rg, port_id);
+		current_extra_val =
+		    fman_get_num_extra_tasks(bmi_rg, port_id);
+	}
+
+	if (num_of_extra_tasks > current_extra_val)
+		p_fm->p_fm_state_struct->extra_tasks_pool_size =
+		(uint8_t)max(p_fm->p_fm_state_struct->extra_tasks_pool_size,
+			     num_of_extra_tasks);
+
+	/* check that there are enough uncommitted tasks */
+	if ((p_fm->p_fm_state_struct->accumulated_num_of_tasks - current_val +
+	     num_of_tasks) >
+	    (p_fm->p_fm_state_struct->total_num_of_tasks -
+	     p_fm->p_fm_state_struct->extra_tasks_pool_size)) {
+		pr_err("Requested num_of_tasks and extra tasks pool for fm%d exceed total num_of_tasks.\n",
+		       p_fm->p_fm_state_struct->fm_id);
+		return -EAGAIN;
+	}
+	ASSERT(p_fm->p_fm_state_struct->
+		    accumulated_num_of_tasks >=
+		    current_val);
+	/* update accumulated */
+	p_fm->p_fm_state_struct->accumulated_num_of_tasks -=
+	current_val;
+	p_fm->p_fm_state_struct->accumulated_num_of_tasks +=
+	num_of_tasks;
+	fman_set_num_of_tasks(bmi_rg, port_id, num_of_tasks,
+			      num_of_extra_tasks);
+
+	return 0;
+}
+
+int fm_set_num_of_open_dmas(void *h_fm,
+			    uint8_t port_id,
+			    uint8_t *p_num_of_open_dmas,
+			    uint8_t *p_num_of_extra_open_dmas,
+			    bool initial_config)
+{
+	struct fm_t *p_fm = (struct fm_t *)h_fm;
+	struct fman_bmi_regs __iomem *bmi_rg = p_fm->p_fm_bmi_regs;
+	uint8_t num_of_open_dmas = *p_num_of_open_dmas,
+	num_of_extra_open_dmas = *p_num_of_extra_open_dmas;
+	uint8_t total_num_dmas = 0, current_val = 0, current_extra_val = 0;
+
+	ASSERT(IN_RANGE(1, port_id, 63));
+
+	if (!initial_config) {
+		/* !initial_config - runtime change of existing value.
+		* - read the current number of open Dma's
+		*/
+		current_extra_val =
+		    fman_get_num_extra_dmas(bmi_rg, port_id);
+		current_val = fman_get_num_of_dmas(bmi_rg, port_id);
+	}
+
+	/* it's illegal to be in a state where this is
+	 * not the first set and no value is specified
+	 */
+	ASSERT(initial_config || num_of_open_dmas);
+	if (!num_of_open_dmas) {
+		/* !num_of_open_dmas - first configuration according
+		 * to values in regs.- read the current number of
+		 * open Dma's
+		 */
+		current_extra_val =
+		    fman_get_num_extra_dmas(bmi_rg, port_id);
+		current_val = fman_get_num_of_dmas(bmi_rg, port_id);
+		/* This is the first configuration and user did not
+		 * specify value (!num_of_open_dmas), reset values will be used
+		 * and we just save these values for resource management
+		 */
+		p_fm->p_fm_state_struct->extra_open_dmas_pool_size =
+			(uint8_t)max(p_fm->p_fm_state_struct->
+				     extra_open_dmas_pool_size,
+				     current_extra_val);
+		p_fm->p_fm_state_struct->accumulated_num_of_open_dmas +=
+		current_val;
+		*p_num_of_open_dmas = current_val;
+		*p_num_of_extra_open_dmas = current_extra_val;
+		return 0;
+	}
+
+	if (num_of_extra_open_dmas > current_extra_val)
+		p_fm->p_fm_state_struct->extra_open_dmas_pool_size =
+		    (uint8_t)max(p_fm->p_fm_state_struct->
+				 extra_open_dmas_pool_size,
+				 num_of_extra_open_dmas);
+
+#ifdef FM_HAS_TOTAL_DMAS
+	if ((p_fm->p_fm_state_struct->rev_info.major_rev < 6) &&
+	    (p_fm->p_fm_state_struct->accumulated_num_of_open_dmas -
+	     current_val + num_of_open_dmas >
+	     p_fm->p_fm_state_struct->max_num_of_open_dmas)) {
+		pr_err("Requested num_of_open_dmas for fm%d exceeds total num_of_open_dmas.\n",
+		       p_fm->p_fm_state_struct->fm_id);
+		return -EAGAIN;
+	}
+#else
+	if ((p_fm->p_fm_state_struct->rev_info.major_rev >= 6) &&
+	    #ifdef FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981
+	    !((p_fm->p_fm_state_struct->rev_info.major_rev == 6) &&
+	      (p_fm->p_fm_state_struct->rev_info.minor_rev == 0)) &&
+#endif /* FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 */
+	    (p_fm->p_fm_state_struct->accumulated_num_of_open_dmas -
+	     current_val + num_of_open_dmas >
+	     p_fm->intg->dma_thresh_max_commq + 1)) {
+		pr_err("Requested num_of_open_dmas for fm%d exceeds DMA Command queue (%d)\n",
+		       p_fm->p_fm_state_struct->fm_id,
+		       p_fm->intg->dma_thresh_max_commq + 1);
+		return -EAGAIN;
+	}
+#endif /* FM_HAS_TOTAL_DMAS */
+	else {
+		ASSERT(p_fm->p_fm_state_struct->
+			    accumulated_num_of_open_dmas >=
+			    current_val);
+		/* update acummulated */
+		p_fm->p_fm_state_struct->accumulated_num_of_open_dmas -=
+		current_val;
+		p_fm->p_fm_state_struct->accumulated_num_of_open_dmas +=
+		    num_of_open_dmas;
+
+#ifdef FM_HAS_TOTAL_DMAS
+		if (p_fm->p_fm_state_struct->rev_info.major_rev < 6)
+			total_num_dmas =
+			    (uint8_t)(p_fm->p_fm_state_struct->
+				       accumulated_num_of_open_dmas +
+				       p_fm->p_fm_state_struct->
+				       extra_open_dmas_pool_size);
+#endif /* FM_HAS_TOTAL_DMAS */
+		fman_set_num_of_open_dmas(bmi_rg,
+					  port_id,
+					  num_of_open_dmas,
+					  num_of_extra_open_dmas,
+					  total_num_dmas);
+	}
+
+	return 0;
+}
+
 int fm_reset_mac(void *h_fm, enum fm_mac_type type, uint8_t mac_id)
 {
 	struct fm_t *p_fm = (struct fm_t *)h_fm;
@@ -928,6 +1414,7 @@ static int init_fm_qmi(struct fm_t *p_fm)
 void *fm_config(struct fm_params_t *p_fm_param)
 {
 	struct fm_t *p_fm;
+	uint8_t i;
 	uintptr_t base_addr;
 
 	if (!((p_fm_param->firmware.p_code && p_fm_param->firmware.size) ||
@@ -952,6 +1439,9 @@ void *fm_config(struct fm_params_t *p_fm_param)
 	/* Initialize FM parameters which will be kept by the driver */
 	p_fm->p_fm_state_struct->fm_id = p_fm_param->fm_id;
 
+	for (i = 0; i < FM_MAX_NUM_OF_HW_PORT_IDS; i++)
+		p_fm->p_fm_state_struct->ports_types[i] = FM_PORT_TYPE_DUMMY;
+
 	/* Allocate the FM driver's parameters structure */
 	p_fm->p_fm_drv_param = kzalloc(sizeof(*p_fm->p_fm_drv_param),
 						 GFP_KERNEL);
diff --git a/drivers/net/ethernet/freescale/fman/fm_common.h b/drivers/net/ethernet/freescale/fman/fm_common.h
index 4fe12c6..374c43b 100644
--- a/drivers/net/ethernet/freescale/fman/fm_common.h
+++ b/drivers/net/ethernet/freescale/fman/fm_common.h
@@ -41,6 +41,14 @@
 
 #define CLS_PLAN_NUM_PER_GRP                        8
 
+/* Defines used for manipulation CC and BMI */
+#define UPDATE_NIA_PNEN                         0x80000000
+#define UPDATE_NIA_PNDN                         0x20000000
+#define UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY      0x10000000
+#define UPDATE_NIA_FENE                         0x04000000
+#define UPDATE_NIA_CMNE                         0x02000000
+#define UPDATE_NIA_FPNE                         0x01000000
+
 /* list_object
  * Macro to get the struct (object) for this entry.
  * type   - The type of the struct (object) this list
@@ -53,6 +61,12 @@
 #define list_object(p_list, type, member) \
 ((type *)((char *)(p_list) - member_offset(type, member)))
 
+#define FM_LIODN_OFFSET_MASK    0x3FF
+
+/* NIA Description */
+/* V3 only */
+#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME        0x00000028
+
 /* Enum for inter-module interrupts registration */
 enum fm_event_modules {
 	FM_MOD_PRS = 0,		/* Parser event */
@@ -168,6 +182,59 @@ static inline bool TRY_LOCK(spinlock_t *spinlock, volatile bool *p_flag)
 
 #define FM_LIODN_OFFSET_MASK    0x3FF
 
+/* NIA Description */
+#define NIA_ENG_MASK                0x007C0000
+#define NIA_AC_MASK                 0x0003ffff
+
+#define NIA_ORDER_RESTOR            0x00800000
+#define NIA_ENG_FM_CTL              0x00000000
+#define NIA_ENG_PRS                 0x00440000
+#define NIA_ENG_BMI                 0x00500000
+#define NIA_ENG_QMI_ENQ             0x00540000
+#define NIA_ENG_QMI_DEQ             0x00580000
+
+#define NIA_FM_CTL_AC_HC                        0x0000000C
+#define NIA_FM_CTL_AC_IND_MODE_TX               0x00000008
+#define NIA_FM_CTL_AC_IND_MODE_RX               0x0000000A
+#define NIA_FM_CTL_AC_POP_TO_N_STEP             0x0000000e
+#define NIA_FM_CTL_AC_PRE_BMI_FETCH_HEADER      0x00000010
+#define NIA_FM_CTL_AC_PRE_BMI_FETCH_FULL_FRAME  0x00000018
+#define NIA_FM_CTL_AC_POST_BMI_FETCH            0x00000012
+#define NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME         0x0000001A
+#define NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME     0x0000001E
+#define NIA_FM_CTL_AC_POST_BMI_ENQ_ORR          0x00000014
+#define NIA_FM_CTL_AC_POST_BMI_ENQ              0x00000022
+#define NIA_FM_CTL_AC_POST_TX                   0x00000024
+/* V3 only */
+#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME        0x00000028
+#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_DISCARD_FRAME    0x0000002A
+#define NIA_FM_CTL_AC_NO_IPACC_POP_TO_N_STEP            0x0000002C
+
+#define NIA_BMI_AC_ENQ_FRAME        0x00000002
+#define NIA_BMI_AC_TX_RELEASE       0x000002C0
+#define NIA_BMI_AC_RELEASE          0x000000C0
+#define NIA_BMI_AC_DISCARD          0x000000C1
+#define NIA_BMI_AC_TX               0x00000274
+#define NIA_BMI_AC_FETCH            0x00000208
+#define NIA_BMI_AC_MASK             0x000003FF
+
+#define NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA    0x00000202
+
+#define GET_NIA_BMI_AC_ENQ_FRAME(GET_NIA_BMI_AC_ENQ_FRAME, errata_A006675)\
+	(errata_A006675 ?						\
+	((uint32_t)(NIA_ENG_FM_CTL |					\
+		NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME)) :		\
+	((uint32_t)(NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+#define GET_NIA_BMI_AC_DISCARD_FRAME(h_fm_pcd, errata_A006675)	\
+	(errata_A006675 ?						\
+	((uint32_t)(NIA_ENG_FM_CTL |					\
+		NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_DISCARD_FRAME)) :	\
+	((uint32_t)(NIA_ENG_BMI | NIA_BMI_AC_DISCARD)))
+#define GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME(errata_A006675)		\
+	(errata_A006675 ?						\
+	(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME) :\
+	(NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))
+
 /* Description        CTRL Parameters Page defines */
 #define FM_CTL_PARAMS_PAGE_OP_FIX_EN            0x80000000
 #define FM_CTL_PARAMS_PAGE_ALWAYS_ON            0x00000100
@@ -198,6 +265,20 @@ do {									\
 	}								\
 } while (0)
 
+#define HW_PORT_ID_TO_SW_PORT_ID(major, _mac_id, port_id)		\
+do {									\
+	if (port_id >= BASE_TX_PORTID)					\
+		_mac_id = (uint8_t)(port_id - BASE_TX_PORTID);		\
+	else if (port_id >= BASE_RX_PORTID)				\
+		_mac_id = (uint8_t)(port_id - BASE_RX_PORTID);		\
+	else if (port_id >= BASE_OH_PORTID(major))			\
+		_mac_id = (uint8_t)(port_id - BASE_OH_PORTID(major));	\
+	else {								\
+		_mac_id = (uint8_t)DUMMY_PORT_ID;			\
+		ASSERT(true);						\
+	}								\
+} while (0)
+
 #define BMI_MAX_FIFO_SIZE                   (FM_MURAM_SIZE)
 #define BMI_FIFO_UNITS                      0x100
 
@@ -258,9 +339,7 @@ default:                                                \
 } \
 } while (0)
 
-#define FM_PCD_MAX_NUM_OF_OPTIONS(cls_plan_entries)   \
-((cls_plan_entries == 256) ? 8 : ((cls_plan_entries == 128) ? 7 : \
-((cls_plan_entries == 64) ? 6 : ((cls_plan_entries == 32) ? 5 : 0))))
+/*          Common API for FM-Port module                            */
 
 /* Function      fm_register_intr
  * Description   Used to register
@@ -300,6 +379,53 @@ enum fm_mac_type {
 	FM_MAC_1G	    /* 1G MAC */
 };
 
+/* Description   Structure for port-FM communication
+ * during fm_port_init. Fields commented 'IN' are passed
+ * by the port module to be used by the FM module.
+ * Fields commented 'OUT' will be filled by FM before returning to port.
+ * Some fields are optional (depending on configuration) and
+ * will be analized by the port and FM modules accordingly.
+ */
+struct fm_inter_module_port_init_params_t {
+	uint8_t port_id;
+	/* IN. port Id */
+	enum fm_port_type port_type;
+	/* IN. Port type */
+	enum fm_port_speed port_speed;
+	/* IN. Port speed */
+	/* IN. Port's requested resource*/
+	uint16_t liodn_offset;
+	/* IN. Port's requested resource */
+	uint8_t num_of_tasks;
+	/* IN. Port's requested resource */
+	uint8_t num_of_extra_tasks;
+	/* IN. Port's requested resource */
+	uint8_t num_of_open_dmas;
+	/* IN. Port's requested resource */
+	uint8_t num_of_extra_open_dmas;
+	/* IN. Port's requested resource */
+	uint32_t size_of_fifo;
+	/* IN. Port's requested resource */
+	uint32_t extra_size_of_fifo;
+	/* IN. Port's requested resource */
+	uint8_t deq_pipeline_depth;
+	/* IN. Port's max frame length. */
+	uint16_t max_frame_length;
+	/* IN. Irrelevant for P4080 rev 1.
+	 * LIODN base for this port, to be
+	 * used together with LIODN offset.
+	 */
+	uint16_t liodn_base;
+};
+
+/* Description   Structure for port-FM communication during fm_port_free.*/
+struct fm_inter_module_port_free_params_t {
+	uint8_t port_id;		/* IN. port Id */
+	enum fm_port_type port_type;	/* IN. Port type */
+	enum fm_port_speed port_speed;	/* IN. Port speed */
+	uint8_t deq_pipeline_depth;	/* IN. Port's requested resource */
+};
+
 /* Function      fm_get_muram_pointer
  * Description   Get the pointer of the MURAM from the FM module
  * Param[in]     h_fm            A handle to an FM Module.
@@ -342,6 +468,29 @@ uint16_t fm_get_clock_freq(void *h_fm);
  */
 uint8_t fm_get_id(void *h_fm);
 
+/* Function      fm_get_set_port_params
+ * Description   Used by FM-PORT driver to pass and receive parameters between
+ *		PORT and FM modules.
+ * Param[in]     h_fm            A handle to an FM Module.
+ * Param[in,out] p_port_params    A structure of FM Port parameters.
+ * Return        0 on success; Error code otherwise.
+ * Cautions      Allowed only following fm_init().
+ */
+int fm_get_set_port_params(void *h_fm,
+			   struct fm_inter_module_port_init_params_t
+			   *p_port_params);
+
+/* Function      fm_free_port_params
+ * Description   Used by FM-PORT driver to free port's resources within the FM.
+ * Param[in]     h_fm            A handle to an FM Module.
+ * Param[in,out] p_port_params    A structure of FM Port parameters.
+ * Return        None.
+ * Cautions      Allowed only following fm_init().
+ */
+void fm_free_port_params(void *h_fm,
+			 struct fm_inter_module_port_free_params_t
+			 *p_port_params);
+
 #ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
 int fm_10g_tx_ecc_workaround(void *h_fm, uint8_t mac_id);
 #endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
@@ -368,5 +517,22 @@ struct num_of_ports_info_t *fm_get_num_of_ports(void *h_fm);
 
 int fm_set_mac_max_frame(void *h_fm, enum fm_mac_type type,
 			 uint8_t mac_id, uint16_t mtu);
+int fm_set_num_of_open_dmas(void *h_fm,
+			    uint8_t port_id,
+			    uint8_t *p_num_of_open_dmas,
+			    uint8_t *p_num_of_extra_open_dmas,
+			    bool initial_config);
+int fm_set_num_of_tasks(void *h_fm,
+			uint8_t port_id,
+			uint8_t *p_num_of_tasks,
+			uint8_t *p_num_of_extra_tasks,
+			bool initial_config);
+int fm_set_size_of_fifo(void *h_fm,
+			uint8_t port_id,
+			uint32_t *p_size_of_fifo,
+			uint32_t *p_extra_size_of_fifo,
+			bool initial_config);
+
+uint32_t fm_get_bmi_max_fifo_size(void *h_fm);
 
 #endif /* __FM_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/fm_drv.c b/drivers/net/ethernet/freescale/fman/fm_drv.c
index 2d8db7f..c8eb3a3 100644
--- a/drivers/net/ethernet/freescale/fman/fm_drv.c
+++ b/drivers/net/ethernet/freescale/fman/fm_drv.c
@@ -219,6 +219,73 @@ static void destroy_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
 	kfree(p_lnx_wrp_fm_dev);
 }
 
+static int fill_rest_fm_info(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+#define FM_BMI_PPIDS_OFFSET                 0x00080304
+#define FM_DMA_PLR_OFFSET                   0x000c2060
+#define FM_FPM_IP_REV_1_OFFSET              0x000c30c4
+#define DMA_HIGH_LIODN_MASK                 0x0FFF0000
+#define DMA_LOW_LIODN_MASK                  0x00000FFF
+#define DMA_LIODN_SHIFT                     16
+
+/* These need to be moved to FLib: */
+	struct plr_t {
+		uint32_t plr[32];
+	} __attribute__((__packed__));
+
+	struct ppids_t {
+		volatile uint32_t fmbm_ppid[63];
+	} __attribute__((__packed__));
+
+	struct plr_t *p_plr;
+	struct ppids_t *p_ppids;
+	int i;
+	uint32_t fm_rev;
+
+	fm_rev = (uint32_t)(*((volatile uint32_t *)
+				UINT_TO_PTR(p_lnx_wrp_fm_dev->fm_base_addr +
+					    FM_FPM_IP_REV_1_OFFSET)));
+	fm_rev &= 0xffff;
+
+	p_plr =
+	    (struct plr_t *)UINT_TO_PTR(p_lnx_wrp_fm_dev->fm_base_addr +
+				  FM_DMA_PLR_OFFSET);
+#ifdef MODULE
+	for (i = 0; i < FM_MAX_NUM_OF_PARTITIONS / 2; i++)
+		p_plr->plr[i] = 0;
+#endif /* MODULE */
+
+	for (i = 0; i < FM_MAX_NUM_OF_PARTITIONS; i++) {
+		uint16_t liodn_base;
+
+		liodn_base = (uint16_t)((i % 2) ?
+				(p_plr->plr[i / 2] & DMA_LOW_LIODN_MASK) :
+				((p_plr->plr[i / 2] & DMA_HIGH_LIODN_MASK) >>
+				DMA_LIODN_SHIFT));
+#ifdef FM_PARTITION_ARRAY
+		p_lnx_wrp_fm_dev->params.liodn_base_per_port[i] = liodn_base;
+#endif /* FM_PARTITION_ARRAY */
+
+		if (((i >= FIRST_RX_PORT) && (i <= LAST_RX_PORT)) ||
+		    ((i >= FIRST_TX_PORT) && (i <= FIRST_TX_PORT)) ||
+		    ((i >= FIRST_OP_PORT(
+			    p_lnx_wrp_fm_dev->fm_rev_info.major_rev)) &&
+		    (i <= LAST_OP_PORT)))
+			p_lnx_wrp_fm_dev->ports[i].port_params.liodn_base =
+			liodn_base;
+	}
+
+	p_ppids = (struct ppids_t *)
+		UINT_TO_PTR(p_lnx_wrp_fm_dev->fm_base_addr +
+			    FM_BMI_PPIDS_OFFSET);
+
+	for (i = FIRST_RX_PORT; i <= LAST_RX_PORT; i++)
+		p_lnx_wrp_fm_dev->ports[i].port_params.specific_params.
+		    rx_params.liodn_offset = (u16)(p_ppids->fmbm_ppid[i - 1]);
+
+	return 0;
+}
+
 /**
 *find_fman_microcode - find the Fman microcode
  *
@@ -562,7 +629,7 @@ static int configure_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
 	p_lnx_wrp_fm_dev->params.f_bus_error = lnxwrp_fm_dev_bus_error_cb;
 	p_lnx_wrp_fm_dev->params.h_app = p_lnx_wrp_fm_dev;
 
-	return 0;
+	return fill_rest_fm_info(p_lnx_wrp_fm_dev);
 }
 
 static int init_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
@@ -820,6 +887,56 @@ void *fm_get_handle(struct fm *fm)
 EXPORT_SYMBOL(fm_get_handle);
 
 
+struct fm_port *fm_port_bind(struct device *fm_port_dev)
+{
+	return (struct fm_port *)(dev_get_drvdata(get_device(fm_port_dev)));
+}
+EXPORT_SYMBOL(fm_port_bind);
+
+void fm_port_unbind(struct fm_port *port)
+{
+	struct lnx_wrp_fm_port_dev_t *p_lnx_wrp_fm_port_dev =
+					(struct lnx_wrp_fm_port_dev_t *)port;
+
+	put_device(p_lnx_wrp_fm_port_dev->dev);
+}
+EXPORT_SYMBOL(fm_port_unbind);
+
+void *fm_port_get_handle(const struct fm_port *port)
+{
+	struct lnx_wrp_fm_port_dev_t *p_lnx_wrp_fm_port_dev =
+					(struct lnx_wrp_fm_port_dev_t *)port;
+
+	return (void *)p_lnx_wrp_fm_port_dev->h_dev;
+}
+EXPORT_SYMBOL(fm_port_get_handle);
+
+void fm_port_get_base_addr(const struct fm_port *port, uint64_t *base_addr)
+{
+	struct lnx_wrp_fm_port_dev_t *p_lnx_wrp_fm_port_dev =
+					(struct lnx_wrp_fm_port_dev_t *)port;
+
+	*base_addr = p_lnx_wrp_fm_port_dev->port_params.base_addr;
+}
+EXPORT_SYMBOL(fm_port_get_base_addr);
+
+void fm_port_get_buff_layout_ext_params(struct fm_port *port,
+					struct fm_port_params *params)
+{
+	/* TODO - Should this function be removed? */
+	params->data_align = 0;
+}
+EXPORT_SYMBOL(fm_port_get_buff_layout_ext_params);
+
+int fm_get_tx_port_channel(struct fm_port *port)
+{
+	struct lnx_wrp_fm_port_dev_t *p_lnx_wrp_fm_port_dev =
+					(struct lnx_wrp_fm_port_dev_t *)port;
+
+	return p_lnx_wrp_fm_port_dev->tx_ch;
+}
+EXPORT_SYMBOL(fm_get_tx_port_channel);
+
 void fm_mutex_lock(void)
 {
 	mutex_lock(&lnxwrp_mutex);
diff --git a/drivers/net/ethernet/freescale/fman/fm_drv.h b/drivers/net/ethernet/freescale/fman/fm_drv.h
index de69965..f2a9885 100644
--- a/drivers/net/ethernet/freescale/fman/fm_drv.h
+++ b/drivers/net/ethernet/freescale/fman/fm_drv.h
@@ -35,6 +35,7 @@
 
 #include "service.h"
 #include "fsl_fman_drv.h"
+#include "fm_port_ext.h"
 
 #ifndef CONFIG_FSL_FM_MAX_FRAME_SIZE
 #define CONFIG_FSL_FM_MAX_FRAME_SIZE 0
@@ -68,6 +69,7 @@ struct lnx_wrp_fm_port_dev_t {
 	uint64_t phys_base_addr;
 	uint64_t base_addr;	/* Port's *virtual* address */
 	resource_size_t mem_size;
+	struct fm_port_params_t port_params;
 	struct fm_buffer_prefix_content_t buff_prefix_content;
 	void *h_dev;
 	void *h_lnx_wrp_fm_dev;
diff --git a/drivers/net/ethernet/freescale/fman/fm_port_drv.c b/drivers/net/ethernet/freescale/fman/fm_port_drv.c
new file mode 100644
index 0000000..110403d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm_port_drv.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*File          lnxwrp_fm_port.c
+ *Description   FMD wrapper - FMan port functions.
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/cdev.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "fm_common.h"
+#include "fsl_fman_drv.h"
+#include "fm_port_ext.h"
+#include "fm_drv.h"
+
+static struct lnx_wrp_fm_port_dev_t
+*read_fm_port_dev_tree_node(struct platform_device *of_dev)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+	struct lnx_wrp_fm_port_dev_t *p_lnx_wrp_fm_port_dev;
+	struct device_node *fm_node, *port_node;
+	struct resource res;
+	const uint32_t *uint32_prop;
+	int _errno = 0, lenp;
+	enum fm_port_type port_type;
+	enum fm_port_speed port_speed;
+	u8 cell_index;
+
+	port_node = of_node_get(of_dev->dev.of_node);
+
+	/* Get the FM node */
+	fm_node = of_get_parent(port_node);
+	if (unlikely(!fm_node)) {
+		pr_err("of_get_parent() = %d\n", _errno);
+		return NULL;
+	}
+
+	p_lnx_wrp_fm_dev = dev_get_drvdata(&of_find_device_by_node(fm_node)->
+					   dev);
+	of_node_put(fm_node);
+
+	/* if fm_probe() failed, no point in going further with port probing */
+	if (!p_lnx_wrp_fm_dev)
+		return NULL;
+
+	uint32_prop =
+	    (uint32_t *)of_get_property(port_node, "cell-index", &lenp);
+	if (unlikely(!uint32_prop)) {
+		pr_err("of_get_property(%s, cell-index) failed\n",
+		       port_node->full_name);
+		return NULL;
+	}
+	if (WARN_ON(lenp != sizeof(uint32_t)))
+		return NULL;
+	cell_index = (u8)*uint32_prop;
+
+	p_lnx_wrp_fm_port_dev = &p_lnx_wrp_fm_dev->ports[cell_index];
+	p_lnx_wrp_fm_port_dev->id = cell_index;
+	p_lnx_wrp_fm_port_dev->port_params.port_id =
+						p_lnx_wrp_fm_port_dev->id;
+
+	if (of_device_is_compatible(port_node, "fsl,fman-v2-port-oh") ||
+	    of_device_is_compatible(port_node, "fsl,fman-v3-port-oh")) {
+		port_type = FM_PORT_TYPE_OP;
+		port_speed = FM_PORT_SPEED_OP;
+
+	} else if (of_device_is_compatible(port_node,
+					    "fsl,fman-v3-port-tx") ||
+		   of_device_is_compatible(port_node,
+					   "fsl,fman-v2-port-tx")) {
+		if (cell_index >= TX_10G_PORT_BASE)
+			port_speed = FM_PORT_SPEED_10G;
+		else
+			port_speed = FM_PORT_SPEED_1G;
+		port_type = FM_PORT_TYPE_TX;
+
+	} else if (of_device_is_compatible(port_node,
+					    "fsl,fman-v3-port-rx") ||
+		   of_device_is_compatible(port_node,
+					   "fsl,fman-v2-port-rx")) {
+		if (cell_index >= RX_10G_PORT_BASE)
+			port_speed = FM_PORT_SPEED_10G;
+		else
+			port_speed = FM_PORT_SPEED_1G;
+		port_type = FM_PORT_TYPE_RX;
+	} else {
+		pr_err("Illegal port type\n");
+		return NULL;
+	}
+
+	p_lnx_wrp_fm_port_dev->port_params.port_type = port_type;
+	p_lnx_wrp_fm_port_dev->port_params.port_speed = port_speed;
+
+	if (port_type == FM_PORT_TYPE_OP || port_type == FM_PORT_TYPE_TX) {
+		uint32_t qman_channel_id;
+
+		qman_channel_id = get_qman_channel_id(p_lnx_wrp_fm_dev,
+						      cell_index,
+						      port_type,
+						      port_speed);
+
+		if (qman_channel_id == 0) {
+			pr_err("incorrect qman-channel-id\n");
+			return NULL;
+		}
+		p_lnx_wrp_fm_port_dev->tx_ch = qman_channel_id;
+		p_lnx_wrp_fm_port_dev->port_params.specific_params.
+				non_rx_params.qm_channel = qman_channel_id;
+	}
+
+	_errno = of_address_to_resource(port_node, 0, &res);
+	if (unlikely(_errno < 0)) {
+		pr_err("of_address_to_resource() = %d\n", _errno);
+		return NULL;
+	}
+
+	p_lnx_wrp_fm_port_dev->dev = &of_dev->dev;
+	p_lnx_wrp_fm_port_dev->base_addr = 0;
+	p_lnx_wrp_fm_port_dev->phys_base_addr = res.start;
+	p_lnx_wrp_fm_port_dev->mem_size = res.end + 1 - res.start;
+	p_lnx_wrp_fm_port_dev->port_params.h_fm = p_lnx_wrp_fm_dev->h_dev;
+	p_lnx_wrp_fm_port_dev->h_lnx_wrp_fm_dev = (void *)p_lnx_wrp_fm_dev;
+
+	of_node_put(port_node);
+
+	p_lnx_wrp_fm_port_dev->active = true;
+
+	return p_lnx_wrp_fm_port_dev;
+}
+
+static int configure_fm_port_dev(struct lnx_wrp_fm_port_dev_t
+				     *p_lnx_wrp_fm_port_dev)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+	    (struct lnx_wrp_fm_dev_t *)p_lnx_wrp_fm_port_dev->h_lnx_wrp_fm_dev;
+	struct resource *dev_res;
+
+	if (!p_lnx_wrp_fm_port_dev->active) {
+		pr_err("FM port not configured!!!\n");
+		return -ENOSYS;
+	}
+
+	dev_res =
+	    __devm_request_region(p_lnx_wrp_fm_dev->dev, p_lnx_wrp_fm_dev->res,
+				  p_lnx_wrp_fm_port_dev->phys_base_addr,
+				  p_lnx_wrp_fm_port_dev->mem_size,
+				  "fman-port-hc");
+	if (unlikely(!dev_res)) {
+		pr_err("__devm_request_region() failed\n");
+		return -ENOSYS;
+	}
+	p_lnx_wrp_fm_port_dev->base_addr =
+	    PTR_TO_UINT(devm_ioremap
+			(p_lnx_wrp_fm_dev->dev,
+			 p_lnx_wrp_fm_port_dev->phys_base_addr,
+			 p_lnx_wrp_fm_port_dev->mem_size));
+	if (unlikely(p_lnx_wrp_fm_port_dev->base_addr == 0))
+		pr_err("devm_ioremap() failed\n");
+
+	p_lnx_wrp_fm_port_dev->port_params.base_addr =
+	    p_lnx_wrp_fm_port_dev->base_addr;
+
+	return 0;
+}
+
+static int init_fm_port_dev(struct lnx_wrp_fm_port_dev_t
+				*p_lnx_wrp_fm_port_dev)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+		(struct lnx_wrp_fm_dev_t *)p_lnx_wrp_fm_port_dev->
+		h_lnx_wrp_fm_dev;
+
+	if (!p_lnx_wrp_fm_port_dev->active || p_lnx_wrp_fm_port_dev->h_dev)
+		return -ENOSYS;
+
+	p_lnx_wrp_fm_port_dev->h_dev =
+	    fm_port_config(&p_lnx_wrp_fm_port_dev->port_params);
+	if (!p_lnx_wrp_fm_port_dev->h_dev) {
+		pr_err("FM-port\n");
+		return -ENOSYS;
+	}
+
+	if (fm_get_revision(p_lnx_wrp_fm_dev->h_dev,
+			    &p_lnx_wrp_fm_port_dev->fm_rev_info) != 0) {
+		pr_err("FM-port\n");
+		return -ENOSYS;
+	}
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+	if ((p_lnx_wrp_fm_port_dev->fm_rev_info.major_rev != 4) &&
+	    (p_lnx_wrp_fm_port_dev->port_params.port_type ==
+	    FM_PORT_TYPE_TX)) {
+		int err_code = 0;
+
+		err_code =
+		    fm_port_cfg_deq_high_priority(p_lnx_wrp_fm_port_dev->
+						     h_dev, true);
+		if (err_code != 0)
+			return -err_code;
+		err_code =
+		    fm_port_cfg_deq_prefetch_option
+		    (p_lnx_wrp_fm_port_dev->h_dev, FM_PORT_DEQ_FULL_PREFETCH);
+		if (err_code != 0)
+			return -err_code;
+	}
+#endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+#ifdef FM_BCB_ERRATA_BMI_SW001
+/* Configure BCB workaround on Rx ports, only for B4860 rev1 */
+#define SVR_SECURITY_MASK    0x00080000
+#define SVR_PERSONALITY_MASK 0x0000FF00
+#define SVR_VER_IGNORE_MASK (SVR_SECURITY_MASK | SVR_PERSONALITY_MASK)
+#define SVR_B4860_REV1_VALUE 0x86800010
+
+	if ((p_lnx_wrp_fm_port_dev->fm_rev_info.major_rev >= 6) &&
+	    (p_lnx_wrp_fm_port_dev->port_params.port_type ==
+	    FM_PORT_TYPE_RX)){
+		unsigned int svr;
+
+		svr = mfspr(SPRN_SVR);
+
+		if ((svr & ~SVR_VER_IGNORE_MASK) == SVR_B4860_REV1_VALUE)
+			fm_port_cfg_bcb_wa(p_lnx_wrp_fm_port_dev->h_dev);
+	}
+#endif /* FM_BCB_ERRATA_BMI_SW001 */
+
+	fm_port_cfg_buf_prefix_content(p_lnx_wrp_fm_port_dev->h_dev,
+				       &p_lnx_wrp_fm_port_dev->
+					buff_prefix_content);
+
+	if (fm_port_init(p_lnx_wrp_fm_port_dev->h_dev) != 0)
+		return -ENOSYS;
+
+/**
+ * FMan Fifo sizes behind the scene":
+ * Using the following formulae (*), under a set of simplifying assumptions (.):
+ * . all ports are configured in Normal Mode (rather than Independent Mode)
+ * . the DPAA Eth driver allocates buffers of size:
+ *     . MAXFRM + NET_IP_ALIGN + DPA_PRIV_DATA_SIZE + DPA_PARSE_RESULTS_SIZE
+ *		 + DPA_HASH_RESULTS_SIZE, i.e.:
+ *       MAXFRM + 2 + 16 + sizeof(fm_prs_result_t) + 16, i.e.:
+ *       MAXFRM + 66
+ * . excessive buffer pools not accounted for
+ *
+ **for Rx ports on P4080:
+ *     . IFSZ = ceil(max(FMBM_EBMPI[PBS]) / 256)*256 + 7*256
+ *     . no internal frame offset (FMBM_RIM[FOF] == 0) - otherwise,
+ *     add up to 256 to the above
+ *
+ **for Rx ports on P1023:
+ *     . IFSZ = ceil(second_largest(FMBM_EBMPI[PBS] / 256))*256 + 7*256,
+ *     if at least 2 bpools are configured
+ *     . IFSZ = 8*256, if only a single bpool is configured
+ *
+ **for Tx ports:
+ *     . IFSZ = ceil(frame_size / 256)*256 + 3*256
+ *			+ FMBM_TFP[DPDE]*256, i.e.:
+ *       IFSZ = ceil(MAXFRM / 256)*256 + 3 x 256 + FMBM_TFP[DPDE]*256
+ *
+ **for OH ports on P4080:
+ *     . IFSZ = ceil(frame_size / 256)*256 + 1*256 + FMBM_PP[MXT]*256
+ **for OH ports on P1023:
+ *     . IFSZ = ceil(frame_size / 256)*256 + 3*256 + FMBM_TFP[DPDE]*256
+ **for both P4080 and P1023:
+ *     . (conservative decisions, assuming that BMI must bring the entire
+ *     frame, not only the frame header)
+ *     . no internal frame offset (FMBM_OIM[FOF] == 0) - otherwise,
+ *     add up to 256 to the above
+ *
+ * . for P4080/P5020/P3041/P2040, DPDE is:
+ *             > 0 or 1, for 1Gb ports, HW default: 0
+ *             > 2..7 (recommended: 3..7) for 10Gb ports, HW default: 3
+ * . for P1023, DPDE should be 1
+ *
+ * . for P1023, MXT is in range (0..31)
+ * . for P4080, MXT is in range (0..63)
+ *
+ */
+	return 0;
+}
+
+void fm_set_rx_port_params(struct fm_port *port, struct fm_port_params *params)
+{
+	struct lnx_wrp_fm_port_dev_t *p_lnx_wrp_fm_port_dev =
+	(struct lnx_wrp_fm_port_dev_t *)port;
+	int i;
+
+	p_lnx_wrp_fm_port_dev->port_params.specific_params.
+	rx_params.err_fqid = params->errq;
+	p_lnx_wrp_fm_port_dev->port_params.specific_params.rx_params.
+	dflt_fqid = params->defq;
+	p_lnx_wrp_fm_port_dev->port_params.specific_params.rx_params.
+	    ext_buf_pools.num_of_pools_used = params->num_pools;
+	for (i = 0; i < params->num_pools; i++) {
+		p_lnx_wrp_fm_port_dev->port_params.specific_params.
+		    rx_params.ext_buf_pools.ext_buf_pool[i].id =
+		    params->pool_param[i].id;
+		p_lnx_wrp_fm_port_dev->port_params.specific_params.
+		    rx_params.ext_buf_pools.ext_buf_pool[i].size =
+		    params->pool_param[i].size;
+	}
+
+	p_lnx_wrp_fm_port_dev->buff_prefix_content.priv_data_size =
+	    params->priv_data_size;
+	p_lnx_wrp_fm_port_dev->buff_prefix_content.pass_prs_result =
+	    params->parse_results;
+	p_lnx_wrp_fm_port_dev->buff_prefix_content.pass_hash_result =
+	    params->hash_results;
+	p_lnx_wrp_fm_port_dev->buff_prefix_content.pass_time_stamp =
+	params->time_stamp;
+	p_lnx_wrp_fm_port_dev->buff_prefix_content.data_align =
+	params->data_align;
+
+	init_fm_port_dev(p_lnx_wrp_fm_port_dev);
+}
+EXPORT_SYMBOL(fm_set_rx_port_params);
+
+/* this function is called from oh_probe as well, thus it contains oh port
+ * specific parameters (make sure everything is checked)
+ **/
+void fm_set_tx_port_params(struct fm_port *port, struct fm_port_params *params)
+{
+	struct lnx_wrp_fm_port_dev_t *p_lnx_wrp_fm_port_dev =
+	(struct lnx_wrp_fm_port_dev_t *)port;
+
+	p_lnx_wrp_fm_port_dev->port_params.specific_params.non_rx_params.
+	err_fqid = params->errq;
+	p_lnx_wrp_fm_port_dev->port_params.specific_params.non_rx_params.
+	dflt_fqid = params->defq;
+
+	p_lnx_wrp_fm_port_dev->buff_prefix_content.priv_data_size =
+	    params->priv_data_size;
+	p_lnx_wrp_fm_port_dev->buff_prefix_content.pass_prs_result =
+	    params->parse_results;
+	p_lnx_wrp_fm_port_dev->buff_prefix_content.pass_hash_result =
+	    params->hash_results;
+	p_lnx_wrp_fm_port_dev->buff_prefix_content.pass_time_stamp =
+	params->time_stamp;
+	p_lnx_wrp_fm_port_dev->buff_prefix_content.data_align =
+	params->data_align;
+
+	init_fm_port_dev(p_lnx_wrp_fm_port_dev);
+}
+EXPORT_SYMBOL(fm_set_tx_port_params);
+
+static void free_fm_port_dev(struct lnx_wrp_fm_port_dev_t
+			     *p_lnx_wrp_fm_port_dev)
+{
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+	    (struct lnx_wrp_fm_dev_t *)p_lnx_wrp_fm_port_dev->h_lnx_wrp_fm_dev;
+
+	if (!p_lnx_wrp_fm_port_dev->active)
+		return;
+
+	if (p_lnx_wrp_fm_port_dev->h_dev)
+		fm_port_free((struct fm_port *)p_lnx_wrp_fm_port_dev);
+
+	devm_iounmap(p_lnx_wrp_fm_dev->dev,
+		     UINT_TO_PTR(p_lnx_wrp_fm_port_dev->base_addr));
+	__devm_release_region(p_lnx_wrp_fm_dev->dev, p_lnx_wrp_fm_dev->res,
+			      p_lnx_wrp_fm_port_dev->phys_base_addr,
+			      p_lnx_wrp_fm_port_dev->mem_size);
+}
+
+static int /*__devinit*/ fm_port_probe(struct platform_device *of_dev)
+{
+	struct lnx_wrp_fm_port_dev_t *p_lnx_wrp_fm_port_dev;
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+	struct device *dev;
+
+	dev = &of_dev->dev;
+
+	p_lnx_wrp_fm_port_dev = read_fm_port_dev_tree_node(of_dev);
+	if (!p_lnx_wrp_fm_port_dev)
+		return -EIO;
+	/* Port can be inactive, thus will not be probed:
+	 * - in performance mode, OH ports are disabled  ...
+	 **/
+	if (!p_lnx_wrp_fm_port_dev->active)
+		return 0;
+
+	if (configure_fm_port_dev(p_lnx_wrp_fm_port_dev) != 0)
+		return -EIO;
+
+	dev_set_drvdata(dev, p_lnx_wrp_fm_port_dev);
+
+	p_lnx_wrp_fm_dev = (struct lnx_wrp_fm_dev_t *)p_lnx_wrp_fm_port_dev->
+			   h_lnx_wrp_fm_dev;
+
+	if (p_lnx_wrp_fm_port_dev->port_params.port_type ==
+		FM_PORT_TYPE_RX) {
+		snprintf(p_lnx_wrp_fm_port_dev->name,
+			 sizeof(p_lnx_wrp_fm_port_dev->name),
+			 "%s-port-rx%d",
+			 p_lnx_wrp_fm_dev->name, p_lnx_wrp_fm_port_dev->id);
+	} else if (p_lnx_wrp_fm_port_dev->port_params.port_type ==
+		FM_PORT_TYPE_TX) {
+		snprintf(p_lnx_wrp_fm_port_dev->name,
+			 sizeof(p_lnx_wrp_fm_port_dev->name),
+			 "%s-port-tx%d",
+			 p_lnx_wrp_fm_dev->name, p_lnx_wrp_fm_port_dev->id);
+	} else if (p_lnx_wrp_fm_port_dev->port_params.port_type ==
+		FM_PORT_TYPE_OP) {
+		snprintf(p_lnx_wrp_fm_port_dev->name,
+			 sizeof(p_lnx_wrp_fm_port_dev->name),
+			 "%s-port-oh%d",
+			 p_lnx_wrp_fm_dev->name, p_lnx_wrp_fm_port_dev->id + 1);
+	}
+#ifdef FM_TX_INVALID_ECC_ERRATA_10GMAC_A009
+	if (p_lnx_wrp_fm_port_dev->fm_rev_info.major_rev < 6 &&
+	    p_lnx_wrp_fm_port_dev->fm_rev_info.major_rev != 4)
+		fm_disable_rams_ecc(p_lnx_wrp_fm_dev->h_dev);
+#endif /* FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 */
+
+	pr_debug("%s probed\n", p_lnx_wrp_fm_port_dev->name);
+
+	return 0;
+}
+
+static int fm_port_remove(struct platform_device *of_dev)
+{
+	struct lnx_wrp_fm_port_dev_t *p_lnx_wrp_fm_port_dev;
+	struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+	struct device *dev;
+
+	dev = &of_dev->dev;
+	p_lnx_wrp_fm_port_dev = dev_get_drvdata(dev);
+
+	p_lnx_wrp_fm_dev = (struct lnx_wrp_fm_dev_t *)p_lnx_wrp_fm_port_dev->
+			   h_lnx_wrp_fm_dev;
+
+	free_fm_port_dev(p_lnx_wrp_fm_port_dev);
+
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id fm_port_match[] = {
+	{
+	 .compatible = "fsl,fman-v3-port-oh"},
+	{
+	 .compatible = "fsl,fman-v2-port-oh"},
+	{
+	 .compatible = "fsl,fman-v3-port-rx"},
+	{
+	 .compatible = "fsl,fman-v2-port-rx"},
+	{
+	 .compatible = "fsl,fman-v3-port-tx"},
+	{
+	 .compatible = "fsl,fman-v2-port-tx"},
+	{}
+};
+
+#ifndef MODULE
+MODULE_DEVICE_TABLE(of, fm_port_match);
+#endif /* !MODULE */
+
+static struct platform_driver fm_port_driver = {
+	.driver = {
+		   .name = "fsl-fman-port",
+		   .of_match_table = fm_port_match,
+		   .owner = THIS_MODULE,
+		   },
+	.probe = fm_port_probe,
+	.remove = fm_port_remove
+};
+
+int lnxwrp_fm_port_init(void)
+{
+	/* Register to the DTB for basic FM port API */
+	if (platform_driver_register(&fm_port_driver))
+		return -ENODEV;
+
+	return 0;
+}
+
+void lnxwrp_fm_port_free(void)
+{
+	platform_driver_unregister(&fm_port_driver);
+}
+
+static int __init __cold fm_port_load(void)
+{
+	if (lnxwrp_fm_port_init() != 0) {
+		pr_crit("Failed to init FM Ports wrapper!\n");
+		return -ENODEV;
+	}
+
+	pr_info("Freescale FM Ports module\n");
+
+	return 0;
+}
+
+static void __exit __cold fm_port_unload(void)
+{
+	lnxwrp_fm_port_free();
+}
+
+module_init(fm_port_load);
+module_exit(fm_port_unload);
diff --git a/drivers/net/ethernet/freescale/fman/inc/fm_ext.h b/drivers/net/ethernet/freescale/fman/inc/fm_ext.h
index 33e3000..92d3eaf 100644
--- a/drivers/net/ethernet/freescale/fman/inc/fm_ext.h
+++ b/drivers/net/ethernet/freescale/fman/inc/fm_ext.h
@@ -58,6 +58,64 @@ enum fm_port_speed {
 #define FM_MAX_NUM_OF_PARTITIONS    64	 /* Maximum number of partitions */
 #define FM_PHYS_ADDRESS_SIZE        6	 /* FM Physical address size */
 
+/* FM Frame descriptor macros  */
+/* Frame queue Context Override */
+#define FM_FD_CMD_FCO                   0x80000000
+#define FM_FD_CMD_RPD                   0x40000000  /* Read Prepended Data */
+/* Update Prepended Data */
+#define FM_FD_CMD_UPD                   0x20000000
+#define FM_FD_CMD_DTC                   0x10000000  /* Do L4 Checksum */
+/* Didn't calculate L4 Checksum */
+#define FM_FD_CMD_DCL4C                 0x10000000
+/* Confirmation Frame Queue */
+#define FM_FD_CMD_CFQ                   0x00ffffff
+
+/* Not for Rx-Port! Unsupported Format */
+#define FM_FD_ERR_UNSUPPORTED_FORMAT    0x04000000
+/* Not for Rx-Port! Length Error */
+#define FM_FD_ERR_LENGTH                0x02000000
+#define FM_FD_ERR_DMA                   0x01000000  /* DMA Data error */
+
+/* IPR frame (not error) */
+#define FM_FD_IPR                       0x00000001
+/* IPR non-consistent-sp */
+#define FM_FD_ERR_IPR_NCSP              (0x00100000 | FM_FD_IPR)
+/* IPR error */
+#define FM_FD_ERR_IPR                   (0x00200000 | FM_FD_IPR)
+/* IPR timeout */
+#define FM_FD_ERR_IPR_TO                (0x00300000 | FM_FD_IPR)
+
+/* Rx FIFO overflow, FCS error, code error, running disparity error
+ * (SGMII and TBI modes), FIFO parity error. PHY Sequence error,
+ * PHY error control character detected.
+ */
+#define FM_FD_ERR_PHYSICAL              0x00080000
+/* Frame too long OR Frame size exceeds max_length_frame  */
+#define FM_FD_ERR_SIZE                  0x00040000
+/* classification discard */
+#define FM_FD_ERR_CLS_DISCARD           0x00020000
+/* Extract Out of Frame */
+#define FM_FD_ERR_EXTRACTION            0x00008000
+/* No Scheme Selected */
+#define FM_FD_ERR_NO_SCHEME             0x00004000
+/* Keysize Overflow */
+#define FM_FD_ERR_KEYSIZE_OVERFLOW      0x00002000
+/* Frame color is red */
+#define FM_FD_ERR_COLOR_RED             0x00000800
+/* Frame color is yellow */
+#define FM_FD_ERR_COLOR_YELLOW          0x00000400
+/* Parser Time out Exceed */
+#define FM_FD_ERR_PRS_TIMEOUT           0x00000080
+/* Invalid Soft Parser instruction */
+#define FM_FD_ERR_PRS_ILL_INSTRUCT      0x00000040
+/* Header error was identified during parsing */
+#define FM_FD_ERR_PRS_HDR_ERR           0x00000020
+/* Frame parsed beyind 256 first bytes */
+#define FM_FD_ERR_BLOCK_LIMIT_EXCEEDED  0x00000008
+
+/* non Frame-Manager error */
+#define FM_FD_RX_STATUS_ERR_NON_FM      0x00400000
+
 /* FM physical Address */
 struct fm_phys_addr_t {
 	uint8_t high;	      /* High part of the physical address */
diff --git a/drivers/net/ethernet/freescale/fman/inc/fm_port_ext.h b/drivers/net/ethernet/freescale/fman/inc/fm_port_ext.h
new file mode 100644
index 0000000..124f314
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/fm_port_ext.h
@@ -0,0 +1,397 @@
+/*
+ * Copyright 2008-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*File          fm_port_ext.h
+ *FM-Port Application Programming Interface.
+ */
+#ifndef __FM_PORT_EXT
+#define __FM_PORT_EXT
+
+#include "service.h"
+#include "fm_ext.h"
+#include "net_ext.h"
+
+/* FM Port API
+ * The FM uses a general module called "port" to represent a Tx port (MAC),
+ * an Rx port (MAC) or Offline Parsing port.
+ * The number of ports in an FM varies between SOCs.
+ * The SW driver manages these ports as sub-modules of the FM,i.e. after an
+ * FM is initialized, its ports may be initialized and operated upon.
+ * The port is initialized aware of its type, but other functions on a port
+ * may be indifferent to its type. When necessary, the driver verifies
+ * coherence and returns error if applicable.
+ * On initialization, user specifies the port type and it's index (relative
+ * to the port's type) - always starting at 0.
+ */
+
+/* Port interrupts */
+enum fm_port_exceptions {
+	FM_PORT_EXCEPTION_IM_BUSY	/* Independent-Mode Rx-BUSY */
+};
+
+/* General FM Port defines */
+/* Number of 4 bytes words in parser result */
+#define FM_PORT_PRS_RESULT_NUM_OF_WORDS     8
+/* @} */
+
+/* FM Frame error */
+/* Frame Descriptor errors */
+/* Not for Rx-Port! Unsupported Format */
+#define FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT	FM_FD_ERR_UNSUPPORTED_FORMAT
+/* Not for Rx-Port! Length Error */
+#define FM_PORT_FRM_ERR_LENGTH			FM_FD_ERR_LENGTH
+/* DMA Data error */
+#define FM_PORT_FRM_ERR_DMA			FM_FD_ERR_DMA
+/* non Frame-Manager error; probably come from SEC that was chained to FM */
+#define FM_PORT_FRM_ERR_NON_FM			FM_FD_RX_STATUS_ERR_NON_FM
+ /* IPR error */
+#define FM_PORT_FRM_ERR_IPRE			(FM_FD_ERR_IPR & ~FM_FD_IPR)
+/* IPR non-consistent-sp */
+#define FM_PORT_FRM_ERR_IPR_NCSP		(FM_FD_ERR_IPR_NCSP &	\
+						~FM_FD_IPR)
+
+/* Obsolete; will be removed in the future */
+#define FM_PORT_FRM_ERR_IPFE			0
+
+/* Rx FIFO overflow, FCS error, code error, running disparity
+ * error (SGMII and TBI modes), FIFO parity error.
+ * PHY Sequence error, PHY error control character detected.
+ **/
+#define FM_PORT_FRM_ERR_PHYSICAL                FM_FD_ERR_PHYSICAL
+/* Frame too long OR Frame size exceeds max_length_frame  */
+#define FM_PORT_FRM_ERR_SIZE                    FM_FD_ERR_SIZE
+/* indicates a classifier "drop" operation */
+#define FM_PORT_FRM_ERR_CLS_DISCARD             FM_FD_ERR_CLS_DISCARD
+/* Extract Out of Frame */
+#define FM_PORT_FRM_ERR_EXTRACTION              FM_FD_ERR_EXTRACTION
+/* No Scheme Selected */
+#define FM_PORT_FRM_ERR_NO_SCHEME               FM_FD_ERR_NO_SCHEME
+/* Keysize Overflow */
+#define FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW        FM_FD_ERR_KEYSIZE_OVERFLOW
+/* Frame color is red */
+#define FM_PORT_FRM_ERR_COLOR_RED               FM_FD_ERR_COLOR_RED
+/* Frame color is yellow */
+#define FM_PORT_FRM_ERR_COLOR_YELLOW            FM_FD_ERR_COLOR_YELLOW
+/* Parser Time out Exceed */
+#define FM_PORT_FRM_ERR_PRS_TIMEOUT             FM_FD_ERR_PRS_TIMEOUT
+/* Invalid Soft Parser instruction */
+#define FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT        FM_FD_ERR_PRS_ILL_INSTRUCT
+/* Header error was identified during parsing */
+#define FM_PORT_FRM_ERR_PRS_HDR_ERR             FM_FD_ERR_PRS_HDR_ERR
+/* Frame parsed beyind 256 first bytes */
+#define FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED    FM_FD_ERR_BLOCK_LIMIT_EXCEEDED
+/* FPM Frame Processing Timeout Exceeded */
+#define FM_PORT_FRM_ERR_PROCESS_TIMEOUT         0x00000001
+
+/* FM Port Initialization Unit */
+
+/*Description   Exceptions user callback routine, will be called upon an
+ *		exception passing the exception identification.
+ *  Param[in]     h_app      - User's application descriptor.
+ *  Param[in]     exception  - The exception.
+ */
+typedef void (fm_port_exception_cb) (void *h_app,
+					  enum fm_port_exceptions exception);
+
+/* A structure for additional Rx port parameters */
+struct fm_port_rx_params_t {
+	uint32_t err_fqid;			/* Error Queue Id. */
+	uint32_t dflt_fqid;			/* Default Queue Id.  */
+	uint16_t liodn_offset;			/* Port's LIODN offset. */
+	/* Which external buffer pools are used
+	 * (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes.
+	 */
+	struct fm_ext_pools_t ext_buf_pools;
+};
+
+/* A structure for additional non-Rx port parameters*/
+struct fm_port_non_rx_params_t {
+	/* Error Queue Id. */
+	uint32_t err_fqid;
+	/* For Tx - Default Confirmation queue, 0 means no Tx confirmation
+	 * for processed frames. For OP port - default Rx queue.
+	 */
+	uint32_t dflt_fqid;
+	/* QM-channel dedicated to this port; will be used
+	 * by the FM for dequeue.
+	 */
+	uint32_t qm_channel;
+};
+
+/* A union for additional parameters depending on port type*/
+union fm_port_specific_params_u {
+	/* Rx port parameters structure */
+	struct fm_port_rx_params_t rx_params;
+	/* Non-Rx port parameters structure */
+	struct fm_port_non_rx_params_t non_rx_params;
+};
+
+/* A structure representing FM initialization parameters*/
+struct fm_port_params_t {
+	uintptr_t base_addr;
+	/* Virtual Address of memory mapped FM Port registers.*/
+	void *h_fm;
+	/* A handle to the FM object this port related to */
+	enum fm_port_type port_type;
+	/* Port type */
+	enum fm_port_speed port_speed;
+	/* Port speed */
+	uint8_t port_id;
+	/* Port Id - relative to type;
+	 * NOTE: When configuring Offline Parsing port for FMANv3 devices,
+	 * it is highly recommended NOT to use port_id=0 due to lack of HW
+	 * resources on port_id=0.
+	 */
+	uint16_t liodn_base;
+	/* Irrelevant for P4080 rev 1. LIODN base for this port, to be
+	 * used together with LIODN offset.
+	 */
+	union fm_port_specific_params_u specific_params;
+	/* Additional parameters depending on port type. */
+	fm_port_exception_cb *f_exception;
+	/* Relevant for IM only Callback routine to be called on
+	 * BUSY exception.
+	 */
+	void *h_app;
+	/* A handle to an application layer object; This handle will be
+	 * passed by the driver upon calling the above callbacks
+	 */
+};
+
+struct fm_port;
+
+/*Function      fm_port_config
+ *Description   Creates a descriptor for the FM PORT module.
+ *		The routine returns a handle (descriptor) to the FM PORT object.
+ *		This descriptor must be passed as first parameter to all other
+ *		FM PORT function calls.
+ *		No actual initialization or configuration of FM hardware is
+ *		done by this routine.
+ *  Param[in]     p_fm_port_params   - Pointer to data structure of parameters
+ *  Retval        Handle to FM object, or NULL for Failure.
+ */
+void *fm_port_config(struct fm_port_params_t *p_fm_port_params);
+
+/*Function      fm_port_init
+ *Description   Initializes the FM PORT module by defining the
+ *		software structure
+ *		and configuring the hardware registers.
+ *  Param[in]     h_fm_port - FM PORT module descriptor
+ *Return        0 on success; Error code otherwise.
+ */
+int fm_port_init(void *h_fm_port);
+
+/*Function      fm_port_free
+ *Description   Frees all resources that were assigned to FM PORT module.
+ *		Calling this routine invalidates the descriptor.
+ *  Param[in]     h_fm_port - FM PORT module descriptor
+ *Return        0 on success; Error code otherwise.
+ */
+int fm_port_free(struct fm_port *port);
+
+/* Configuration functions used to change default values. */
+
+/* enum for defining QM frame dequeue*/
+enum fm_port_deq_type {
+	/* Dequeue from the SP channel - with priority precedence,
+	 * and Intra-Class Scheduling respected.
+	 */
+	FM_PORT_DEQ_TYPE1,
+	/* Dequeue from the SP channel - with active FQ precedence,
+	 * and Intra-Class Scheduling respected.
+	 */
+	FM_PORT_DEQ_TYPE2,
+	/* Dequeue from the SP channel - with active FQ precedence,
+	 * and override Intra-Class Scheduling
+	 */
+	FM_PORT_DEQ_TYPE3
+};
+
+/* enum for defining QM frame dequeue*/
+enum fm_port_deq_prefetch_option {
+	/* QMI preforms a dequeue action for a single frame only
+	 * when a dedicated portID Tnum is waiting.
+	 */
+	FM_PORT_DEQ_NO_PREFETCH,
+	/* QMI preforms a dequeue action for 3 frames when one
+	 * dedicated port_id tnum is waiting.
+	 */
+	FM_PORT_DEQ_PARTIAL_PREFETCH,
+	/* QMI preforms a dequeue action for 3 frames when
+	 * no dedicated port_id tnums are waiting.
+	 */
+	FM_PORT_DEQ_FULL_PREFETCH
+};
+
+/* enum for defining port default color*/
+enum fm_port_color {
+	FM_PORT_COLOR_GREEN,	    /* Default port color is green */
+	FM_PORT_COLOR_YELLOW,	    /* Default port color is yellow */
+	FM_PORT_COLOR_RED,	    /* Default port color is red */
+	FM_PORT_COLOR_OVERRIDE    /* Ignore color */
+};
+
+/* A structure for defining FM port resources*/
+struct fm_port_rsrc_t {
+	uint32_t num; /* Committed required resource */
+	uint32_t extra; /* Extra (not committed) required resource */
+};
+
+/*Function      fm_port_cfg_deq_high_priority
+ *Description   Calling this routine changes the dequeue priority in the
+ *		internal driver data base from its default configuration
+ *		1G: [DEFAULT_PORT_deq_high_priority_1G]
+ *		10G: [DEFAULT_PORT_deq_high_priority_10G]
+ *		May be used for Non-Rx ports only
+ *  Param[in]     h_fm_port    A handle to a FM Port module.
+ *  Param[in]     high_pri     true to select high priority, false for
+ *                              normal operation.
+ *Return        0 on success; Error code otherwise.
+ *  Cautions      Allowed only following fm_port_config() and before
+ *		fm_port_init().
+ */
+int fm_port_cfg_deq_high_priority(void *h_fm_port, bool high_pri);
+
+/*Function      fm_port_cfg_deq_prefetch_option
+ *Description   Calling this routine changes the dequeue prefetch option
+		parameter in the
+ *		internal driver data base from its default configuration
+ *		[DEFAULT_PORT_deq_prefetch_option]
+ *		Note: Available for some chips only
+ *		May be used for Non-Rx ports only
+ *  Param[in]     h_fm_port            A handle to a FM Port module.
+ *  Param[in]     deq_prefetch_option   New option
+ *Return        0 on success; Error code otherwise.
+ *  Cautions      Allowed only following fm_port_config() and before
+ *		fm_port_init().
+ */
+int fm_port_cfg_deq_prefetch_option(void *h_fm_port,
+				    enum fm_port_deq_prefetch_option
+				    deq_prefetch_option);
+
+/*Function      fm_port_cfg_buf_prefix_content
+ *Description   Defines the structure, size and content of the
+ *                 application buffer.
+ *		The prefix will
+ *		In Tx ports, if 'pass_prs_result', the application
+ *		should set a value to their offsets in the prefix of
+ *		the FM will save the first 'priv_data_size', than,
+ *		depending on 'pass_prs_result' and 'pass_time_stamp',
+ *		copy parse result and timeStamp, and the packet itself
+ *		(in this order), to the application buffer, and to offset.
+ *		Calling this routine changes the buffer margins definitions
+ *		in the internal driver data base from its default
+ *		configuration:
+ *		Data size:  [DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PRIV_DATA_SIZE]
+ *		Pass Parser result: [DEFAULT_PORT_BUFFER_PREFIX_CONTENT_
+ *		PASS_PRS_RESULT].
+ *		Pass timestamp: [DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PASS_
+ *		TIME_STAMP].
+ *		May be used for all ports
+ *  Param[in]     h_fm_port                      A handle to a FM Port module.
+ *  Param[in,out] p_fm_buffer_prefix_content   A structure of parameters
+ *						describing the
+ *						structure of the buffer.
+ *						Out parameter: Start margin -
+ *						offset
+ *						of data from start of
+ *						external buffer.
+ *Return        0 on success; Error code otherwise.
+ *  Cautions      Allowed only following fm_port_config() and before
+ *                 fm_port_init().
+ */
+int fm_port_cfg_buf_prefix_content(void *h_fm_port,
+				   struct fm_buffer_prefix_content_t *
+				    p_fm_buffer_prefix_content);
+
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+/*Function      fm_port_cfg_bcb_wa
+ *Description   Configures BCB errata workaround.
+ *		When BCB errata is applicable, the workaround is always
+ *		performed by FM Controller. Thus, this functions doesn't
+ *		actually enable errata workaround but rather allows driver
+ *		to perform adjustments required due to errata workaround
+ *		execution in FM controller.
+ *		Applying BCB workaround also configures FM_PORT_FRM_ERR_PHYSICAL
+ *		errors to be discarded. Thus FM_PORT_FRM_ERR_PHYSICAL can't be
+ *		set by FM_PORT_SetErrorsRoute() function.
+ *  Param[in]     h_fm_port            A handle to a FM Port module.
+ *Return        0 on success; Error code otherwise.
+ *  Cautions      Allowed only following fm_port_config() and before
+ *		   fm_port_init().
+ */
+int fm_port_cfg_bcb_wa(void *h_fm_port);
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+
+/* FM Port Runtime control unit API functions, definitions and enums. */
+
+/*Function      fm_port_get_buffer_time_stamp
+ *Description   Returns the time stamp in the data buffer.
+ *		Relevant for Rx ports for getting the buffer time stamp.
+ *		See fm_port_cfg_buf_prefix_content for data buffer prefix
+ *		configuration.
+ *  Param[in]     port        - FM PORT module descriptor
+ *  Param[in]     p_data      - A pointer to the data buffer.
+ *Return        A pointer to the hash result on success, NULL otherwise.
+ *  Cautions      Allowed only following fm_port_init().
+ */
+u64 *fm_port_get_buffer_time_stamp(const struct fm_port *port, char *p_data);
+
+/*Function      fm_port_disable
+ *Description   Gracefully disable an FM port. The port will not start new
+ *                 tasks after all
+ *		tasks associated with the port are terminated.
+ *  Param[in]     h_fm_port    A handle to a FM Port module.
+ *Return        0 on success; Error code otherwise.
+ *  Cautions      Allowed only following fm_port_init().
+ *		This is a blocking routine, it returns after port is
+ *		gracefully stopped, i.e. the port will not except new frames,
+ *		but it will finish all frames or tasks which were already began
+ */
+int fm_port_disable(struct fm_port *port);
+
+int fm_port_suspend(struct fm_port *port);
+/*Function      fm_port_enable
+ *Description   A runtime routine provided to allow disable/enable of port.
+ *  Param[in]     h_fm_port    A handle to a FM Port module.
+ *Return        0 on success; Error code otherwise.
+ *  Cautions      Allowed only following fm_port_init().
+ */
+int fm_port_enable(struct fm_port *port);
+
+int fm_port_resume(struct fm_port *port);
+#ifdef NCSW_BACKWARD_COMPATIBLE_API
+#define fm_port_cfg_tx_fifo_deq_pipeline_depth \
+fm_port_cfg_fifo_deq_pipeline_depth
+#endif /* NCSW_BACKWARD_COMPATIBLE_API */
+
+#endif /* __FM_PORT_EXT */
diff --git a/drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h b/drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h
index cfbf462..06bc8e9 100644
--- a/drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h
+++ b/drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h
@@ -37,10 +37,44 @@
 
 #include <linux/types.h>
 #include <linux/device.h>	/* struct device */
+#include "fm_mac_ext.h"
 
 /* FM device opaque structure used for type checking */
 struct fm;
 
+/* A structure .., */
+struct fm_port;
+
+/* A structure of information about each of the external
+ * buffer pools used by the port,
+ */
+struct fm_port_pool_param {
+	uint8_t id;			/* External buffer pool id */
+	uint16_t size;			/* External buffer pool buffer size*/
+};
+
+/* structure for additional port parameters */
+struct fm_port_params {
+	uint32_t errq;	    /* Error Queue Id. */
+	uint32_t defq;	    /* For Tx and HC - Default Confirmation queue,
+			     * 0 means no Tx conf for processed frames.
+			     *  For Rx and OP - default Rx queue.
+			     */
+	uint8_t num_pools;  /* Number of pools use by this port */
+	struct fm_port_pool_param pool_param[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+			    /* Parameters for each pool */
+	uint16_t priv_data_size;  /* Area that user may save for his own
+				   * need (E.g. save the SKB)
+				   */
+	bool parse_results; /* Put the parser-results in the Rx/Tx buffer */
+	bool hash_results;  /* Put the hash-results in the Rx/Tx buffer */
+	bool time_stamp;    /* Put the time-stamp in the Rx/Tx buffer */
+	uint16_t data_align;  /* value for selecting a data alignment
+			       * (must be a power of 2);
+			       * if write optimization is used, must be >= 16.
+			       */
+};
+
 /* fm_bind
  *	Bind to a specific FM device.
  *
@@ -60,6 +94,70 @@ void fm_unbind(struct fm *fm);
 void *fm_get_handle(struct fm *fm);
 struct resource *fm_get_mem_region(struct fm *fm);
 
+/*	fm_port_bind
+ *	Bind to a specific FM-port device (may be Rx or Tx port).
+ *  fm_port_dev - the OF handle of the FM port device.
+ *  Return	A handle of the FM port device.
+ *  Allowed only after the port was created.
+ */
+struct fm_port *fm_port_bind(struct device *fm_port_dev);
+
+/*	fm_port_unbind
+ *	Un-bind from a specific FM-port device (may be Rx or Tx port).
+ *  port	- A handle of the FM port device.
+ *  Allowed only after the port was created.
+ */
+void fm_port_unbind(struct fm_port *port);
+
+/* fm_set_rx_port_params
+ *	Configure parameters for a specific Rx FM-port device.
+ *  port	- A handle of the FM port device.
+ *  params	- Rx port parameters
+ *  Allowed only after the port is binded.
+ */
+void fm_set_rx_port_params(struct fm_port *port, struct fm_port_params *params);
+
+/*	fm_port_get_buff_layout_ext_params
+ *	Get data_align from the device tree chosen node if applied.
+ *		This function will only update these two parameters.
+ *		When this port has no such parameters in the device tree
+ *		values will be set to 0.
+ *	port	- A handle of the FM port device.
+ *	params	- PCD port parameters
+ *	Allowed only after the port is binded.
+ */
+void fm_port_get_buff_layout_ext_params(struct fm_port *port,
+					struct fm_port_params *params);
+
+/*	fm_get_tx_port_channel
+ *	Get qman-channel number for this Tx port.
+ *	port	- A handle of the FM port device.
+ *  Return	qman-channel number for this Tx port.
+ *	Allowed only after the port is binded.
+ */
+int fm_get_tx_port_channel(struct fm_port *port);
+
+/*	fm_set_tx_port_params
+ *	Configure parameters for a specific Tx FM-port device
+ *	port	- A handle of the FM port device.
+ *	params	- Tx port parameters
+ *	Allowed only after the port is binded.
+ */
+void fm_set_tx_port_params(struct fm_port *port, struct fm_port_params *params);
+
+void *fm_port_get_handle(const struct fm_port *port);
+
+/*	fm_port_get_base_address
+ *
+ *	Get base address of this port. Useful for accessing
+ *		port-specific registers (i.e., not common ones).
+ *
+ *	port		- A handle of the FM port device.
+ *
+ *	base_addr	- The port's base addr (virtual address).
+ */
+void fm_port_get_base_addr(const struct fm_port *port, uint64_t *base_addr);
+
 /*	fm_mutex_lock
  *
  *   Lock function required before any FMD/LLD call.
diff --git a/drivers/net/ethernet/freescale/fman/port/Makefile b/drivers/net/ethernet/freescale/fman/port/Makefile
index 54b1fa4..55825e3 100644
--- a/drivers/net/ethernet/freescale/fman/port/Makefile
+++ b/drivers/net/ethernet/freescale/fman/port/Makefile
@@ -1,3 +1,3 @@
 obj-y	+= fsl_fman_port.o
 
-fsl_fman_port-objs		:= fman_port.o
+fsl_fman_port-objs		:= fman_port.o fm_port.o
diff --git a/drivers/net/ethernet/freescale/fman/port/fm_port.c b/drivers/net/ethernet/freescale/fman/port/fm_port.c
new file mode 100644
index 0000000..f0db7fb
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/port/fm_port.c
@@ -0,0 +1,1484 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* File          fm_port.c
+ * Description   FM driver routines implementation.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "fm_muram_ext.h"
+
+#include "fman_common.h"
+#include "fm_port.h"
+#include "dpaa_integration_ext.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/*       static functions               */
+
+static int check_init_parameters(struct fm_port_t *p_fm_port)
+{
+	struct fm_port_drv_param_t *p_params = p_fm_port->
+	p_fm_port_drv_param;
+	struct fman_port_cfg *p_dflt_config = &p_params->dflt_cfg;
+	uint32_t unused_mask;
+
+	/* Rx only */
+	if (p_fm_port->port_type == FM_PORT_TYPE_RX) {
+		/* external buffer pools */
+		if (!p_params->ext_buf_pools.num_of_pools_used) {
+			pr_err("ext_buf_pools.num_of_pools_used=0. At least one buffer pool must be defined\n");
+			return -EDOM;
+		}
+
+		if (fm_sp_check_buf_pools_params(&p_params->ext_buf_pools,
+						 p_params->p_backup_bm_pools,
+			&p_params->buf_pool_depletion,
+			p_fm_port->port_intg->max_num_of_ext_pools,
+			p_fm_port->port_intg->bm_max_num_of_pools) != 0)
+			return -EDOM;
+		/* Check that part of IC that needs copying is small enough
+		 * to enter start margin
+		 */
+		if (p_params->int_context.size &&
+		    (p_params->int_context.size +
+		     p_params->int_context.ext_buf_offset >
+		     p_params->buf_margins.start_margins)) {
+			pr_err("int_context.size is larger than start margins\n");
+			return -EDOM;
+		}
+
+		if ((p_params->liodn_offset != DPAA_LIODN_DONT_OVERRIDE) &&
+		    (p_params->liodn_offset & ~FM_LIODN_OFFSET_MASK)) {
+			pr_err("liodn_offset is larger than %d\n",
+			       FM_LIODN_OFFSET_MASK + 1);
+		}
+#ifdef FM_NO_BACKUP_POOLS
+		if ((p_fm_port->fm_rev_info.major_rev != 4) &&
+		    (p_fm_port->fm_rev_info.major_rev < 6))
+			if (p_fm_port->p_fm_port_drv_param->
+			    p_backup_bm_pools) {
+				pr_err("BackupBmPools\n");
+				return -ENOSYS;
+			}
+#endif /* FM_NO_BACKUP_POOLS */
+	}
+
+	/*   Non Rx ports                       */
+	else {
+		if (p_params->deq_sub_portal >=
+		    p_fm_port->port_intg->fm_max_num_of_sub_portals) {
+			pr_err("deq_sub_portal has to be in the range of 0 - %d\n",
+			       p_fm_port->port_intg->fm_max_num_of_sub_portals);
+			return -EDOM;
+		}
+
+		/* to protect HW internal-context from overwrite */
+		if ((p_params->int_context.size) &&
+		    (p_params->int_context.int_context_offset <
+		     MIN_TX_INT_OFFSET)) {
+			pr_err("non-Rx int_context.int_context_offset can't be smaller than %d\n",
+			       MIN_TX_INT_OFFSET);
+			return -EDOM;
+		}
+
+		if ((p_fm_port->port_type == FM_PORT_TYPE_TX) ||
+		    /* in O/H DEFAULT_NOT_SUPPORTED indicates that
+		     * it is not supported and should not be checked
+		     */
+		    (p_fm_port->p_fm_port_drv_param->dflt_cfg.
+		     tx_fifo_deq_pipeline_depth != DEFAULT_NOT_SUPPORTED)) {
+			/* Check that not larger than 8 */
+			if ((!p_fm_port->p_fm_port_drv_param->dflt_cfg.
+			     tx_fifo_deq_pipeline_depth) ||
+				(p_fm_port->p_fm_port_drv_param->dflt_cfg.
+				tx_fifo_deq_pipeline_depth >
+				MAX_FIFO_PIPELINE_DEPTH)) {
+				pr_err("fifoDeqPipelineDepth can't be larger than %d\n",
+				       MAX_FIFO_PIPELINE_DEPTH);
+				return -EDOM;
+			}
+		}
+	}
+
+	/* Rx Or Offline Parsing */
+	if ((p_fm_port->port_type == FM_PORT_TYPE_RX) ||
+	    (p_fm_port->port_type == FM_PORT_TYPE_OP)) {
+		if (!p_params->dflt_fqid) {
+			pr_err("dflt_fqid must be between 1 and 2^24-1\n");
+			return -EDOM;
+		}
+	}
+
+	/*   All ports                          */
+	/* common BMI registers values */
+	/* Check that Queue Id is not larger than 2^24, and is not 0 */
+	if ((p_params->err_fqid & ~0x00FFFFFF) || !p_params->err_fqid) {
+		pr_err("err_fqid must be between 1 and 2^24-1\n");
+		return -EDOM;
+	}
+	if (p_params->dflt_fqid & ~0x00FFFFFF) {
+		pr_err("dflt_fqid must be between 1 and 2^24-1\n");
+		return -EDOM;
+	}
+
+	/* Rx only */
+	if (p_fm_port->port_type == FM_PORT_TYPE_RX) {
+		if (p_dflt_config->rx_pri_elevation % BMI_FIFO_UNITS) {
+			pr_err("rx_fifo_pri_elevation_level has to be divisible by %d\n",
+			       BMI_FIFO_UNITS);
+			return -EDOM;
+		}
+		if ((p_dflt_config->rx_pri_elevation < BMI_FIFO_UNITS) ||
+		    (p_dflt_config->rx_pri_elevation >
+		     p_fm_port->port_intg->max_port_fifo_size)) {
+			pr_err("rx_fifo_pri_elevation_level not in range of 256 - %d\n",
+			       p_fm_port->port_intg->max_port_fifo_size);
+			return -EDOM;
+		}
+		if (p_dflt_config->rx_fifo_thr % BMI_FIFO_UNITS) {
+			pr_err("rx_fifo_threshold must be div by %d\n",
+			       BMI_FIFO_UNITS);
+			return -EDOM;
+		}
+		if ((p_dflt_config->rx_fifo_thr < BMI_FIFO_UNITS) ||
+		    (p_dflt_config->rx_fifo_thr >
+		     p_fm_port->port_intg->max_port_fifo_size)) {
+			pr_err("rx_fifo_threshold has to be in the range of 256 - %d\n",
+			       p_fm_port->port_intg->max_port_fifo_size);
+			return -EDOM;
+		}
+
+		/* Check that not larger than 16 */
+		if (p_dflt_config->rx_cut_end_bytes > FRAME_END_DATA_SIZE) {
+			pr_err("cut_bytes_from_end can't be larger than %d\n",
+			       FRAME_END_DATA_SIZE);
+			return -EDOM;
+		}
+
+		if (fm_sp_check_buf_margins(&p_params->buf_margins) != 0)
+			return -EDOM;
+
+		/* extra FIFO size (allowed only to Rx ports) */
+		if (p_params->set_size_of_fifo &&
+		    (p_fm_port->fifo_bufs.extra % BMI_FIFO_UNITS)) {
+			pr_err("fifo_bufs.extra has to be divisible by %d\n",
+			       BMI_FIFO_UNITS);
+			return -EDOM;
+		}
+
+		if (p_params->buf_pool_depletion.pools_grp_mode_enable &&
+		    !p_params->buf_pool_depletion.num_of_pools) {
+			pr_err("buf_pool_depletion.num_of_pools can not be 0 when pools_grp_mode_enable=true\n");
+			return -EDOM;
+		}
+#ifdef FM_CSI_CFED_LIMIT
+		if (p_fm_port->fm_rev_info.major_rev == 4) {
+			/* Check that not larger than 16 */
+			if (p_dflt_config->rx_cut_end_bytes +
+			    p_dflt_config->checksum_bytes_ignore >
+			    FRAME_END_DATA_SIZE) {
+				pr_err("cheksum_last_bytes_ignore + cut_bytes_from_end can't be larger than %d\n",
+				       FRAME_END_DATA_SIZE);
+				return -EDOM;
+			}
+		}
+#endif /* FM_CSI_CFED_LIMIT */
+	}
+
+	/* Non Rx ports */
+	/* extra FIFO size (allowed only to Rx ports) */
+	else if (p_fm_port->fifo_bufs.extra) {
+		pr_err(" No fifo_bufs.extra for non Rx ports\n");
+		return -EDOM;
+	}
+
+	/* Tx only */
+	if (p_fm_port->port_type == FM_PORT_TYPE_TX) {
+		if (p_dflt_config->tx_fifo_min_level % BMI_FIFO_UNITS) {
+			pr_err("tx_fifo_min_fill_level has to be divisible by %d\n",
+			       BMI_FIFO_UNITS);
+			return -EDOM;
+		}
+		if (p_dflt_config->tx_fifo_min_level >
+		    (p_fm_port->port_intg->max_port_fifo_size - 256)) {
+			pr_err("tx_fifo_min_fill_level has to be in the range of 0 - %d\n",
+			       (p_fm_port->port_intg->max_port_fifo_size -
+				256));
+			return -EDOM;
+		}
+		if (p_dflt_config->tx_fifo_low_comf_level % BMI_FIFO_UNITS) {
+			pr_err("tx_fifo_low_comf_level has to be divisible by %d\n",
+			       BMI_FIFO_UNITS);
+			return -EDOM;
+		}
+		if ((p_dflt_config->tx_fifo_low_comf_level < BMI_FIFO_UNITS) ||
+		    (p_dflt_config->tx_fifo_low_comf_level >
+		     p_fm_port->port_intg->max_port_fifo_size)) {
+			pr_err("tx_fifo_low_comf_level has to be in the range of 256 - %d\n",
+			       p_fm_port->port_intg->max_port_fifo_size);
+			return -EDOM;
+		}
+		if (p_fm_port->port_speed == FM_PORT_SPEED_1G)
+			if (p_fm_port->p_fm_port_drv_param->dflt_cfg.
+			    tx_fifo_deq_pipeline_depth > 2) {
+				pr_err("fifoDeqPipelineDepth for 1G can't be larger than 2\n");
+				return -EDOM;
+			}
+	}
+
+	/*   Non Tx Ports                       */
+	/* If discard override was selected , no frames may be discarded. */
+	else if (p_dflt_config->discard_override && p_params->
+		 errors_to_discard) {
+		pr_err("errors_to_discard is not empty, but frm_discard_override selected (all discarded frames to be enqueued to error queue).\n");
+		return -ENOSYS;
+	}
+
+	/* Rx and Offline parsing */
+	if ((p_fm_port->port_type == FM_PORT_TYPE_RX) ||
+	    (p_fm_port->port_type == FM_PORT_TYPE_OP)) {
+		if (p_fm_port->port_type == FM_PORT_TYPE_OP)
+			unused_mask = BMI_STATUS_OP_MASK_UNUSED;
+		else
+			unused_mask = BMI_STATUS_RX_MASK_UNUSED;
+
+		/* Check that no common bits with BMI_STATUS_MASK_UNUSED */
+		if (p_params->errors_to_discard & unused_mask) {
+			pr_err("errors_to_discard contains undefined bits\n");
+			return -ENOSYS;
+		}
+	}
+
+	/* Offline Ports */
+#ifdef FM_OP_OPEN_DMA_MIN_LIMIT
+	if ((p_fm_port->fm_rev_info.major_rev >= 6) &&
+	    (p_fm_port->port_type == FM_PORT_TYPE_OP) &&
+	    p_params->set_num_of_open_dmas &&
+	    (p_fm_port->open_dmas.num < MIN_NUM_OF_OP_DMAS)) {
+		pr_err("For Offline port, open_dmas.num can't be smaller than %d\n",
+		       MIN_NUM_OF_OP_DMAS);
+		return -EDOM;
+	}
+#endif /* FM_OP_OPEN_DMA_MIN_LIMIT */
+
+	/* Offline Ports */
+	if (p_fm_port->port_type == FM_PORT_TYPE_OP) {
+#ifndef FM_FRAME_END_PARAMS_FOR_OP
+		if ((p_fm_port->fm_rev_info.major_rev < 6) &&
+		    (p_fm_port->p_fm_port_drv_param->
+		     cheksum_last_bytes_ignore !=
+		     DEFAULT_NOT_SUPPORTED)) {
+			/* this is an indication that user called config
+			 * for this mode which is not supported in this
+			 * integration
+			 */
+			pr_err("cheksum_last_bytes_ignore is available for Rx&Tx ports only\n");
+			return -EDOM;
+		}
+#endif /* !FM_FRAME_END_PARAMS_FOR_OP */
+
+#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP
+		if ((!((p_fm_port->fm_rev_info.major_rev == 4) ||
+		       (p_fm_port->fm_rev_info.major_rev >= 6))) &&
+		    (p_fm_port->p_fm_port_drv_param->dflt_cfg.
+		     tx_fifo_deq_pipeline_depth != DEFAULT_NOT_SUPPORTED)) {
+			/* this is an indication that user called config for
+			 * this mode which is not supported in this integration
+			 **/
+			pr_err("fifoDeqPipelineDepth is available for Tx ports only\n");
+			return -ENOSYS;
+		}
+#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */
+	}
+
+	/*   All ports                          */
+
+	/* Check that not larger than 16 */
+	if ((p_params->cheksum_last_bytes_ignore > FRAME_END_DATA_SIZE) &&
+	    ((p_params->cheksum_last_bytes_ignore != DEFAULT_NOT_SUPPORTED))) {
+		pr_err("cheksum_last_bytes_ignore can't be larger than %d\n",
+		       FRAME_END_DATA_SIZE);
+		return -EDOM;
+	}
+
+	if (fm_sp_check_int_context_params(&p_params->int_context) != 0)
+		return -EDOM;
+
+	/* common BMI registers values */
+	if (p_params->set_num_of_tasks &&
+	    ((!p_fm_port->tasks.num) ||
+	     (p_fm_port->tasks.num > MAX_NUM_OF_TASKS))) {
+		pr_err("tasks.num can't be larger than %d\n",
+		       MAX_NUM_OF_TASKS);
+		return -EDOM;
+	}
+	if (p_params->set_num_of_tasks &&
+	    (p_fm_port->tasks.extra > MAX_NUM_OF_EXTRA_TASKS)) {
+		pr_err("tasks.extra can't be larger than %d\n",
+		       MAX_NUM_OF_EXTRA_TASKS);
+		return -EDOM;
+	}
+	if (p_params->set_num_of_open_dmas &&
+	    ((!p_fm_port->open_dmas.num) ||
+	     (p_fm_port->open_dmas.num > MAX_NUM_OF_DMAS))) {
+		pr_err("open_dmas.num can't be larger than %d\n",
+		       MAX_NUM_OF_DMAS);
+		return -EDOM;
+	}
+	if (p_params->set_num_of_open_dmas &&
+	    (p_fm_port->open_dmas.extra > MAX_NUM_OF_EXTRA_DMAS)) {
+		pr_err("open_dmas.extra can't be larger than %d\n",
+		       MAX_NUM_OF_EXTRA_DMAS);
+		return -EDOM;
+	}
+	if (p_params->set_size_of_fifo &&
+	    (!p_fm_port->fifo_bufs.num || (p_fm_port->fifo_bufs.num >
+	     p_fm_port->port_intg->max_port_fifo_size))) {
+		pr_err("fifo_bufs.num has to be in the range of 256 - %d\n",
+		       p_fm_port->port_intg->max_port_fifo_size);
+		return -EDOM;
+	}
+	if (p_params->set_size_of_fifo &&
+	    (p_fm_port->fifo_bufs.num % BMI_FIFO_UNITS)) {
+		pr_err("fifo_bufs.num has to be divisible by %d\n",
+		       BMI_FIFO_UNITS);
+		return -EDOM;
+	}
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+	if (p_fm_port->fm_rev_info.major_rev == 4)
+		if (p_fm_port->p_fm_port_drv_param->deq_prefetch_option !=
+		    DEFAULT_NOT_SUPPORTED) {
+			/* this is an indication that user called config
+			 * for this mode which is not supported in this
+			 * integration
+			 **/
+			pr_err("deq_prefetch_option\n");
+			return -ENOSYS;
+		}
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+	return 0;
+}
+
+/* Checks if p_fm_port driver parameters were initialized
+ * returns 0 if success else returns error code
+ */
+static int is_init_done(struct fm_port_drv_param_t *p_fm_port_drv_parameters)
+{
+	if (!p_fm_port_drv_parameters)
+		return 0;
+	return -ENOSYS;
+}
+
+static int verify_size_of_fifo(struct fm_port_t *p_fm_port)
+{
+	uint32_t min_fifo_size_required = 0, opt_fifo_size_for_b2b = 0;
+
+	/* TX PORTS */
+	if (p_fm_port->port_type == FM_PORT_TYPE_TX) {
+		min_fifo_size_required = (uint32_t)
+		    (ROUND_UP(p_fm_port->max_frame_length,
+			      BMI_FIFO_UNITS) + (3 * BMI_FIFO_UNITS));
+
+		min_fifo_size_required +=
+		    p_fm_port->p_fm_port_drv_param->
+		    dflt_cfg.tx_fifo_deq_pipeline_depth * BMI_FIFO_UNITS;
+
+		opt_fifo_size_for_b2b = min_fifo_size_required;
+
+		/* Add some margin for back-to-back capability to improve
+		 * performance, allows the hardware to pipeline new frame dma
+		 * while the previous frame not yet transmitted.
+		 */
+		if (p_fm_port->port_speed == FM_PORT_SPEED_10G)
+			opt_fifo_size_for_b2b += 3 * BMI_FIFO_UNITS;
+		else
+			opt_fifo_size_for_b2b += 2 * BMI_FIFO_UNITS;
+	}
+
+	/* RX PORTS */
+	else if (p_fm_port->port_type == FM_PORT_TYPE_RX) {
+		if (p_fm_port->fm_rev_info.major_rev == 4) {
+			if (p_fm_port->rx_pools_params.num_of_pools == 1)
+				min_fifo_size_required = 8 * BMI_FIFO_UNITS;
+			else
+				min_fifo_size_required = (uint32_t)
+				    (ROUND_UP
+				     (p_fm_port->
+				      rx_pools_params.second_largest_buf_size,
+				      BMI_FIFO_UNITS) + (7 * BMI_FIFO_UNITS));
+		} else {
+			if (p_fm_port->fm_rev_info.major_rev >= 6)
+				min_fifo_size_required = (uint32_t)
+				(ROUND_UP(p_fm_port->max_frame_length,
+					BMI_FIFO_UNITS) + (5 * BMI_FIFO_UNITS));
+				/* 4 according to spec + 1 for FOF>0 */
+			else
+				min_fifo_size_required = (uint32_t)
+				(ROUND_UP(min(p_fm_port->max_frame_length,
+						p_fm_port->rx_pools_params.
+						largest_buf_size),
+					BMI_FIFO_UNITS) + (7 * BMI_FIFO_UNITS));
+		}
+
+		opt_fifo_size_for_b2b = min_fifo_size_required;
+
+		/* Add some margin for back-to-back capability to improve
+		 * performance,allows the hardware to pipeline new frame dma
+		 * while the previous frame not yet transmitted.
+		 */
+		if (p_fm_port->port_speed == FM_PORT_SPEED_10G)
+			opt_fifo_size_for_b2b += 8 * BMI_FIFO_UNITS;
+		else
+			opt_fifo_size_for_b2b += 3 * BMI_FIFO_UNITS;
+	}
+
+	/* For O/H ports, check fifo size and update if necessary */
+	else if (p_fm_port->port_type == FM_PORT_TYPE_OP) {
+		if (p_fm_port->fm_rev_info.major_rev >= 6) {
+			opt_fifo_size_for_b2b =  (uint32_t)(ROUND_UP(
+				p_fm_port->max_frame_length,
+				BMI_FIFO_UNITS) +
+				((p_fm_port->p_fm_port_drv_param->dflt_cfg.
+				tx_fifo_deq_pipeline_depth + 5) *
+				BMI_FIFO_UNITS));
+			min_fifo_size_required = opt_fifo_size_for_b2b;
+		/* 4 according to spec + 1 for FOF>0 */
+		} else {
+			opt_fifo_size_for_b2b =
+			(uint32_t)((p_fm_port->tasks.num + 2) * BMI_FIFO_UNITS);
+			min_fifo_size_required = opt_fifo_size_for_b2b;
+		}
+	}
+
+	ASSERT(min_fifo_size_required > 0);
+	ASSERT(opt_fifo_size_for_b2b >= min_fifo_size_required);
+
+	/* Verify the size  */
+	if (p_fm_port->fifo_bufs.num < min_fifo_size_required)
+		pr_debug("FIFO size should be enlarged to %d bytes\n",
+			 min_fifo_size_required);
+	else if (p_fm_port->fifo_bufs.num < opt_fifo_size_for_b2b)
+		pr_debug("For b2b processing,FIFO may be enlarged to %d bytes\n",
+			 opt_fifo_size_for_b2b);
+
+	return 0;
+}
+
+static void fm_port_drv_param_free(struct fm_port_t *p_fm_port)
+{
+	kfree(p_fm_port->p_fm_port_drv_param);
+	p_fm_port->p_fm_port_drv_param = NULL;
+}
+
+static int set_ext_buffer_pools(struct fm_port_t *p_fm_port)
+{
+	struct fm_ext_pools_t *p_ext_buf_pools =
+	    &p_fm_port->p_fm_port_drv_param->ext_buf_pools;
+	struct fm_buf_pool_depletion_t *p_buf_pool_depletion =
+	    &p_fm_port->p_fm_port_drv_param->buf_pool_depletion;
+	uint8_t ordered_array[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+	uint16_t sizes_array[BM_MAX_NUM_OF_POOLS];
+	int i = 0, j = 0, err;
+	struct fman_port_bpools bpools;
+
+	memset(&ordered_array, 0,
+	       sizeof(uint8_t) * FM_PORT_MAX_NUM_OF_EXT_POOLS);
+	memset(&sizes_array, 0, sizeof(uint16_t) * BM_MAX_NUM_OF_POOLS);
+	memcpy(&p_fm_port->ext_buf_pools, p_ext_buf_pools,
+	       sizeof(struct fm_ext_pools_t));
+
+	fm_sp_set_buf_pools_in_asc_order_of_buf_sizes(p_ext_buf_pools,
+						      ordered_array,
+						      sizes_array);
+
+	/* Prepare flibs bpools structure */
+	memset(&bpools, 0, sizeof(struct fman_port_bpools));
+	bpools.count = p_ext_buf_pools->num_of_pools_used;
+	bpools.counters_enable = true;
+	for (i = 0; i < p_ext_buf_pools->num_of_pools_used; i++) {
+		bpools.bpool[i].bpid = ordered_array[i];
+		bpools.bpool[i].size = sizes_array[ordered_array[i]];
+		/* functionality available only for some derivatives
+		 * (limited by config)
+		 */
+		if (p_fm_port->p_fm_port_drv_param->p_backup_bm_pools)
+			for (j = 0; j < p_fm_port->p_fm_port_drv_param->
+			     p_backup_bm_pools->num_of_backup_pools; j++)
+				if (ordered_array[i] ==
+				    p_fm_port->p_fm_port_drv_param->
+				    p_backup_bm_pools->pool_ids[j]) {
+					bpools.bpool[i].is_backup = true;
+					break;
+				}
+	}
+
+	/* save pools parameters for later use */
+	p_fm_port->rx_pools_params.num_of_pools =
+	p_ext_buf_pools->num_of_pools_used;
+	p_fm_port->rx_pools_params.largest_buf_size =
+	    sizes_array[ordered_array[p_ext_buf_pools->
+		num_of_pools_used - 1]];
+	p_fm_port->rx_pools_params.second_largest_buf_size =
+	    sizes_array[ordered_array[p_ext_buf_pools->
+		num_of_pools_used - 2]];
+
+	/* FMBM_RMPD reg. - pool depletion */
+	if (p_buf_pool_depletion->pools_grp_mode_enable) {
+		bpools.grp_bp_depleted_num = p_buf_pool_depletion->
+num_of_pools;
+		for (i = 0; i < p_fm_port->port_intg->bm_max_num_of_pools;
+		     i++) {
+			if (p_buf_pool_depletion->pools_to_consider[i]) {
+				for (j = 0; j < p_ext_buf_pools->
+				     num_of_pools_used; j++) {
+					if (i == ordered_array[j]) {
+						bpools.bpool[j].
+						    grp_bp_depleted = true;
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	if (p_buf_pool_depletion->single_pool_mode_enable) {
+		for (i = 0; i < p_fm_port->port_intg->bm_max_num_of_pools;
+		     i++) {
+			if (p_buf_pool_depletion->
+			    pools_to_consider_for_single_mode[i]) {
+				for (j = 0; j < p_ext_buf_pools->
+				     num_of_pools_used; j++) {
+					if (i == ordered_array[j]) {
+						bpools.bpool[j].
+						    single_bp_depleted = true;
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	/* Issue flibs function */
+	err = fman_port_set_bpools(&p_fm_port->port, &bpools);
+	if (err != 0) {
+		pr_err("fman_port_set_bpools\n");
+		return -EDOM;
+	}
+
+	kfree(p_fm_port->p_fm_port_drv_param->p_backup_bm_pools);
+
+	return 0;
+}
+
+static int init_low_level_driver(struct fm_port_t *p_fm_port)
+{
+	struct fm_port_drv_param_t *p_drv_params = p_fm_port->
+	p_fm_port_drv_param;
+	struct fman_port_params port_params;
+	uint32_t tmp_val;
+
+	/* Set up flibs parameters and issue init function */
+
+	memset(&port_params, 0, sizeof(struct fman_port_params));
+	port_params.discard_mask = p_drv_params->errors_to_discard;
+	port_params.dflt_fqid = p_drv_params->dflt_fqid;
+	port_params.err_fqid = p_drv_params->err_fqid;
+	port_params.deq_sp = p_drv_params->deq_sub_portal;
+	port_params.dont_release_buf = p_drv_params->dont_release_buf;
+	switch (p_fm_port->port_type) {
+	case (FM_PORT_TYPE_RX):
+		port_params.err_mask =
+			(RX_ERRS_TO_ENQ & ~port_params.discard_mask);
+		if (p_drv_params->forward_reuse_int_context)
+			p_drv_params->dflt_cfg.rx_fd_bits =
+			    (uint8_t)(BMI_PORT_RFNE_FRWD_RPD >> 24);
+		break;
+
+	case (FM_PORT_TYPE_OP):
+		port_params.err_mask =
+			(OP_ERRS_TO_ENQ & ~port_params.discard_mask);
+		break;
+		break;
+
+	default:
+		break;
+	}
+
+	tmp_val = (uint32_t)((p_fm_port->internal_buf_offset %
+			     OFFSET_UNITS) ? (p_fm_port->
+			     internal_buf_offset / OFFSET_UNITS +
+			      1) : (p_fm_port->internal_buf_offset /
+				    OFFSET_UNITS));
+	p_fm_port->internal_buf_offset = (uint8_t)(tmp_val * OFFSET_UNITS);
+	p_drv_params->dflt_cfg.int_buf_start_margin =
+	    p_fm_port->internal_buf_offset;
+
+	p_drv_params->dflt_cfg.ext_buf_start_margin =
+	    p_drv_params->buf_margins.start_margins;
+	p_drv_params->dflt_cfg.ext_buf_end_margin =
+	    p_drv_params->buf_margins.end_margins;
+
+	p_drv_params->dflt_cfg.ic_ext_offset =
+	    p_drv_params->int_context.ext_buf_offset;
+	p_drv_params->dflt_cfg.ic_int_offset =
+	    p_drv_params->int_context.int_context_offset;
+	p_drv_params->dflt_cfg.ic_size = p_drv_params->int_context.size;
+
+	p_drv_params->dflt_cfg.stats_counters_enable = true;
+	p_drv_params->dflt_cfg.perf_counters_enable = true;
+	p_drv_params->dflt_cfg.queue_counters_enable = true;
+
+	p_drv_params->dflt_cfg.perf_cnt_params.task_val =
+	    (uint8_t)p_fm_port->tasks.num;
+	if (p_fm_port->port_type == FM_PORT_TYPE_OP)
+		p_drv_params->dflt_cfg.perf_cnt_params.queue_val = 0;
+	else
+		p_drv_params->dflt_cfg.perf_cnt_params.queue_val = 1;
+	p_drv_params->dflt_cfg.perf_cnt_params.dma_val =
+	    (uint8_t)p_fm_port->open_dmas.num;
+	p_drv_params->dflt_cfg.perf_cnt_params.fifo_val =
+	    p_fm_port->fifo_bufs.num;
+
+	if (0 !=
+	    fman_port_init(&p_fm_port->port, &p_drv_params->dflt_cfg,
+			   &port_params)) {
+		pr_err("fman_port_init\n");
+		return -ENODEV;
+	}
+
+	/* The code bellow is a trick so the FM will not release the buffer
+	 * to BM nor will try to enqueue the frame to QM
+	 */
+	if (p_fm_port->port_type == FM_PORT_TYPE_TX) {
+		if (!p_drv_params->dflt_fqid && p_drv_params->
+		    dont_release_buf) {
+			/* override fmbm_tcfqid 0 with a false non-0 value.
+			 * This will force FM to act according to tfene.
+			 * Otherwise, if fmbm_tcfqid is 0 the FM will release
+			 * buffers to BM regardless of fmbm_tfene
+			 */
+			WRITE_UINT32(p_fm_port->port.bmi_regs->tx.fmbm_tcfqid,
+				     0xFFFFFF);
+			WRITE_UINT32(p_fm_port->port.bmi_regs->tx.fmbm_tfene,
+				     NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
+		}
+	}
+
+	return 0;
+}
+
+static struct fm_port_intg_t *set_port_intg_params(struct fm_port_t *p_fm_port)
+{
+	struct fm_port_intg_t *intg;
+	uint32_t bmi_max_fifo_size;
+
+	intg = kzalloc(sizeof(*intg), GFP_KERNEL);
+	if (!intg)
+		return NULL;
+
+	bmi_max_fifo_size = fm_get_bmi_max_fifo_size(p_fm_port->h_fm);
+
+	intg->max_port_fifo_size =
+				MAX_PORT_FIFO_SIZE(bmi_max_fifo_size);
+
+	switch (p_fm_port->fm_rev_info.major_rev) {
+	case FM_IP_BLOCK_P2_P3_P5:
+	case FM_IP_BLOCK_P4:
+		intg->max_num_of_ext_pools		= 4;
+		intg->fm_max_num_of_sub_portals		= 12;
+		intg->bm_max_num_of_pools		= 64;
+		break;
+
+	case FM_IP_BLOCK_P1:
+		intg->max_num_of_ext_pools		= 4;
+		intg->fm_max_num_of_sub_portals		= 7;
+		intg->bm_max_num_of_pools		= 8;
+		break;
+
+	case FM_IP_BLOCK_B_T:
+		intg->max_num_of_ext_pools		= 8;
+		intg->fm_max_num_of_sub_portals		= 16;
+		intg->bm_max_num_of_pools		= 64;
+		break;
+
+	default:
+		pr_err("Unsupported FMan version\n");
+		kfree(intg);
+		return NULL;
+	}
+
+	return intg;
+}
+
+/*       API Init unit functions        */
+
+void *fm_port_config(struct fm_port_params_t *p_fm_port_params)
+{
+	struct fm_port_t *p_fm_port;
+	uintptr_t base_addr = p_fm_port_params->base_addr;
+#ifdef FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127
+	uint32_t tmp_reg;
+#endif /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 */
+	enum fman_port_type fman_port_type = E_FMAN_PORT_TYPE_DUMMY;
+
+	/* Allocate FM structure */
+	p_fm_port = kzalloc(sizeof(*p_fm_port), GFP_KERNEL);
+	if (!p_fm_port)
+		return NULL;
+
+	/* Allocate the FM driver's parameters structure */
+	p_fm_port->p_fm_port_drv_param =
+	kzalloc(sizeof(*p_fm_port->p_fm_port_drv_param),
+		GFP_KERNEL);
+	if (!p_fm_port->p_fm_port_drv_param) {
+		kfree(p_fm_port);
+		pr_err("FM Port driver parameters\n");
+		return NULL;
+	}
+
+	/* Initialize FM port parameters which will be kept by the driver */
+	p_fm_port->port_type = p_fm_port_params->port_type;
+	p_fm_port->port_speed = p_fm_port_params->port_speed;
+	p_fm_port->port_id = p_fm_port_params->port_id;
+	p_fm_port->f_exception = p_fm_port_params->f_exception;
+	p_fm_port->h_app = p_fm_port_params->h_app;
+	p_fm_port->h_fm = p_fm_port_params->h_fm;
+
+	/* get FM revision */
+	fm_get_revision(p_fm_port->h_fm, &p_fm_port->fm_rev_info);
+
+	p_fm_port->port_intg = set_port_intg_params(p_fm_port);
+	if (!p_fm_port->port_intg) {
+			kfree(p_fm_port->p_fm_port_drv_param);
+			kfree(p_fm_port);
+			return NULL;
+	}
+
+	if (p_fm_port->fm_rev_info.major_rev >= 6) {
+		if ((p_fm_port->port_type == FM_PORT_TYPE_OP) &&
+		    (p_fm_port_params->port_id == FM_OH_PORT_ID))
+			pr_debug("Use nonzero portid for OP port\n");
+	}
+
+	/* Set up FM port parameters for initialization phase only */
+
+	/* First, fill in flibs struct */
+	/* In order to be aligned with flib port types, we need to translate
+	 * the port type and speed to fman_port_type
+	 */
+	if (p_fm_port->port_type == FM_PORT_TYPE_OP) {
+		fman_port_type = E_FMAN_PORT_TYPE_OP;
+	} else if (p_fm_port->port_type == FM_PORT_TYPE_TX) {
+		if (p_fm_port->port_speed == FM_PORT_SPEED_10G)
+			fman_port_type = E_FMAN_PORT_TYPE_TX_10G;
+		else
+			fman_port_type = E_FMAN_PORT_TYPE_TX;
+	} else if (p_fm_port->port_type == FM_PORT_TYPE_RX) {
+		if (p_fm_port->port_speed == FM_PORT_SPEED_10G)
+			fman_port_type = E_FMAN_PORT_TYPE_RX_10G;
+		else
+			fman_port_type = E_FMAN_PORT_TYPE_RX;
+	}
+	fman_port_defconfig(&p_fm_port->p_fm_port_drv_param->dflt_cfg,
+			    fman_port_type);
+	/* Overwrite some integration specific parameters */
+	p_fm_port->p_fm_port_drv_param->dflt_cfg.rx_pri_elevation =
+		DFLT_PORT_RX_FIFO_PRI_ELEVATION_LEV(
+				p_fm_port->port_intg->max_port_fifo_size);
+	p_fm_port->p_fm_port_drv_param->dflt_cfg.rx_fifo_thr =
+	p_fm_port->p_fm_port_drv_param->rx_fifo_threshold =
+	DFLT_PORT_RX_FIFO_THRESHOLD(
+				    p_fm_port->fm_rev_info.major_rev,
+				    p_fm_port->port_intg->max_port_fifo_size);
+
+	p_fm_port->p_fm_port_drv_param->dflt_cfg.errata_A006675 = false;
+
+#if defined(FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675) || \
+defined(FM_ERROR_VSP_NO_MATCH_SW006)
+	if (p_fm_port->fm_rev_info.major_rev >= 6)
+		p_fm_port->p_fm_port_drv_param->dflt_cfg.errata_A006675 =
+		true;
+#endif
+	if ((p_fm_port->fm_rev_info.major_rev == 6) &&
+	    ((p_fm_port->fm_rev_info.minor_rev == 0) ||
+	     (p_fm_port->fm_rev_info.minor_rev == 3)))
+		p_fm_port->p_fm_port_drv_param->dflt_cfg.errata_A006320 =
+		true;
+	else
+		p_fm_port->p_fm_port_drv_param->dflt_cfg.errata_A006320 =
+		false;
+
+	/* Excessive Threshold register - exists for pre-FMv3 chips only */
+	if (p_fm_port->fm_rev_info.major_rev < 6) {
+#ifdef FM_NO_RESTRICT_ON_ACCESS_RSRC
+		p_fm_port->p_fm_port_drv_param->dflt_cfg.
+		    excessive_threshold_register = true;
+#endif /* FM_NO_RESTRICT_ON_ACCESS_RSRC */
+		p_fm_port->p_fm_port_drv_param->dflt_cfg.fmbm_rebm_has_sgd =
+		    false;
+		p_fm_port->p_fm_port_drv_param->
+		dflt_cfg.fmbm_tfne_has_features =
+		    false;
+	} else {
+		p_fm_port->p_fm_port_drv_param->dflt_cfg.
+		    excessive_threshold_register = false;
+		p_fm_port->p_fm_port_drv_param->dflt_cfg.fmbm_rebm_has_sgd =
+		true;
+		p_fm_port->p_fm_port_drv_param->
+		dflt_cfg.fmbm_tfne_has_features = true;
+	}
+	if (p_fm_port->fm_rev_info.major_rev == 4)
+		p_fm_port->p_fm_port_drv_param->
+		dflt_cfg.qmi_deq_options_support = false;
+	else
+		p_fm_port->p_fm_port_drv_param->
+		dflt_cfg.qmi_deq_options_support = true;
+
+	/* Continue with other parameters */
+	p_fm_port->p_fm_port_drv_param->base_addr = base_addr;
+	/* set memory map pointers */
+	p_fm_port->p_fm_port_qmi_regs =
+	    (struct fm_port_qmi_regs_t __iomem *)UINT_TO_PTR(base_addr +
+	QMI_PORT_REGS_OFFSET);
+	p_fm_port->p_fm_port_bmi_regs =
+	    (union fm_port_bmi_regs_u __iomem *)UINT_TO_PTR(base_addr +
+	BMI_PORT_REGS_OFFSET);
+
+	p_fm_port->p_fm_port_drv_param->
+	buffer_prefix_content.priv_data_size =
+	    DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PRIV_DATA_SIZE;
+	p_fm_port->p_fm_port_drv_param->
+	buffer_prefix_content.pass_prs_result =
+	    DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PASS_PRS_RESULT;
+	p_fm_port->p_fm_port_drv_param->
+	buffer_prefix_content.pass_time_stamp =
+	    DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PASS_TIME_STAMP;
+	p_fm_port->p_fm_port_drv_param->buffer_prefix_content.data_align =
+	    DEFAULT_PORT_BUFFER_PREFIX_CONTEXT_DATA_ALIGN;
+	p_fm_port->p_fm_port_drv_param->liodn_base =
+	    p_fm_port_params->liodn_base;
+	p_fm_port->p_fm_port_drv_param->cheksum_last_bytes_ignore =
+	    DEFAULT_PORT_cheksum_last_bytes_ignore;
+
+	p_fm_port->max_frame_length = DEFAULT_PORT_max_frame_length;
+	/* resource distribution. */
+
+	p_fm_port->fifo_bufs.num =
+	DFLT_PORT_NUM_OF_FIFO_BUFS(p_fm_port->fm_rev_info.major_rev,
+				   p_fm_port->port_type,
+				   p_fm_port->port_speed) * BMI_FIFO_UNITS;
+	p_fm_port->fifo_bufs.extra =
+	DFLT_PORT_EXTRA_NUM_OF_FIFO_BUFS * BMI_FIFO_UNITS;
+
+	p_fm_port->open_dmas.num =
+	DFLT_PORT_NUM_OF_OPEN_DMAS(p_fm_port->fm_rev_info.major_rev,
+				   p_fm_port->port_type,
+				   p_fm_port->port_speed);
+	p_fm_port->open_dmas.extra =
+	DFLT_PORT_EXTRA_NUM_OF_OPEN_DMAS(p_fm_port->fm_rev_info.major_rev,
+					 p_fm_port->port_type,
+					 p_fm_port->port_speed);
+	p_fm_port->tasks.num =
+	DFLT_PORT_NUM_OF_TASKS(p_fm_port->fm_rev_info.major_rev,
+			       p_fm_port->port_type,
+			       p_fm_port->port_speed);
+	p_fm_port->tasks.extra =
+	DFLT_PORT_EXTRA_NUM_OF_TASKS(p_fm_port->fm_rev_info.major_rev,
+				     p_fm_port->port_type,
+				     p_fm_port->port_speed);
+
+#ifdef FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981
+	if ((p_fm_port->fm_rev_info.major_rev == 6) &&
+	    (p_fm_port->fm_rev_info.minor_rev == 0) &&
+	    ((p_fm_port->port_type == FM_PORT_TYPE_OP) ||
+	     ((p_fm_port->port_type == FM_PORT_TYPE_TX) &&
+	     (p_fm_port->port_speed == FM_PORT_SPEED_1G)))) {
+		p_fm_port->open_dmas.num = 16;
+		p_fm_port->open_dmas.extra = 0;
+	}
+#endif /* FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 */
+
+	/* Port type specific initialization: */
+	switch (p_fm_port->port_type) {
+	case (FM_PORT_TYPE_RX):
+		/* Initialize FM port parameters for initialization phase only*/
+		p_fm_port->p_fm_port_drv_param->cut_bytes_from_end =
+		    DEFAULT_PORT_cut_bytes_from_end;
+		p_fm_port->p_fm_port_drv_param->en_buf_pool_depletion =
+		false;
+		p_fm_port->p_fm_port_drv_param->frm_discard_override =
+		    DEFAULT_PORT_frm_discard_override;
+
+		p_fm_port->p_fm_port_drv_param->rx_fifo_pri_elevation_level =
+		DFLT_PORT_RX_FIFO_PRI_ELEVATION_LEV(p_fm_port->port_intg->
+						    max_port_fifo_size);
+		p_fm_port->p_fm_port_drv_param->rx_fifo_threshold =
+		DFLT_PORT_RX_FIFO_THRESHOLD(p_fm_port->fm_rev_info.major_rev,
+					    p_fm_port->port_intg->
+					    max_port_fifo_size);
+
+		p_fm_port->p_fm_port_drv_param->buf_margins.end_margins =
+		    DEFAULT_PORT_BUF_MARGINS_END_MAARGINS;
+		p_fm_port->p_fm_port_drv_param->errors_to_discard =
+		    DEFAULT_PORT_errors_to_discard;
+		p_fm_port->p_fm_port_drv_param->forward_reuse_int_context =
+		    DEFAULT_PORT_FORWARD_INT_CONTENT_REUSE;
+		break;
+
+	case (FM_PORT_TYPE_TX):
+		if (p_fm_port->port_speed == FM_PORT_SPEED_1G) {
+			p_fm_port->p_fm_port_drv_param->dont_release_buf =
+			false;
+#ifdef FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127
+			if (p_fm_port->fm_rev_info.major_rev >= 6) {
+				tmp_reg = 0x00001013;
+				WRITE_UINT32(p_fm_port->p_fm_port_bmi_regs->
+					     tx_port_bmi_regs.fmbm_tfp,
+					     tmp_reg);
+			}
+#endif /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 */
+		}
+		if (p_fm_port->port_speed == FM_PORT_SPEED_10G) {
+			p_fm_port->p_fm_port_drv_param->tx_fifo_min_fill_level
+			= DFLT_PORT_TX_FIFO_MIN_FILL_LEVEL;
+			p_fm_port->p_fm_port_drv_param->tx_fifo_low_comf_level
+			= DFLT_PORT_TX_FIFO_LOW_COMF_LEVEL;
+
+			p_fm_port->p_fm_port_drv_param->deq_type =
+			DEFAULT_PORT_deq_type;
+			p_fm_port->p_fm_port_drv_param->deq_prefetch_option =
+			DEFAULT_PORT_deq_prefetch_option;
+		}
+		p_fm_port->p_fm_port_drv_param->deq_high_priority =
+			DFLT_PORT_DEQ_HIGH_PRIORITY(p_fm_port->port_speed);
+		p_fm_port->p_fm_port_drv_param->deq_byte_cnt =
+			DFLT_PORT_DEQ_BYTE_CNT(p_fm_port->port_speed);
+		p_fm_port->p_fm_port_drv_param->dflt_cfg.
+			tx_fifo_deq_pipeline_depth = (uint8_t)
+			DFLT_PORT_FIFO_DEQ_PIPELINE_DEPTH(
+				     p_fm_port->fm_rev_info.major_rev,
+				     p_fm_port->port_type,
+				     p_fm_port->port_speed);
+		break;
+	case (FM_PORT_TYPE_OP):
+		p_fm_port->p_fm_port_drv_param->errors_to_discard =
+		    DEFAULT_PORT_errors_to_discard;
+		break;
+
+	default:
+		kfree(p_fm_port->p_fm_port_drv_param);
+		kfree(p_fm_port);
+		pr_err("Invalid port type\n");
+		return NULL;
+	}
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+	if (p_fm_port->fm_rev_info.major_rev == 4)
+		p_fm_port->p_fm_port_drv_param->deq_prefetch_option =
+		    (enum fm_port_deq_prefetch_option)DEFAULT_NOT_SUPPORTED;
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+	switch (p_fm_port->port_type) {
+	case (FM_PORT_TYPE_RX):
+		/* Initialize FM port parameters for initialization phase only*/
+		memcpy(&p_fm_port->p_fm_port_drv_param->ext_buf_pools,
+		       &p_fm_port_params->
+			specific_params.rx_params.ext_buf_pools,
+		       sizeof(struct fm_ext_pools_t));
+		p_fm_port->p_fm_port_drv_param->err_fqid
+		    = p_fm_port_params->specific_params.rx_params.err_fqid;
+		p_fm_port->p_fm_port_drv_param->dflt_fqid
+		    = p_fm_port_params->specific_params.rx_params.dflt_fqid;
+		p_fm_port->p_fm_port_drv_param->liodn_offset
+		    = p_fm_port_params->specific_params.rx_params.liodn_offset;
+		break;
+	case (FM_PORT_TYPE_OP):
+	case (FM_PORT_TYPE_TX):
+		p_fm_port->p_fm_port_drv_param->err_fqid =
+		    p_fm_port_params->specific_params.non_rx_params.err_fqid;
+		p_fm_port->p_fm_port_drv_param->deq_sub_portal =
+		    (uint8_t)(p_fm_port_params->specific_params.non_rx_params.
+			       qm_channel & QMI_DEQ_CFG_SUBPORTAL_MASK);
+		p_fm_port->p_fm_port_drv_param->dflt_fqid =
+		    p_fm_port_params->specific_params.non_rx_params.dflt_fqid;
+		break;
+	default:
+		kfree(p_fm_port->p_fm_port_drv_param);
+		kfree(p_fm_port);
+		pr_err("Invalid port type\n");
+		return NULL;
+	}
+
+	memset(p_fm_port->name, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+	if (snprintf(p_fm_port->name, MODULE_NAME_SIZE, "FM-%d-port-%s-%d",
+		     fm_get_id(p_fm_port->h_fm),
+		     ((p_fm_port->port_type == FM_PORT_TYPE_OP) ? "OP" :
+		     ((p_fm_port->port_type == FM_PORT_TYPE_TX) ?
+		     ((p_fm_port->port_speed == FM_PORT_SPEED_10G) ? "10g-TX" :
+		     "1g-TX") :
+		     ((p_fm_port->port_speed == FM_PORT_SPEED_10G) ? "10g-RX" :
+		     "1g-RX"))),
+		     p_fm_port->port_id) == 0) {
+		kfree(p_fm_port->p_fm_port_drv_param);
+		kfree(p_fm_port);
+		pr_err("sprintf failed\n");
+		return NULL;
+	}
+
+	p_fm_port->spinlock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+	if (!p_fm_port->spinlock) {
+		kfree(p_fm_port->p_fm_port_drv_param);
+		kfree(p_fm_port);
+		pr_err("Spin lock init failed\n");
+		return NULL;
+	}
+
+	spin_lock_init(p_fm_port->spinlock);
+
+	return p_fm_port;
+}
+
+/* Function      fm_port_init
+ * Description   Initializes the FM module
+ * Param[in]     h_fm_port - FM module descriptor
+ * Return        0 on success; Error code otherwise.
+ */
+int fm_port_init(void *h_fm_port)
+{
+	struct fm_port_t *p_fm_port = (struct fm_port_t *)h_fm_port;
+	struct fm_port_drv_param_t *p_drv_params;
+	int err_code;
+	struct fm_inter_module_port_init_params_t fm_params;
+	struct fm_revision_info_t rev_info;
+	int ret, ret_err;
+	enum fman_port_type fman_port_type = E_FMAN_PORT_TYPE_DUMMY;
+
+	ret = is_init_done(p_fm_port->p_fm_port_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	err_code =
+	    fm_sp_build_buffer_structure(&p_fm_port->p_fm_port_drv_param->
+					 int_context,
+					 &p_fm_port->p_fm_port_drv_param->
+					 buffer_prefix_content,
+					 &p_fm_port->p_fm_port_drv_param->
+					 buf_margins,
+					 &p_fm_port->buffer_offsets,
+					 &p_fm_port->internal_buf_offset);
+	if (err_code != 0)
+		return -err_code;
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+	if (p_fm_port->fm_rev_info.major_rev >= 6 &&
+	    (p_fm_port->p_fm_port_drv_param->bcb_workaround) &&
+	    ((p_fm_port->port_type == FM_PORT_TYPE_RX) &&
+	    (p_fm_port->port_speed == FM_PORT_SPEED_1G))) {
+		p_fm_port->p_fm_port_drv_param->errors_to_discard |=
+		    FM_PORT_FRM_ERR_PHYSICAL;
+		if (!p_fm_port->fifo_bufs.num)
+			p_fm_port->fifo_bufs.num =
+				DFLT_PORT_NUM_OF_FIFO_BUFS(
+					p_fm_port->fm_rev_info.major_rev,
+					p_fm_port->port_type,
+					p_fm_port->port_speed) *
+					BMI_FIFO_UNITS;
+		p_fm_port->fifo_bufs.num += 4 * 1024;
+	}
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+
+	ret_err = check_init_parameters(p_fm_port);
+	if (ret_err)
+		return ret_err;
+
+	p_drv_params = p_fm_port->p_fm_port_drv_param;
+
+	/* Set up flibs port structure */
+	memset(&p_fm_port->port, 0, sizeof(struct fman_port));
+	/* In order to be aligned with flib port types, we need to translate
+	 * the port type and speed to fman_port_type
+	 */
+	if (p_fm_port->port_type == FM_PORT_TYPE_OP) {
+		fman_port_type = E_FMAN_PORT_TYPE_OP;
+	} else if (p_fm_port->port_type == FM_PORT_TYPE_TX) {
+		if (p_fm_port->port_speed == FM_PORT_SPEED_10G)
+			fman_port_type = E_FMAN_PORT_TYPE_TX_10G;
+		else
+			fman_port_type = E_FMAN_PORT_TYPE_TX;
+	} else if (p_fm_port->port_type == FM_PORT_TYPE_RX) {
+		if (p_fm_port->port_speed == FM_PORT_SPEED_10G)
+			fman_port_type = E_FMAN_PORT_TYPE_RX_10G;
+		else
+			fman_port_type = E_FMAN_PORT_TYPE_RX;
+	}
+	p_fm_port->port.type = fman_port_type;
+	fm_get_revision(p_fm_port->h_fm, &rev_info);
+	p_fm_port->port.fm_rev_maj = rev_info.major_rev;
+	p_fm_port->port.fm_rev_min = rev_info.minor_rev;
+	p_fm_port->port.bmi_regs = (union fman_port_bmi_regs __iomem *)
+	    UINT_TO_PTR(p_drv_params->base_addr + BMI_PORT_REGS_OFFSET);
+	p_fm_port->port.qmi_regs = (struct fman_port_qmi_regs __iomem *)
+	    UINT_TO_PTR(p_drv_params->base_addr + QMI_PORT_REGS_OFFSET);
+	p_fm_port->port.ext_pools_num =
+	    (uint8_t)((rev_info.major_rev == 4) ? 4 : 8);
+
+	if (p_fm_port->port_type == FM_PORT_TYPE_RX) {
+		/* Call the external Buffer routine which also checks fifo
+		 * size and updates it if necessary
+		 */
+		/* define external buffer pools and pool depletion */
+		err_code = set_ext_buffer_pools(p_fm_port);
+		if (err_code)
+			return -err_code;
+		/* check if the largest external buffer pool is large enough */
+		if (p_drv_params->buf_margins.start_margins +
+		    MIN_EXT_BUF_SIZE +
+		    p_drv_params->buf_margins.end_margins >
+		    p_fm_port->rx_pools_params.largest_buf_size) {
+			pr_err("buf_margins.start_margins (%d) + minimum buf size (64) + buf_margins.end_margins (%d) is larger than maximum external buffer size (%d)\n",
+			       p_drv_params->buf_margins.start_margins,
+			       p_drv_params->buf_margins.end_margins,
+			       p_fm_port->rx_pools_params.largest_buf_size);
+			return -ENOSYS;
+		}
+	}
+	if (p_fm_port->port_type == FM_PORT_TYPE_OP) {
+		{
+#ifdef FM_NO_OP_OBSERVED_POOLS
+			struct fm_revision_info_t rev_info;
+
+			fm_get_revision(p_fm_port->h_fm, &rev_info);
+		if ((rev_info.major_rev == 4) &&
+		    (p_drv_params->en_buf_pool_depletion))
+#endif /* FM_NO_OP_OBSERVED_POOLS */
+			{
+				/* define external buffer pools */
+				err_code = set_ext_buffer_pools(p_fm_port);
+				if (err_code)
+					return -err_code;
+			}
+		}
+	}
+
+	/* Call FM module routine for communicating parameters      */
+
+	memset(&fm_params, 0, sizeof(fm_params));
+	fm_params.port_id = p_fm_port->port_id;
+	fm_params.port_type = (enum fm_port_type)p_fm_port->port_type;
+	fm_params.port_speed = (enum fm_port_speed)p_fm_port->port_speed;
+	fm_params.num_of_tasks = (uint8_t)p_fm_port->tasks.num;
+	fm_params.num_of_extra_tasks = (uint8_t)p_fm_port->tasks.extra;
+	fm_params.num_of_open_dmas = (uint8_t)p_fm_port->open_dmas.num;
+	fm_params.num_of_extra_open_dmas = (uint8_t)p_fm_port->open_dmas.extra;
+
+	if (p_fm_port->fifo_bufs.num) {
+		err_code = verify_size_of_fifo(p_fm_port);
+		if (err_code != 0)
+			return -err_code;
+	}
+	fm_params.size_of_fifo = p_fm_port->fifo_bufs.num;
+	fm_params.extra_size_of_fifo = p_fm_port->fifo_bufs.extra;
+	fm_params.liodn_offset = p_drv_params->liodn_offset;
+	fm_params.liodn_base = p_drv_params->liodn_base;
+	fm_params.deq_pipeline_depth =
+	    p_fm_port->p_fm_port_drv_param->
+	    dflt_cfg.tx_fifo_deq_pipeline_depth;
+	fm_params.max_frame_length = p_fm_port->max_frame_length;
+#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP
+	if (p_fm_port->port_type == FM_PORT_TYPE_OP) {
+		if (!((p_fm_port->fm_rev_info.major_rev == 4) ||
+		      (p_fm_port->fm_rev_info.major_rev >= 6)))
+			/* OP ports do not have fifoDeqPipelineDepth,
+			 * but it is needed only
+			 *for deq threshold calculation.
+			 */
+			fm_params.deq_pipeline_depth = 2;
+	}
+#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */
+
+	err_code = fm_get_set_port_params(p_fm_port->h_fm, &fm_params);
+	if (err_code)
+		return -err_code;
+
+	err_code = init_low_level_driver(p_fm_port);
+	if (err_code != 0)
+		return -err_code;
+
+	fm_port_drv_param_free(p_fm_port);
+
+	return 0;
+}
+
+void *fm_port_get_handle(const struct fm_port *port);
+
+/* Function      fm_port_free
+ * Description   Frees all resources that were assigned to FM module.
+ *		 Calling this routine invalidates the descriptor.
+ * Param[in]     h_fm_port - FM module descriptor
+ * Return        0 on success; Error code otherwise.
+ */
+int fm_port_free(struct fm_port *port)
+{
+	struct fm_port_t *p_fm_port =
+		(struct fm_port_t *)fm_port_get_handle(port);
+	struct fm_inter_module_port_free_params_t fm_params;
+
+	if (p_fm_port->enabled) {
+		if (fm_port_disable(port) != 0) {
+			pr_err("fm_port_disable FAILED\n");
+			return -ENOSYS;
+		}
+	}
+
+	fm_port_drv_param_free(p_fm_port);
+
+	fm_params.port_id = p_fm_port->port_id;
+	fm_params.port_type = (enum fm_port_type)p_fm_port->port_type;
+	fm_params.deq_pipeline_depth =
+	    p_fm_port->p_fm_port_drv_param->
+	    dflt_cfg.tx_fifo_deq_pipeline_depth;
+
+	fm_free_port_params(p_fm_port->h_fm, &fm_params);
+
+	kfree(p_fm_port->spinlock);
+
+	kfree(p_fm_port);
+
+	return 0;
+}
+
+/*       API Advanced Init unit functions        */
+
+int fm_port_cfg_deq_high_priority(void *h_fm_port, bool high_pri)
+{
+	struct fm_port_t *p_fm_port = (struct fm_port_t *)h_fm_port;
+	int ret;
+
+	ret = is_init_done(p_fm_port->p_fm_port_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	if (p_fm_port->port_type == FM_PORT_TYPE_RX) {
+		pr_err("not available for Rx ports\n");
+		return -ENOMEM;
+	}
+
+	p_fm_port->p_fm_port_drv_param->dflt_cfg.deq_high_pri = high_pri;
+
+	return 0;
+}
+
+int fm_port_cfg_deq_prefetch_option(void *h_fm_port,
+				    enum fm_port_deq_prefetch_option
+				    deq_prefetch_option)
+{
+	struct fm_port_t *p_fm_port = (struct fm_port_t *)h_fm_port;
+	int ret;
+
+	ret = is_init_done(p_fm_port->p_fm_port_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	if (p_fm_port->port_type == FM_PORT_TYPE_RX) {
+		pr_err("not available for Rx ports\n");
+		return -ENODEV;
+	}
+	p_fm_port->p_fm_port_drv_param->dflt_cfg.deq_prefetch_opt =
+	    (enum fman_port_deq_prefetch)deq_prefetch_option;
+
+	return 0;
+}
+
+int fm_port_cfg_buf_prefix_content(void *h_fm_port,
+				   struct fm_buffer_prefix_content_t *
+				   p_fm_buffer_prefix_content)
+{
+	struct fm_port_t *p_fm_port = (struct fm_port_t *)h_fm_port;
+	int ret;
+
+	ret = is_init_done(p_fm_port->p_fm_port_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	memcpy(&p_fm_port->p_fm_port_drv_param->buffer_prefix_content,
+	       p_fm_buffer_prefix_content,
+	       sizeof(struct fm_buffer_prefix_content_t));
+	/* if data_align was not initialized by user,
+	 * we return to driver's default
+	 **/
+	if (!p_fm_port->p_fm_port_drv_param->
+	    buffer_prefix_content.data_align)
+		p_fm_port->p_fm_port_drv_param->
+		buffer_prefix_content.data_align =
+		    DEFAULT_PORT_BUFFER_PREFIX_CONTEXT_DATA_ALIGN;
+
+	return 0;
+}
+
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+int fm_port_cfg_bcb_wa(void *h_fm_port)
+{
+	struct fm_port_t *p_fm_port = (struct fm_port_t *)h_fm_port;
+	int ret;
+
+	ret = is_init_done(p_fm_port->p_fm_port_drv_param);
+	if (!ret)
+		return -ENOSYS;
+
+	p_fm_port->p_fm_port_drv_param->bcb_workaround = true;
+
+	return 0;
+}
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+
+/*       API Run-time Control unit functions        */
+
+u64 *fm_port_get_buffer_time_stamp(const struct fm_port *port, char *p_data)
+{
+	struct fm_port_t *p_fm_port =
+		(struct fm_port_t *)fm_port_get_handle(port);
+	int ret;
+
+	ret = is_init_done(p_fm_port->p_fm_port_drv_param);
+	if (ret)
+		return NULL;
+
+	if (p_fm_port->buffer_offsets.time_stamp_offset == ILLEGAL_BASE)
+		return NULL;
+
+	return (uint64_t *)PTR_MOVE(p_data,
+				    p_fm_port->
+				    buffer_offsets.time_stamp_offset);
+}
+EXPORT_SYMBOL(fm_port_get_buffer_time_stamp);
+
+int fm_port_disable(struct fm_port *port)
+{
+	struct fm_port_t *p_fm_port =
+		(struct fm_port_t *)fm_port_get_handle(port);
+	int err, ret;
+
+	ret = is_init_done(p_fm_port->p_fm_port_drv_param);
+	if (ret)
+		return ret;
+
+	err = fman_port_disable(&p_fm_port->port);
+	if (err == -EBUSY) {
+		pr_debug("%s: BMI or QMI is Busy. Port forced down\n",
+			 p_fm_port->name);
+		err = 0;
+	}
+
+	p_fm_port->enabled = false;
+
+	return err;
+}
+EXPORT_SYMBOL(fm_port_disable);
+
+int fm_port_suspend(struct fm_port *port)
+{
+	struct fm_port_t *p_fm_port =
+		(struct fm_port_t *)fm_port_get_handle(port);
+	int err, ret;
+
+	ret = is_init_done(p_fm_port->p_fm_port_drv_param);
+	if (ret)
+		return ret;
+
+	err = fman_port_disable(&p_fm_port->port);
+	if (err == -EBUSY) {
+		pr_debug("%s: BMI or QMI is Busy. Port forced down\n",
+			 p_fm_port->name);
+		err = 0;
+	}
+
+	p_fm_port->enabled = false;
+
+	return err;
+}
+EXPORT_SYMBOL(fm_port_suspend);
+
+int fm_port_enable(struct fm_port *port)
+{
+	struct fm_port_t *p_fm_port =
+		(struct fm_port_t *)fm_port_get_handle(port);
+	int err, ret;
+
+	ret = is_init_done(p_fm_port->p_fm_port_drv_param);
+	if (ret)
+		return ret;
+
+	/* Used by fm_port_free routine as indication
+	 * if to disable port. Thus set it to true prior
+	 * to enabling itself. This way if part of enable
+	 * process fails there will be still things
+	 * to disable during Free. For example, if BMI
+	 * enable succeeded but QMI failed, still  BMI
+	 * needs to be disabled by Free.
+	 */
+	p_fm_port->enabled = true;
+
+	err = fman_port_enable(&p_fm_port->port);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_port_enable);
+
+int fm_port_resume(struct fm_port *port)
+{
+	struct fm_port_t *p_fm_port =
+		(struct fm_port_t *)fm_port_get_handle(port);
+	int err, ret;
+
+	ret = is_init_done(p_fm_port->p_fm_port_drv_param);
+	if (ret)
+		return ret;
+
+	/* Used by fm_port_free routine as indication
+	 * if to disable port. Thus set it to true prior
+	 * to enabling itself. This way if part of enable
+	 * process fails there will be still things
+	 * to disable during Free. For example, if BMI
+	 * enable succeeded but QMI failed, still  BMI
+	 * needs to be disabled by Free.
+	 */
+	p_fm_port->enabled = true;
+
+	err = fman_port_enable(&p_fm_port->port);
+
+	return err;
+}
+EXPORT_SYMBOL(fm_port_resume);
diff --git a/drivers/net/ethernet/freescale/fman/port/fm_port.h b/drivers/net/ethernet/freescale/fman/port/fm_port.h
new file mode 100644
index 0000000..c0f2cd6
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/port/fm_port.h
@@ -0,0 +1,711 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* FM Port internal structures and definitions. */
+#ifndef __FM_PORT_H
+#define __FM_PORT_H
+
+#include "service.h"
+
+#include "fm_common.h"
+#include "fm_sp_common.h"
+#include "fsl_fman_sp.h"
+#include "fm_port_ext.h"
+#include "fsl_fman_port.h"
+
+#define MIN_EXT_BUF_SIZE                                64
+#define DATA_ALIGNMENT                                  64
+#define MAX_LIODN_OFFSET                                64
+
+#define MAX_PORT_FIFO_SIZE(bmi_max_fifo_size)	\
+	min((u32)bmi_max_fifo_size, (u32)1024 * BMI_FIFO_UNITS)
+
+/* Memory Map defines */
+#define BMI_PORT_REGS_OFFSET                            0
+#define QMI_PORT_REGS_OFFSET                            0x400
+#define PRS_PORT_REGS_OFFSET                            0x800
+
+/* defaults */
+#define DFLT_PORT_DEQ_HIGH_PRIORITY(speed)	\
+	((speed == FM_PORT_SPEED_10G) ? true : false)
+#define DEFAULT_PORT_deq_type                            FM_PORT_DEQ_TYPE1
+#define DEFAULT_PORT_deq_prefetch_option FM_PORT_DEQ_FULL_PREFETCH
+#define DEFAULT_PORT_deq_prefetch_option_HC FM_PORT_DEQ_NO_PREFETCH
+#define DFLT_PORT_DEQ_BYTE_CNT(speed)	\
+	((speed == FM_PORT_SPEED_10G) ? 0x1400 : 0x400)
+#define DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PRIV_DATA_SIZE \
+DEFAULT_FM_SP_BUFFER_PREFIX_CONTENT_PRIV_DATA_SIZE
+#define DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PASS_PRS_RESULT \
+DEFAULT_FM_SP_BUFFER_PREFIX_CONTENT_PRIV_PASS_PRS_RESULT
+#define DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PASS_TIME_STAMP  \
+DEFAULT_FM_SP_BUFFER_PREFIX_CONTEXT_PASS_TIME_STAMP
+#define DEFAULT_PORT_BUFFER_PREFIX_CONTEXT_DATA_ALIGN      \
+DEFAULT_FM_SP_BUFFER_PREFIX_CONTEXT_DATA_ALIGN
+#define DEFAULT_PORT_cheksum_last_bytes_ignore             0
+#define DEFAULT_PORT_cut_bytes_from_end                    4
+
+#define DEFAULT_PORT_frm_discard_override                 false
+
+#define DEFAULT_PORT_FORWARD_INT_CONTENT_REUSE             false
+#define DEFAULT_PORT_BUF_MARGINS_END_MAARGINS		0
+#define DEFAULT_PORT_sync_req                            true
+#define DEFAULT_PORT_color                              FM_PORT_COLOR_GREEN
+#define DEFAULT_PORT_errors_to_discard                    \
+FM_PORT_FRM_ERR_CLS_DISCARD
+#define DEFAULT_PORT_exception                          IM_EV_BSY
+#define DEFAULT_PORT_max_frame_length                     9600
+
+#define DEFAULT_NOT_SUPPORTED                            0xff
+
+#define DFLT_PORT_RX_FIFO_PRI_ELEVATION_LEV(bmi_max_fifo_size)	\
+	MAX_PORT_FIFO_SIZE(bmi_max_fifo_size)
+
+#define DFLT_PORT_RX_FIFO_THRESHOLD(major, bmi_max_fifo_size)	\
+	(major == 6 ?						\
+	MAX_PORT_FIFO_SIZE(bmi_max_fifo_size) :		\
+	(MAX_PORT_FIFO_SIZE(bmi_max_fifo_size) * 3 / 4))	\
+
+#define DFLT_PORT_TX_FIFO_MIN_FILL_LEVEL		0
+#define DFLT_PORT_TX_FIFO_LOW_COMF_LEVEL		(5 * 1024)
+
+/* OP - 2, 10G - 4, 1G (FMAN V3 - 2, FMAN V2 - 1) */
+#define DFLT_PORT_FIFO_DEQ_PIPELINE_DEPTH(major, type, speed)		\
+	((type == FM_PORT_TYPE_OP) ? 2 :				\
+		((speed == FM_PORT_SPEED_10G) ? 4 :			\
+		((major >= 6) ? 2 : 1)))
+
+#define DFLT_PORT_EXTRA_NUM_OF_FIFO_BUFS		0
+
+/* FMAN V3: OP - 6, 10G (RX/TX 16), 1G (RX/TX) 4
+ * FMAN V2: OP - 3, 10G (TX/TX 16), 1G (RX/TX) 3
+ */
+#define DFLT_PORT_NUM_OF_TASKS(major, type, speed)			\
+	((major >= 6) ?							\
+	((type == FM_PORT_TYPE_OP) ? 6 :				\
+		((speed == FM_PORT_SPEED_10G) ? 16 : 4)) :		\
+	((speed == FM_PORT_SPEED_10G) ? 16 : 3))
+
+/* FMAN V3: 0 for all ports
+ * FMAN V2: RX 10G - 8, RX 1G 2, TX/OP - 0
+ */
+#define DFLT_PORT_EXTRA_NUM_OF_TASKS(major, type, speed)		\
+	((major >= 6) ?	 0 :						\
+	((type == FM_PORT_TYPE_RX) ?					\
+	((speed == FM_PORT_SPEED_10G) ? 8 : 2) : 0))
+
+/* FMAN V3: 10G RX - 8, 1G RX - 2, 10G TX - 12, 1G TX 3, OP - 6
+ * FMAN V2: 10G RX/TX - 8, 1G(TX/RX)/OP - 1
+ */
+#define DFLT_PORT_NUM_OF_OPEN_DMAS(major, type, speed)			\
+	((major >= 6) ?							\
+	((type == FM_PORT_TYPE_RX) ?					\
+		((speed == FM_PORT_SPEED_10G) ? 8 : 2) :		\
+		((type == FM_PORT_TYPE_TX) ?				\
+		((speed == FM_PORT_SPEED_10G) ? 12 : 3) : 4)) :	\
+	((speed == FM_PORT_SPEED_10G) ? 8 : 1))
+
+/* FMAN V3: 0 for all ports
+ * FMAN V2: RX 10G - 8, 1G RX/TX & OP - 1
+ */
+#define DFLT_PORT_EXTRA_NUM_OF_OPEN_DMAS(major, type, speed)		\
+	((major >= 6) ?	 0 :						\
+	((speed == FM_PORT_SPEED_10G) ? 8 : 1))
+
+/* FMAN V3: 10G RX - 96, 10G TX 64, 1G/OP 50
+ * FMAN V2: 10G - 48, 1G RX 45, 1G TX 44, OP = 8
+ */
+#define DFLT_PORT_NUM_OF_FIFO_BUFS(major, type, speed)			\
+	(major >= 6 ?							\
+	(((speed == FM_PORT_SPEED_10G) ?				\
+		((type == FM_PORT_TYPE_RX) ? (96) : (64)) : (50))) :	\
+	((speed == FM_PORT_SPEED_10G) ? 48 :				\
+		((type == FM_PORT_TYPE_OP) ? 8 :			\
+		((type == FM_PORT_TYPE_RX) ? 45 : 44))))		\
+
+#define FM_PORT_MAX_NUM_OF_CONGESTION_GRPS_ALL_INTEGRATIONS 256
+
+#define FM_OH_PORT_ID                               1
+
+/* Memory Mapped Registers */
+
+struct fm_port_rx_bmi_regs_t {
+	uint32_t fmbm_rcfg;	/* Rx Configuration */
+	uint32_t fmbm_rst;	/* Rx Status */
+	uint32_t fmbm_rda;	/* Rx DMA attributes*/
+	uint32_t fmbm_rfp;	/* Rx FIFO Parameters*/
+	uint32_t fmbm_rfed;	/* Rx Frame End Data*/
+	uint32_t fmbm_ricp;	/* Rx Internal Context Parameters*/
+	uint32_t fmbm_rim;	/* Rx Internal Buffer Margins*/
+	uint32_t fmbm_rebm;	/* Rx External Buffer Margins*/
+	uint32_t fmbm_rfne;	/* Rx Frame Next Engine*/
+	uint32_t fmbm_rfca;	/* Rx Frame Command Attributes.*/
+	uint32_t fmbm_rfpne;	/* Rx Frame Parser Next Engine*/
+	uint32_t fmbm_rpso;	/* Rx Parse Start Offset*/
+	uint32_t fmbm_rpp;	/* Rx Policer Profile  */
+	uint32_t fmbm_rccb;	/* Rx Coarse Classification Base */
+	uint32_t fmbm_reth;	/* Rx Excessive Threshold */
+	uint32_t reserved1[0x01];
+	/* (0x03C) */
+	uint32_t fmbm_rprai[FM_PORT_PRS_RESULT_NUM_OF_WORDS];
+	/* Rx Parse Results Array Initialization*/
+	uint32_t fmbm_rfqid;	/* Rx Frame Queue ID*/
+	uint32_t fmbm_refqid;	/* Rx Error Frame Queue ID*/
+	uint32_t fmbm_rfsdm;	/* Rx Frame Status Discard Mask*/
+	uint32_t fmbm_rfsem;	/* Rx Frame Status Error Mask*/
+	uint32_t fmbm_rfene;	/* Rx Frame Enqueue Next Engine */
+	uint32_t reserved2[0x02];
+	/* (0x074-0x078) */
+	/* Rx Frame Continuous Mode Next Engine */
+	uint32_t fmbm_rcmne;
+	uint32_t reserved3[0x20];
+	/* (0x080 0x0FF)  */
+	uint32_t fmbm_ebmpi[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+	/* Buffer Manager pool Information-*/
+	uint32_t fmbm_acnt[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+	/* Allocate Counter-*/
+	uint32_t reserved4[0x08];
+	/* 0x130/0x140 - 0x15F reserved -*/
+	uint32_t
+	fmbm_rcgm[FM_PORT_MAX_NUM_OF_CONGESTION_GRPS_ALL_INTEGRATIONS / 32];
+	/* Congestion Group Map*/
+	uint32_t fmbm_rmpd;	/* BM Pool Depletion  */
+	uint32_t reserved5[0x1F];
+	/* (0x184 0x1FF) */
+	uint32_t fmbm_rstc;	/* Rx Statistics Counters*/
+	uint32_t fmbm_rfrc;	/* Rx Frame Counter*/
+	uint32_t fmbm_rfbc;	/* Rx Bad Frames Counter*/
+	uint32_t fmbm_rlfc;	/* Rx Large Frames Counter*/
+	uint32_t fmbm_rffc;	/* Rx Filter Frames Counter*/
+	uint32_t fmbm_rfcd;	/* Rx Frame Discard Counter*/
+	uint32_t fmbm_rfldec;	/* Rx Frames List DMA Error Counter*/
+	uint32_t fmbm_rodc;/* Rx Out of Buffers Discard Counter-*/
+	uint32_t fmbm_rbdc;	/* Rx Buffers Deallocate Counter-*/
+	uint32_t fmbm_rpec;	/* Rx RX Prepare to enqueue Counter-*/
+	uint32_t reserved6[0x16];
+	/* (0x228 0x27F) */
+	uint32_t fmbm_rpc;	/* Rx Performance Counters*/
+	uint32_t fmbm_rpcp;	/* Rx Performance Count Parameters*/
+	uint32_t fmbm_rccn;	/* Rx Cycle Counter*/
+	uint32_t fmbm_rtuc;	/* Rx Tasks Utilization Counter*/
+	uint32_t fmbm_rrquc;/* Rx Receive Queue Utilization Counter*/
+	uint32_t fmbm_rduc;	/* Rx DMA Utilization Counter*/
+	uint32_t fmbm_rfuc;	/* Rx FIFO Utilization Counter*/
+	uint32_t fmbm_rpac;	/* Rx Pause Activation Counter*/
+	uint32_t reserved7[0x18];
+	/* (0x2A0-0x2FF) */
+	uint32_t fmbm_rdcfg[0x3];
+	/* Rx Debug-*/
+	uint32_t fmbm_rgpr;	/* Rx General Purpose Register. */
+	uint32_t reserved8[0x3a];
+	/* (0x310-0x3FF) */
+} __attribute__((__packed__));
+
+struct fm_port_tx_bmi_regs_t {
+	 uint32_t fmbm_tcfg;	/* Tx Configuration */
+	 uint32_t fmbm_tst;	/* Tx Status */
+	 uint32_t fmbm_tda;	/* Tx DMA attributes */
+	 uint32_t fmbm_tfp;	/* Tx FIFO Parameters */
+	 uint32_t fmbm_tfed;	/* Tx Frame End Data */
+	 uint32_t fmbm_ticp;	/* Tx Internal Context Parameters */
+	 uint32_t fmbm_tfdne;	/* Tx Frame Dequeue Next Engine. */
+	 uint32_t fmbm_tfca;	/* Tx Frame Command attribute. */
+	 uint32_t fmbm_tcfqid;	/* Tx Confirmation Frame Queue ID. */
+	 uint32_t fmbm_tfeqid;	/* Tx Frame Error Queue ID */
+	 uint32_t fmbm_tfene;	/* Tx Frame Enqueue Next Engine */
+	 uint32_t fmbm_trlmts;	/* Tx Rate Limiter Scale */
+	 uint32_t fmbm_trlmt;	/* Tx Rate Limiter */
+	 uint32_t fmbm_tccb;	/* Tx Coarse Classification Base */
+	 uint32_t reserved0[0x0e];
+					/* (0x038-0x070) */
+	 uint32_t fmbm_tfne;	/* Tx Frame Next Engine */
+	 uint32_t fmbm_tpfcm[0x02];
+			/* Tx Priority based Flow Control (PFC) Mapping */
+	/* Tx Frame Continuous Mode Next Engine */
+	 uint32_t fmbm_tcmne;
+	 uint32_t reserved2[0x60];
+					/* (0x080-0x200) */
+	 uint32_t fmbm_tstc;	/* Tx Statistics Counters */
+	 uint32_t fmbm_tfrc;	/* Tx Frame Counter */
+	 uint32_t fmbm_tfdc;	/* Tx Frames Discard Counter */
+	 uint32_t fmbm_tfledc;	/* Tx Frame Length error discard counter */
+	/* Tx Frame unsupported format discard Counter */
+	 uint32_t fmbm_tfufdc;
+	 uint32_t fmbm_tbdc;	/* Tx Buffers Deallocate Counter */
+	 uint32_t reserved3[0x1A];
+					/* (0x218-0x280) */
+	 uint32_t fmbm_tpc;	/* Tx Performance Counters*/
+	 uint32_t fmbm_tpcp;	/* Tx Performance Count Parameters*/
+	 uint32_t fmbm_tccn;	/* Tx Cycle Counter*/
+	 uint32_t fmbm_ttuc;	/* Tx Tasks Utilization Counter*/
+	 /* Tx Transmit Confirm Queue Utilization Counter*/
+	 uint32_t fmbm_ttcquc;
+	 uint32_t fmbm_tduc;	/* Tx DMA Utilization Counter*/
+	 uint32_t fmbm_tfuc;	/* Tx FIFO Utilization Counter*/
+	 uint32_t reserved4[16];/* (0x29C-0x2FF) */
+	 uint32_t fmbm_tdcfg[0x3];
+					/* Tx Debug-*/
+	 uint32_t fmbm_tgpr;	/* O/H General Purpose Register */
+	 uint32_t reserved5[0x3a];
+					/* (0x310-0x3FF) */
+} __attribute__((__packed__));
+
+struct fm_port_oh_bmi_regs_t {
+	uint32_t fmbm_ocfg;	/* O/H Configuration  */
+	uint32_t fmbm_ost;	/* O/H Status */
+	uint32_t fmbm_oda;	/* O/H DMA attributes  */
+	uint32_t fmbm_oicp;	/* O/H Internal Context Parameters*/
+	uint32_t fmbm_ofdne;	/* O/H Frame Dequeue Next Engine  */
+	uint32_t fmbm_ofne;	/* O/H Frame Next Engine  */
+	uint32_t fmbm_ofca;	/* O/H Frame Command Attributes.  */
+	uint32_t fmbm_ofpne;	/* O/H Frame Parser Next Engine  */
+	uint32_t fmbm_opso;	/* O/H Parse Start Offset  */
+	uint32_t fmbm_opp;	/* O/H Policer Profile */
+	uint32_t fmbm_occb;	/* O/H Coarse Classification base */
+	uint32_t fmbm_oim;	/* O/H Internal margins*/
+	uint32_t fmbm_ofp;	/* O/H Fifo Parameters*/
+	uint32_t fmbm_ofed;	/* O/H Frame End Data*/
+	uint32_t reserved0[2];	/* (0x038 - 0x03F) */
+	uint32_t fmbm_oprai[FM_PORT_PRS_RESULT_NUM_OF_WORDS];
+				/* O/H Parse Results Array Initialization */
+	uint32_t fmbm_ofqid;	/* O/H Frame Queue ID  */
+	uint32_t fmbm_oefqid;	/* O/H Error Frame Queue ID  */
+	uint32_t fmbm_ofsdm;	/* O/H Frame Status Discard Mask  */
+	uint32_t fmbm_ofsem;	/* O/H Frame Status Error Mask  */
+	uint32_t fmbm_ofene;	/* O/H Frame Enqueue Next Engine  */
+	uint32_t fmbm_orlmts;	/* O/H Rate Limiter Scale  */
+	uint32_t fmbm_orlmt;	/* O/H Rate Limiter  */
+	uint32_t fmbm_ocmne;	/* O/H Continuous Mode Next Engine*/
+	uint32_t reserved1[0x20];
+					/* (0x080 - 0x0FF) */
+	/* Buffer Manager Observed Pool Information */
+	uint32_t fmbm_oebmpi[2];
+	uint32_t reserved2[0x16];
+					/* (0x108 - 0x15F) */
+	uint32_t fmbm_ocgm;	/* Observed Congestion Group Map */
+	uint32_t reserved3[0x7];
+					/* (0x164 - 0x17F) */
+	uint32_t fmbm_ompd;	/* Observed BMan Pool Depletion */
+	uint32_t reserved4[0x1F];
+					/* (0x184 - 0x1FF) */
+	uint32_t fmbm_ostc;	/* O/H Statistics Counters  */
+	uint32_t fmbm_ofrc;	/* O/H Frame Counter  */
+	uint32_t fmbm_ofdc;	/* O/H Frames Discard Counter  */
+	/* O/H Frames Length Error Discard Counter  */
+	uint32_t fmbm_ofledc;
+	/* O/H Frames Unsupported Format Discard Counter  */
+	uint32_t fmbm_ofufdc;
+	uint32_t fmbm_offc;	/* O/H Filter Frames Counter  */
+	uint32_t fmbm_ofwdc;	/* - Rx Frames WRED Discard Counter*/
+	/* O/H Frames List DMA Error Counter */
+	uint32_t fmbm_ofldec;
+	/* O/H Buffers Deallocate Counter */
+	uint32_t fmbm_obdc;
+	/* O/H Out of Buffers Discard Counter */
+	uint32_t fmbm_oodc;
+	/* O/H Prepare to enqueue Counter */
+	uint32_t fmbm_opec;
+	uint32_t reserved5[0x15];
+					/* ( - 0x27F) */
+	uint32_t fmbm_opc;	/* O/H Performance Counters  */
+	uint32_t fmbm_opcp;	/* O/H Performance Count Parameters*/
+	uint32_t fmbm_occn;	/* O/H Cycle Counter  */
+	uint32_t fmbm_otuc;	/* O/H Tasks Utilization Counter  */
+	uint32_t fmbm_oduc;	/* O/H DMA Utilization Counter */
+	uint32_t fmbm_ofuc;	/* O/H FIFO Utilization Counter */
+	uint32_t reserved6[26];/* (0x298-0x2FF) */
+	uint32_t fmbm_odcfg[0x3];
+					/* O/H Debug (only 1 in P1023) */
+	uint32_t fmbm_ogpr;	/* O/H General Purpose Register. */
+	uint32_t reserved7[0x3a];
+					/* (0x310 0x3FF) */
+} __attribute__((__packed__));
+
+union fm_port_bmi_regs_u {
+	struct fm_port_rx_bmi_regs_t rx_port_bmi_regs;
+	struct fm_port_tx_bmi_regs_t tx_port_bmi_regs;
+	struct fm_port_oh_bmi_regs_t oh_port_bmi_regs;
+} __attribute__((__packed__));
+
+struct fm_port_non_rx_qmi_regs_t {
+	/*   0xn024 - 0x02B */
+	uint32_t reserved1[2];
+	/*   PortID n Dequeue NIA Register */
+	uint32_t fmqm_pndn;
+	/*   PortID n Dequeue Config Register */
+	uint32_t fmqm_pndc;
+	/*   PortID n Dequeue Total Frame Counter */
+	uint32_t fmqm_pndtfc;
+	/*   PortID n Dequeue FQID from Default Counter */
+	uint32_t fmqm_pndfdc;
+	/*   PortID n Dequeue Confirm Counter */
+	uint32_t fmqm_pndcc;
+} __attribute__((__packed__));
+
+struct fm_port_qmi_regs_t {
+	/*   PortID n Configuration Register */
+	uint32_t fmqm_pnc;
+	/*   PortID n Status Register */
+	uint32_t fmqm_pns;
+	/*   PortID n Task Status Register */
+	uint32_t fmqm_pnts;
+	/*   0xn00C - 0xn01B */
+	uint32_t reserved0[4];
+	/*   PortID n Enqueue NIA Register */
+	uint32_t fmqm_pnen;
+	/*   PortID n Enqueue Total Frame Counter */
+	uint32_t fmqm_pnetfc;
+	/*   Registers for Tx Hc&Op ports */
+	struct fm_port_non_rx_qmi_regs_t non_rx_qmi_regs;
+} __attribute__((__packed__));
+
+/* Registers bit fields */
+
+/* BMI defines */
+#define BMI_PORT_CFG_EN                         0x80000000
+#define BMI_PORT_CFG_FDOVR                      0x02000000
+#define BMI_PORT_CFG_IM                         0x01000000
+#define BMI_PORT_STATUS_BSY                     0x80000000
+#define BMI_COUNTERS_EN                         0x80000000
+
+#define BMI_PORT_RFNE_FRWD_DCL4C                0x10000000
+#define BMI_PORT_RFNE_FRWD_RPD                  0x40000000
+#define BMI_RFNE_FDCS_MASK                      0xFF000000
+
+#define BMI_CMD_MR_LEAC                         0x00200000
+#define BMI_CMD_MR_SLEAC                        0x00100000
+#define BMI_CMD_MR_MA                           0x00080000
+#define BMI_CMD_MR_DEAS                         0x00040000
+#define BMI_CMD_RX_MR_DEF	\
+(BMI_CMD_MR_LEAC | \
+BMI_CMD_MR_SLEAC | \
+BMI_CMD_MR_MA | \
+BMI_CMD_MR_DEAS)
+#define BMI_CMD_ATTR_ORDER                      0x80000000
+#define BMI_CMD_ATTR_SYNC                       0x02000000
+#define BMI_CMD_ATTR_MODE_MISS_ALIGN_ADDR_EN   0x00080000
+#define BMI_CMD_ATTR_MACCMD_MASK                0x0000ff00
+#define BMI_CMD_ATTR_MACCMD_OVERRIDE            0x00008000
+#define BMI_CMD_ATTR_MACCMD_SECURED             0x00001000
+#define BMI_CMD_ATTR_MACCMD_SC_MASK             0x00000f00
+
+#define BMI_EXT_BUF_POOL_ID_MASK                0x003F0000
+#define BMI_STATUS_RX_MASK_UNUSED	\
+(uint32_t)(~(FM_PORT_FRM_ERR_DMA                    | \
+FM_PORT_FRM_ERR_PHYSICAL               | \
+FM_PORT_FRM_ERR_SIZE                   | \
+FM_PORT_FRM_ERR_CLS_DISCARD            | \
+FM_PORT_FRM_ERR_EXTRACTION             | \
+FM_PORT_FRM_ERR_NO_SCHEME              | \
+FM_PORT_FRM_ERR_COLOR_RED              | \
+FM_PORT_FRM_ERR_COLOR_YELLOW           | \
+FM_PORT_FRM_ERR_PRS_TIMEOUT            | \
+FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT       | \
+FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED   | \
+FM_PORT_FRM_ERR_PRS_HDR_ERR            | \
+FM_PORT_FRM_ERR_IPRE                   | \
+FM_PORT_FRM_ERR_IPR_NCSP               | \
+FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW))
+
+#define BMI_STATUS_OP_MASK_UNUSED			\
+	(uint32_t)(BMI_STATUS_RX_MASK_UNUSED	&	\
+		~(FM_PORT_FRM_ERR_LENGTH	|	\
+		FM_PORT_FRM_ERR_NON_FM		|	\
+		FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT))
+
+#define BMI_RX_FIFO_THRESHOLD_BC                0x80000000
+
+#define BMI_PRS_RESULT_HIGH                     0x00000000
+#define BMI_PRS_RESULT_LOW                      0xFFFFFFFF
+
+#define RX_ERRS_TO_ENQ	\
+(FM_PORT_FRM_ERR_DMA                    | \
+FM_PORT_FRM_ERR_PHYSICAL               | \
+FM_PORT_FRM_ERR_SIZE                   | \
+FM_PORT_FRM_ERR_EXTRACTION             | \
+FM_PORT_FRM_ERR_NO_SCHEME              | \
+FM_PORT_FRM_ERR_PRS_TIMEOUT            | \
+FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT       | \
+FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED   | \
+FM_PORT_FRM_ERR_PRS_HDR_ERR            | \
+FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW       | \
+FM_PORT_FRM_ERR_IPRE)
+
+#define OP_ERRS_TO_ENQ	\
+(RX_ERRS_TO_ENQ                         | \
+FM_PORT_FRM_ERR_LENGTH                 | \
+FM_PORT_FRM_ERR_NON_FM                 | \
+FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT)
+
+#define BMI_RX_FIFO_PRI_ELEVATION_MASK          0x03FF0000
+#define BMI_RX_FIFO_THRESHOLD_MASK              0x000003FF
+#define BMI_TX_FIFO_MIN_FILL_MASK               0x03FF0000
+#define BMI_FIFO_PIPELINE_DEPTH_MASK            0x0000F000
+#define BMI_TX_LOW_COMF_MASK                    0x000003FF
+
+/* shifts */
+#define BMI_PORT_CFG_MS_SEL_SHIFT               16
+#define BMI_DMA_ATTR_IC_CACHE_SHIFT             FMAN_SP_DMA_ATTR_IC_CACHE_SHIFT
+#define BMI_DMA_ATTR_HDR_CACHE_SHIFT            FMAN_SP_DMA_ATTR_HDR_CACHE_SHIFT
+#define BMI_DMA_ATTR_SG_CACHE_SHIFT             FMAN_SP_DMA_ATTR_SG_CACHE_SHIFT
+
+#define BMI_IM_FOF_SHIFT                        28
+#define BMI_PR_PORTID_SHIFT                     24
+
+#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT         16
+#define BMI_RX_FIFO_THRESHOLD_SHIFT             0
+
+#define BMI_RX_FRAME_END_CS_IGNORE_SHIFT        24
+#define BMI_RX_FRAME_END_CUT_SHIFT              16
+
+#define BMI_IC_SIZE_SHIFT                       FMAN_SP_IC_SIZE_SHIFT
+
+#define BMI_INT_BUF_MARG_SHIFT                  28
+
+#define BMI_EXT_BUF_MARG_END_SHIFT              FMAN_SP_EXT_BUF_MARG_END_SHIFT
+
+#define BMI_CMD_ATTR_COLOR_SHIFT                26
+#define BMI_CMD_ATTR_COM_MODE_SHIFT             16
+#define BMI_CMD_ATTR_MACCMD_SHIFT               8
+#define BMI_CMD_ATTR_MACCMD_OVERRIDE_SHIFT      15
+#define BMI_CMD_ATTR_MACCMD_SECURED_SHIFT       12
+#define BMI_CMD_ATTR_MACCMD_SC_SHIFT            8
+
+#define BMI_POOL_DEP_NUM_OF_POOLS_VECTOR_SHIFT  24
+
+#define BMI_TX_FIFO_MIN_FILL_SHIFT              16
+#define BMI_TX_LOW_COMF_SHIFT                   0
+
+#define BMI_PERFORMANCE_TASK_COMP_SHIFT         24
+#define BMI_PERFORMANCE_PORT_COMP_SHIFT         16
+#define BMI_PERFORMANCE_DMA_COMP_SHIFT          12
+#define BMI_PERFORMANCE_FIFO_COMP_SHIFT         0
+
+#define BMI_MAX_BURST_SHIFT                     16
+#define BMI_COUNT_RATE_UNIT_SHIFT               16
+
+/* sizes */
+#define FRAME_END_DATA_SIZE                     16
+#define FRAME_OFFSET_UNITS                      16
+#define MIN_TX_INT_OFFSET                       16
+#define MAX_FRAME_OFFSET                        64
+#define MAX_FIFO_PIPELINE_DEPTH                 8
+#define MAX_PERFORMANCE_TASK_COMP               64
+#define MAX_PERFORMANCE_TX_QUEUE_COMP           8
+#define MAX_PERFORMANCE_RX_QUEUE_COMP           64
+#define MAX_PERFORMANCE_DMA_COMP                16
+#define MAX_NUM_OF_TASKS                        64
+#define MAX_NUM_OF_EXTRA_TASKS                  8
+#define MAX_NUM_OF_DMAS                         16
+#define MAX_NUM_OF_EXTRA_DMAS                   8
+#define MAX_BURST_SIZE                          1024
+#define MIN_NUM_OF_OP_DMAS                      2
+
+/* QMI defines */
+/* masks */
+#define QMI_PORT_CFG_EN                         0x80000000
+#define QMI_PORT_CFG_EN_COUNTERS                0x10000000
+#define QMI_PORT_STATUS_DEQ_TNUM_BSY            0x80000000
+#define QMI_PORT_STATUS_DEQ_FD_BSY              0x20000000
+
+#define QMI_DEQ_CFG_PREFETCH_NO_TNUM            0x02000000
+#define QMI_DEQ_CFG_PREFETCH_WAITING_TNUM       0
+#define QMI_DEQ_CFG_PREFETCH_1_FRAME            0
+#define QMI_DEQ_CFG_PREFETCH_3_FRAMES           0x01000000
+
+#define QMI_DEQ_CFG_PRI                         0x80000000
+#define QMI_DEQ_CFG_TYPE1                       0x10000000
+#define QMI_DEQ_CFG_TYPE2                       0x20000000
+#define QMI_DEQ_CFG_TYPE3                       0x30000000
+
+#define QMI_DEQ_CFG_SUBPORTAL_MASK              0x1f
+#define QMI_DEQ_CFG_SUBPORTAL_SHIFT             20
+
+/* PARSER defines */
+/* masks */
+#define PRS_HDR_ERROR_DIS                       0x00000800
+#define PRS_HDR_SW_PRS_EN                       0x00000400
+#define PRS_CP_OFFSET_MASK                      0x0000000F
+#define PRS_TPID1_MASK                          0xFFFF0000
+#define PRS_TPID2_MASK                          0x0000FFFF
+#define PRS_TPID_DFLT                           0x91009100
+
+#define PRS_HDR_MPLS_LBL_INTER_EN               0x00200000
+#define PRS_HDR_IPV6_ROUTE_HDR_EN               0x00008000
+#define PRS_HDR_PPPOE_MTU_CHECK_EN              0x80000000
+#define PRS_HDR_UDP_PAD_REMOVAL                 0x80000000
+#define PRS_HDR_TCP_PAD_REMOVAL                 0x80000000
+#define PRS_CAC_STOP                            0x00000001
+#define PRS_CAC_ACTIVE                          0x00000100
+
+/* shifts */
+#define PRS_PCTPID_SHIFT                        16
+#define PRS_HDR_MPLS_NEXT_HDR_SHIFT             22
+#define PRS_HDR_ETH_BC_SHIFT                    28
+#define PRS_HDR_ETH_MC_SHIFT                    24
+#define PRS_HDR_VLAN_STACKED_SHIFT              16
+#define PRS_HDR_MPLS_STACKED_SHIFT              16
+#define PRS_HDR_IPV4_1_BC_SHIFT                 28
+#define PRS_HDR_IPV4_1_MC_SHIFT                 24
+#define PRS_HDR_IPV4_2_UC_SHIFT                 20
+#define PRS_HDR_IPV4_2_MC_BC_SHIFT              16
+#define PRS_HDR_IPV6_1_MC_SHIFT                 24
+#define PRS_HDR_IPV6_2_UC_SHIFT                 20
+#define PRS_HDR_IPV6_2_MC_SHIFT                 16
+
+#define PRS_HDR_ETH_BC_MASK                     0x0fffffff
+#define PRS_HDR_ETH_MC_MASK                     0xf0ffffff
+#define PRS_HDR_VLAN_STACKED_MASK               0xfff0ffff
+#define PRS_HDR_MPLS_STACKED_MASK               0xfff0ffff
+#define PRS_HDR_IPV4_1_BC_MASK                  0x0fffffff
+#define PRS_HDR_IPV4_1_MC_MASK                  0xf0ffffff
+#define PRS_HDR_IPV4_2_UC_MASK                  0xff0fffff
+#define PRS_HDR_IPV4_2_MC_BC_MASK               0xfff0ffff
+#define PRS_HDR_IPV6_1_MC_MASK                  0xf0ffffff
+#define PRS_HDR_IPV6_2_UC_MASK                  0xff0fffff
+#define PRS_HDR_IPV6_2_MC_MASK                  0xfff0ffff
+
+/* others */
+#define PRS_HDR_ENTRY_SIZE                      8
+#define DEFAULT_CLS_PLAN_VECTOR                 0xFFFFFFFF
+
+#define IPSEC_SW_PATCH_START                    0x20
+#define SCTP_SW_PATCH_START                     0x4D
+#define DCCP_SW_PATCH_START                     0x41
+
+/* Additional defines */
+
+struct fm_port_drv_param_t {
+	struct fman_port_cfg dflt_cfg;
+	uint32_t dflt_fqid;
+	uint32_t err_fqid;
+	uintptr_t base_addr;
+	uint8_t deq_sub_portal;
+	bool deq_high_priority;
+	enum fm_port_deq_type deq_type;
+	enum fm_port_deq_prefetch_option deq_prefetch_option;
+	uint16_t deq_byte_cnt;
+	uint8_t cheksum_last_bytes_ignore;
+	uint8_t cut_bytes_from_end;
+	struct fm_buf_pool_depletion_t buf_pool_depletion;
+	bool frm_discard_override;
+	bool en_buf_pool_depletion;
+	uint16_t liodn_offset;
+	uint16_t liodn_base;
+	struct fm_ext_pools_t ext_buf_pools;
+	enum fm_dma_swap_option dma_swap_data;
+	uint32_t tx_fifo_min_fill_level;
+	uint32_t tx_fifo_low_comf_level;
+	uint32_t rx_fifo_pri_elevation_level;
+	uint32_t rx_fifo_threshold;
+	struct fm_sp_buf_margins_t buf_margins;
+	struct fm_sp_int_context_data_copy_t int_context;
+	bool sync_req;
+	enum fm_port_color color;
+	uint32_t errors_to_discard;
+	uint32_t errors_to_enq;
+	bool forward_reuse_int_context;
+	struct fm_buffer_prefix_content_t buffer_prefix_content;
+	struct fm_backup_bm_pools_t *p_backup_bm_pools;
+	bool dont_release_buf;
+	bool set_num_of_tasks;
+	bool set_num_of_open_dmas;
+	bool set_size_of_fifo;
+
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+	bool bcb_workaround;
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+};
+
+struct fm_port_rx_pools_params_t {
+	uint8_t num_of_pools;
+	uint16_t second_largest_buf_size;
+	uint16_t largest_buf_size;
+};
+
+struct fm_port_intg_t {
+	uint32_t max_port_fifo_size;
+	uint32_t max_num_of_ext_pools;
+	uint32_t fm_max_num_of_sub_portals;
+	uint32_t bm_max_num_of_pools;
+};
+
+/* No PCD Engine indicated */
+#define FM_PCD_NONE                                 0
+struct fm_port_t {
+	struct fman_port port;
+	void *h_fm;
+	struct fm_revision_info_t fm_rev_info;
+	uint8_t port_id;
+	enum fm_port_type port_type;
+	enum fm_port_speed port_speed;
+	int enabled;
+	char name[MODULE_NAME_SIZE];
+	uint16_t fm_clk_freq;
+	struct fm_port_qmi_regs_t __iomem *p_fm_port_qmi_regs;
+
+	union fm_port_bmi_regs_u __iomem *p_fm_port_bmi_regs;
+	/* The optional engines are devined avobe */
+	uint32_t saved_bmi_nia;
+	uint8_t private_info;
+	struct fm_sp_buffer_offsets_t buffer_offsets;
+
+	volatile bool lock;
+	/* Spinlock for port use */
+	spinlock_t *spinlock;
+	fm_port_exception_cb *f_exception;
+	void *h_app;
+	uint8_t internal_buf_offset;
+	uint32_t exceptions;
+	bool polling;
+	struct fm_ext_pools_t ext_buf_pools;
+	uint32_t required_action;
+	uint32_t saved_qmi_pnen;
+	uint32_t saved_bmi_fene;
+	uint32_t saved_bmi_fpne;
+	uint32_t saved_bmi_cmne;
+	uint32_t saved_non_rx_qmi_regs_pndn;
+	uint32_t orig_non_rx_qmi_regs_pndn;
+	bool include_in_prs_statistics;
+	uint16_t max_frame_length;
+	uint32_t or_fman_ctrl;
+	struct fm_port_rsrc_t open_dmas;
+	struct fm_port_rsrc_t tasks;
+	struct fm_port_rsrc_t fifo_bufs;
+	struct fm_port_rx_pools_params_t rx_pools_params;
+
+	struct fm_port_drv_param_t *p_fm_port_drv_param;
+
+	struct fm_port_intg_t *port_intg;
+
+};
+
+#endif /* __FM_PORT_H */
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3 12/12] fsl/fman: Add FMan MAC driver
  2015-05-07 13:05                   ` [RFC,v3 11/12] fsl/fman: Add FMan Port Support Madalin Bucur
@ 2015-05-07 13:05                     ` Madalin Bucur
  0 siblings, 0 replies; 13+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman

From: Igal Liberman <Igal.Liberman@freescale.com>

This patch adds the Ethernet MAC driver support.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 drivers/net/ethernet/freescale/fman/inc/mac.h     | 125 +++++
 drivers/net/ethernet/freescale/fman/mac/Makefile  |   3 +-
 drivers/net/ethernet/freescale/fman/mac/mac-api.c | 605 ++++++++++++++++++++++
 drivers/net/ethernet/freescale/fman/mac/mac.c     | 527 +++++++++++++++++++
 4 files changed, 1259 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/freescale/fman/inc/mac.h
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/mac-api.c
 create mode 100644 drivers/net/ethernet/freescale/fman/mac/mac.c

diff --git a/drivers/net/ethernet/freescale/fman/inc/mac.h b/drivers/net/ethernet/freescale/fman/inc/mac.h
new file mode 100644
index 0000000..2d27331
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/mac.h
@@ -0,0 +1,125 @@
+/* Copyright 2008-2015 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MAC_H
+#define __MAC_H
+
+#include <linux/device.h>	/* struct device, BUS_ID_SIZE */
+#include <linux/if_ether.h>	/* ETH_ALEN */
+#include <linux/phy.h>		/* phy_interface_t, struct phy_device */
+#include <linux/list.h>
+
+#include "fsl_fman_drv.h"	/* struct port_device */
+#include "fm_mac_ext.h"		/* FM MAC API */
+#include "fm_port_ext.h"
+
+enum {DTSEC, XGMAC, MEMAC};
+
+struct mac_device {
+	struct device		*dev;
+	void			*priv;
+	u8			 cell_index;
+	struct resource		*res;
+	void __iomem		*vaddr;
+	u8			 addr[ETH_ALEN];
+	bool			 promisc;
+
+	struct fm		*fm_dev;
+	struct fm_port		*port_dev[2];
+
+	phy_interface_t		 phy_if;
+	u32			 if_support;
+	bool			 link;
+	u16		 speed;
+	u16		 max_speed;
+	struct device_node	*phy_node;
+	char			 fixed_bus_id[MII_BUS_ID_SIZE + 3];
+	struct device_node	*tbi_node;
+	struct phy_device	*phy_dev;
+	void			*fm;
+	/* List of multicast addresses */
+	struct list_head	 mc_addr_list;
+	struct platform_device	*eth_dev;
+
+	bool autoneg_pause;
+	bool rx_pause_req;
+	bool tx_pause_req;
+	bool rx_pause_active;
+	bool tx_pause_active;
+
+	struct fm_mac_dev * (*get_mac_handle)(struct mac_device *mac_dev);
+	int (*init_phy)(struct net_device *net_dev, struct mac_device *mac_dev);
+	int (*init)(struct mac_device *mac_dev);
+	int (*start)(struct mac_device *mac_dev);
+	int (*stop)(struct mac_device *mac_dev);
+	int (*set_promisc)(struct fm_mac_dev *fm_mac_dev, bool enable);
+	int (*change_addr)(struct fm_mac_dev *fm_mac_dev,
+			   enet_addr_t *p_enet_addr);
+	int (*set_multi)(struct net_device *net_dev,
+			 struct mac_device *mac_dev);
+	int (*uninit)(struct fm_mac_dev *fm_mac_dev);
+	int (*set_rx_pause)(struct fm_mac_dev *fm_mac_dev, bool en);
+	int (*set_tx_pause)(struct fm_mac_dev *fm_mac_dev, u8 priority,
+			    u16 pause_time, u16 thresh_time);
+};
+
+struct mac_address {
+	u8 addr[ETH_ALEN];
+	struct list_head list;
+};
+
+struct dpaa_eth_data {
+	struct device_node *mac_node;
+	struct mac_device *mac_dev;
+	int mac_hw_id;
+	int fman_hw_id;
+};
+
+#define get_fm_handle(net_dev) \
+	(((struct dpa_priv_s *)netdev_priv(net_dev))->mac_dev->fm_dev)
+
+#define for_each_port_device(i, port_dev)	\
+	for (i = 0; i < ARRAY_SIZE(port_dev); i++)
+
+static inline __attribute((nonnull)) void *macdev_priv(
+		const struct mac_device *mac_dev)
+{
+	return (void *)mac_dev + sizeof(*mac_dev);
+}
+
+extern const char	*mac_driver_description;
+extern const size_t	 mac_sizeof_priv[];
+extern void (*const mac_setup[])(struct mac_device *mac_dev);
+
+int set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx);
+void get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, bool *tx_pause);
+
+#endif	/* __MAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/Makefile b/drivers/net/ethernet/freescale/fman/mac/Makefile
index 042a1f7..a422fbf 100644
--- a/drivers/net/ethernet/freescale/fman/mac/Makefile
+++ b/drivers/net/ethernet/freescale/fman/mac/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_FSL_FMAN_MAC)	+= fsl_fman_mac.o
+obj-y	+= fsl_fman_mac.o  fsl_mac.o
 
 fsl_fman_mac-objs		:= fman_dtsec.o fman_dtsec_mii_acc.o	\
 				    dtsec.o dtsec_mii_acc.o		\
@@ -6,3 +6,4 @@ fsl_fman_mac-objs		:= fman_dtsec.o fman_dtsec_mii_acc.o	\
 				   memac.o memac_mii_acc.o		\
 				   fman_tgec.o tgec.o			\
 				   fman_crc32.o fm_mac.o
+fsl_mac-objs += mac.o mac-api.o
diff --git a/drivers/net/ethernet/freescale/fman/mac/mac-api.c b/drivers/net/ethernet/freescale/fman/mac/mac-api.c
new file mode 100644
index 0000000..159aa15
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/mac-api.c
@@ -0,0 +1,605 @@
+/* Copyright 2008-2015 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+	KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+	KBUILD_BASENAME ".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+	KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_mdio.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include "mac.h"
+#include "fsl_fman_drv.h"
+#include "fm_mac_ext.h"
+
+#include "../fman/flib/fsl_fman_dtsec.h"
+#include "../fman/flib/fsl_fman_tgec.h"
+#include "../fman/flib/fsl_fman_memac.h"
+
+#define MAC_DESCRIPTION "FSL FMan MAC API based driver"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+MODULE_AUTHOR("Emil Medve <Emilian.Medve@Freescale.com>");
+
+MODULE_DESCRIPTION(MAC_DESCRIPTION);
+
+struct mac_priv_s {
+	struct fm_mac_dev *fm_mac;
+};
+
+const char	*mac_driver_description __initconst = MAC_DESCRIPTION;
+const size_t	 mac_sizeof_priv[] = {
+	[DTSEC] = sizeof(struct mac_priv_s),
+	[XGMAC] = sizeof(struct mac_priv_s),
+	[MEMAC] = sizeof(struct mac_priv_s)
+};
+
+static const enet_mode_t _100[] = {
+	[PHY_INTERFACE_MODE_MII]	= ENET_MODE_MII_100,
+	[PHY_INTERFACE_MODE_RMII]	= ENET_MODE_RMII_100
+};
+
+static const enet_mode_t _1000[] = {
+	[PHY_INTERFACE_MODE_GMII]	= ENET_MODE_GMII_1000,
+	[PHY_INTERFACE_MODE_SGMII]	= ENET_MODE_SGMII_1000,
+	[PHY_INTERFACE_MODE_TBI]	= ENET_MODE_TBI_1000,
+	[PHY_INTERFACE_MODE_RGMII]	= ENET_MODE_RGMII_1000,
+	[PHY_INTERFACE_MODE_RGMII_ID]	= ENET_MODE_RGMII_1000,
+	[PHY_INTERFACE_MODE_RGMII_RXID]	= ENET_MODE_RGMII_1000,
+	[PHY_INTERFACE_MODE_RGMII_TXID]	= ENET_MODE_RGMII_1000,
+	[PHY_INTERFACE_MODE_RTBI]	= ENET_MODE_RTBI_1000
+};
+
+static enet_mode_t __cold __attribute__((nonnull))
+macdev2enetinterface(const struct mac_device *mac_dev)
+{
+	switch (mac_dev->max_speed) {
+	case SPEED_100:
+		return _100[mac_dev->phy_if];
+	case SPEED_1000:
+		return _1000[mac_dev->phy_if];
+	case SPEED_10000:
+		return ENET_MODE_XGMII_10000;
+	default:
+		return ENET_MODE_MII_100;
+	}
+}
+
+static void mac_exception(void *_mac_dev, enum fm_mac_exceptions ex)
+{
+	struct mac_device	*mac_dev;
+
+	mac_dev = (struct mac_device *)_mac_dev;
+
+	if (FM_MAC_EX_10G_RX_FIFO_OVFL == ex) {
+		/* don't flag RX FIFO after the first */
+		fm_mac_set_exception(mac_dev->get_mac_handle(mac_dev),
+				     FM_MAC_EX_10G_RX_FIFO_OVFL, false);
+		dev_err(mac_dev->dev, "10G MAC got RX FIFO Error = %x\n",
+			ex);
+	}
+
+	dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c",
+		__func__, ex);
+}
+
+static int __cold init(struct mac_device *mac_dev)
+{
+	int					_errno;
+	struct mac_priv_s	*priv;
+	struct fm_mac_params_t		param;
+	u32			version;
+
+	priv = macdev_priv(mac_dev);
+
+	param.base_addr =  (typeof(param.base_addr))(uintptr_t)devm_ioremap(
+		mac_dev->dev, mac_dev->res->start, 0x2000);
+	param.enet_mode	= macdev2enetinterface(mac_dev);
+	memcpy(&param.addr, mac_dev->addr,
+	       min(sizeof(param.addr), sizeof(mac_dev->addr)));
+	param.mac_id		= mac_dev->cell_index;
+	param.h_fm		= (void *)mac_dev->fm;
+	param.mdio_irq		= NO_IRQ;
+	param.f_exception	= mac_exception;
+	param.f_event		= mac_exception;
+	param.h_app		= mac_dev;
+
+	priv->fm_mac = fm_mac_config(&param);
+	if (unlikely(!priv->fm_mac)) {
+		_errno = -EINVAL;
+		goto _return;
+	}
+
+	_errno = fm_mac_cfg_max_frame_len(priv->fm_mac, fm_get_max_frm());
+	if (unlikely(_errno < 0))
+		goto _return_fm_mac_free;
+
+	if (macdev2enetinterface(mac_dev) != ENET_MODE_XGMII_10000) {
+		/* 10G always works with pad and CRC */
+		_errno = fm_mac_cfg_pad_and_crc(priv->fm_mac, true);
+		if (unlikely(_errno < 0))
+			goto _return_fm_mac_free;
+
+		if (unlikely(_errno < 0))
+			goto _return_fm_mac_free;
+	} else {
+		_errno = fm_mac_cfg_reset_on_init(priv->fm_mac, true);
+		if (unlikely(_errno < 0))
+			goto _return_fm_mac_free;
+	}
+
+	_errno = fm_mac_init(priv->fm_mac);
+	if (unlikely(_errno < 0))
+		goto _return_fm_mac_free;
+
+	/* For 1G MAC, disable by default the MIB counters overflow interrupt */
+	if (macdev2enetinterface(mac_dev) != ENET_MODE_XGMII_10000) {
+		_errno = fm_mac_set_exception(mac_dev->get_mac_handle(mac_dev),
+					      FM_MAC_EX_1G_RX_MIB_CNT_OVFL,
+					      false);
+		if (unlikely(_errno < 0))
+			goto _return_fm_mac_free;
+	}
+
+	/* For 10G MAC, disable Tx ECC exception */
+	if (macdev2enetinterface(mac_dev) == ENET_MODE_XGMII_10000) {
+		_errno = fm_mac_set_exception(mac_dev->get_mac_handle(mac_dev),
+					      FM_MAC_EX_10G_1TX_ECC_ER, false);
+		if (unlikely(_errno < 0))
+			goto _return_fm_mac_free;
+	}
+
+	_errno = fm_mac_get_version(priv->fm_mac, &version);
+	if (unlikely(_errno < 0))
+		goto _return_fm_mac_free;
+
+	dev_info(mac_dev->dev, "FMan %s version: 0x%08x\n",
+		 ((macdev2enetinterface(mac_dev) != ENET_MODE_XGMII_10000) ?
+		  "dTSEC" : "XGEC"), version);
+
+	goto _return;
+
+_return_fm_mac_free:
+	fm_mac_free(mac_dev->get_mac_handle(mac_dev));
+
+_return:
+	return _errno;
+}
+
+static int __cold memac_init(struct mac_device *mac_dev)
+{
+	int			_errno;
+	struct mac_priv_s	*priv;
+	struct fm_mac_params_t		param;
+
+	priv = macdev_priv(mac_dev);
+
+	param.base_addr =  (typeof(param.base_addr))(uintptr_t)devm_ioremap(
+		mac_dev->dev, mac_dev->res->start, 0x2000);
+	param.enet_mode	= macdev2enetinterface(mac_dev);
+	memcpy(&param.addr, mac_dev->addr, sizeof(mac_dev->addr));
+	param.mac_id		= mac_dev->cell_index;
+	param.h_fm		= (void *)mac_dev->fm;
+	param.mdio_irq		= NO_IRQ;
+	param.f_exception	= mac_exception;
+	param.f_event		= mac_exception;
+	param.h_app		= mac_dev;
+
+	priv->fm_mac = fm_mac_config(&param);
+	if (unlikely(!priv->fm_mac)) {
+		_errno = -EINVAL;
+		goto _return;
+	}
+
+	_errno = fm_mac_cfg_max_frame_len(priv->fm_mac, fm_get_max_frm());
+	if (unlikely(_errno < 0))
+		goto _return_fm_mac_free;
+
+	_errno = fm_mac_cfg_reset_on_init(priv->fm_mac, true);
+	if (unlikely(_errno < 0))
+		goto _return_fm_mac_free;
+
+	_errno = fm_mac_init(priv->fm_mac);
+	if (unlikely(_errno < 0))
+		goto _return_fm_mac_free;
+
+	dev_info(mac_dev->dev, "FMan MEMAC\n");
+
+	goto _return;
+
+_return_fm_mac_free:
+	fm_mac_free(priv->fm_mac);
+
+_return:
+	return _errno;
+}
+
+static int __cold start(struct mac_device *mac_dev)
+{
+	int	 _errno;
+	struct phy_device *phy_dev = mac_dev->phy_dev;
+
+	_errno = fm_mac_enable(mac_dev->get_mac_handle(mac_dev),
+			       COMM_MODE_RX_AND_TX);
+
+	if (!_errno && phy_dev) {
+		if (macdev2enetinterface(mac_dev) != ENET_MODE_XGMII_10000)
+			phy_start(phy_dev);
+		else if (phy_dev->drv->read_status)
+			phy_dev->drv->read_status(phy_dev);
+	}
+
+	return _errno;
+}
+
+static int __cold stop(struct mac_device *mac_dev)
+{
+	if (mac_dev->phy_dev && (macdev2enetinterface(mac_dev) !=
+				 ENET_MODE_XGMII_10000))
+		phy_stop(mac_dev->phy_dev);
+
+	return fm_mac_disable(mac_dev->get_mac_handle(mac_dev),
+			      COMM_MODE_RX_AND_TX);
+}
+
+static int __cold set_multi(struct net_device *net_dev,
+			    struct mac_device *mac_dev)
+{
+	struct mac_priv_s	*mac_priv;
+	struct mac_address	*old_addr, *tmp;
+	struct netdev_hw_addr	*ha;
+	int			_errno;
+	enet_addr_t		*addr;
+
+	mac_priv = macdev_priv(mac_dev);
+
+	/* Clear previous address list */
+	list_for_each_entry_safe(old_addr, tmp, &mac_dev->mc_addr_list, list) {
+		addr = (enet_addr_t *)old_addr->addr;
+		_errno = fm_mac_remove_hash_mac_addr(mac_priv->fm_mac, addr);
+		if (_errno < 0)
+			return _errno;
+
+		list_del(&old_addr->list);
+		kfree(old_addr);
+	}
+
+	/* Add all the addresses from the new list */
+	netdev_for_each_mc_addr(ha, net_dev) {
+		addr = (enet_addr_t *)ha->addr;
+		_errno = fm_mac_add_hash_mac_addr(mac_priv->fm_mac, addr);
+		if (_errno < 0)
+			return _errno;
+
+		tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC);
+		if (!tmp)
+			return -ENOMEM;
+
+		ether_addr_copy(tmp->addr, ha->addr);
+		list_add(&tmp->list, &mac_dev->mc_addr_list);
+	}
+	return 0;
+}
+
+/* Avoid redundant calls to FMD, if the MAC driver already contains the desired
+ * active PAUSE settings. Otherwise, the new active settings should be reflected
+ * in FMan.
+ */
+int set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx)
+{
+	struct fm_mac_dev *fm_mac_dev = mac_dev->get_mac_handle(mac_dev);
+	int _errno = 0;
+
+	if (unlikely(rx != mac_dev->rx_pause_active)) {
+		_errno = fm_mac_set_rx_pause_frames(fm_mac_dev, rx);
+		if (likely(_errno == 0))
+			mac_dev->rx_pause_active = rx;
+	}
+
+	if (unlikely(tx != mac_dev->tx_pause_active)) {
+		u16 pause_time = (tx ? FSL_FM_PAUSE_TIME_ENABLE :
+					 FSL_FM_PAUSE_TIME_DISABLE);
+
+		_errno = fm_mac_set_tx_pause_frames(fm_mac_dev, 0,
+						    pause_time, 0);
+
+		if (likely(_errno == 0))
+			mac_dev->tx_pause_active = tx;
+	}
+
+	return _errno;
+}
+EXPORT_SYMBOL(set_mac_active_pause);
+
+/* Determine the MAC RX/TX PAUSE frames settings based on PHY
+ * autonegotiation or values set by eththool.
+ */
+void get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, bool *tx_pause)
+{
+	struct phy_device *phy_dev = mac_dev->phy_dev;
+	u16 lcl_adv, rmt_adv;
+	u8 flowctrl;
+
+	*rx_pause = *tx_pause = false;
+
+	if (!phy_dev->duplex)
+		return;
+
+	/* If PAUSE autonegotiation is disabled, the TX/RX PAUSE settings
+	 * are those set by ethtool.
+	 */
+	if (!mac_dev->autoneg_pause) {
+		*rx_pause = mac_dev->rx_pause_req;
+		*tx_pause = mac_dev->tx_pause_req;
+		return;
+	}
+
+	/* Else if PAUSE autonegotiation is enabled, the TX/RX PAUSE
+	 * settings depend on the result of the link negotiation.
+	 */
+
+	/* get local capabilities */
+	lcl_adv = 0;
+	if (phy_dev->advertising & ADVERTISED_Pause)
+		lcl_adv |= ADVERTISE_PAUSE_CAP;
+	if (phy_dev->advertising & ADVERTISED_Asym_Pause)
+		lcl_adv |= ADVERTISE_PAUSE_ASYM;
+
+	/* get link partner capabilities */
+	rmt_adv = 0;
+	if (phy_dev->pause)
+		rmt_adv |= LPA_PAUSE_CAP;
+	if (phy_dev->asym_pause)
+		rmt_adv |= LPA_PAUSE_ASYM;
+
+	/* Calculate TX/RX settings based on local and peer advertised
+	 * symmetric/asymmetric PAUSE capabilities.
+	 */
+	flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+	if (flowctrl & FLOW_CTRL_RX)
+		*rx_pause = true;
+	if (flowctrl & FLOW_CTRL_TX)
+		*tx_pause = true;
+}
+EXPORT_SYMBOL(get_pause_cfg);
+
+static void adjust_link(struct net_device *net_dev)
+{
+	struct device *dev = net_dev->dev.parent;
+	struct dpaa_eth_data *eth_data = dev->platform_data;
+	struct mac_device *mac_dev = eth_data->mac_dev;
+	struct phy_device *phy_dev = mac_dev->phy_dev;
+	struct fm_mac_dev *fm_mac_dev;
+	bool rx_pause, tx_pause;
+	int _errno;
+
+	fm_mac_dev = mac_dev->get_mac_handle(mac_dev);
+	fm_mac_adjust_link(fm_mac_dev, phy_dev->link, phy_dev->speed);
+
+	get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
+	_errno = set_mac_active_pause(mac_dev, rx_pause, tx_pause);
+	if (unlikely(_errno < 0))
+		netdev_err(net_dev, "set_mac_active_pause() = %d\n", _errno);
+}
+
+/* Initializes driver's PHY state, and attaches to the PHY.
+ * Returns 0 on success.
+ */
+static int dtsec_init_phy(struct net_device *net_dev,
+			  struct mac_device *mac_dev)
+{
+	struct phy_device	*phy_dev;
+
+	if (!mac_dev->phy_node)
+		phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id,
+				      &adjust_link, mac_dev->phy_if);
+	else
+		phy_dev = of_phy_connect(net_dev, mac_dev->phy_node,
+					 &adjust_link, 0, mac_dev->phy_if);
+	if (unlikely(!phy_dev) || IS_ERR(phy_dev)) {
+		netdev_err(net_dev, "Could not connect to PHY %s\n",
+			   mac_dev->phy_node ?
+				mac_dev->phy_node->full_name :
+				mac_dev->fixed_bus_id);
+		return (!phy_dev) ? -ENODEV : PTR_ERR(phy_dev);
+	}
+
+	/* Remove any features not supported by the controller */
+	phy_dev->supported &= mac_dev->if_support;
+	/* Enable the symmetric and asymmetric PAUSE frame advertisements,
+	 * as most of the PHY drivers do not enable them by default.
+	 */
+	phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+	phy_dev->advertising = phy_dev->supported;
+
+	mac_dev->phy_dev = phy_dev;
+
+	return 0;
+}
+
+static int xgmac_init_phy(struct net_device *net_dev,
+			  struct mac_device *mac_dev)
+{
+	struct phy_device *phy_dev;
+
+	if (!mac_dev->phy_node)
+		phy_dev = phy_attach(net_dev, mac_dev->fixed_bus_id,
+				     mac_dev->phy_if);
+	else
+		phy_dev = of_phy_attach(net_dev, mac_dev->phy_node, 0,
+					mac_dev->phy_if);
+	if (unlikely(!phy_dev) || IS_ERR(phy_dev)) {
+		netdev_err(net_dev, "Could not attach to PHY %s\n",
+			   mac_dev->phy_node ?
+				mac_dev->phy_node->full_name :
+				mac_dev->fixed_bus_id);
+		return (!phy_dev) ? -ENODEV : PTR_ERR(phy_dev);
+	}
+
+	phy_dev->supported &= mac_dev->if_support;
+	/* Enable the symmetric and asymmetric PAUSE frame advertisements,
+	 * as most of the PHY drivers do not enable them by default.
+	 */
+	phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+	phy_dev->advertising = phy_dev->supported;
+
+	mac_dev->phy_dev = phy_dev;
+
+	return 0;
+}
+
+static int memac_init_phy(struct net_device *net_dev,
+			  struct mac_device *mac_dev)
+{
+	struct phy_device       *phy_dev;
+
+	if (macdev2enetinterface(mac_dev) == ENET_MODE_XGMII_10000) {
+		if (!mac_dev->phy_node) {
+			mac_dev->phy_dev = NULL;
+			return 0;
+		}
+
+		phy_dev = of_phy_attach(net_dev, mac_dev->phy_node, 0,
+					mac_dev->phy_if);
+	} else {
+		if (!mac_dev->phy_node)
+			phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id,
+					      &adjust_link, mac_dev->phy_if);
+		else
+			phy_dev = of_phy_connect(net_dev, mac_dev->phy_node,
+						 &adjust_link, 0,
+						 mac_dev->phy_if);
+	}
+
+	if (unlikely(!phy_dev) || IS_ERR(phy_dev)) {
+		netdev_err(net_dev, "Could not connect to PHY %s\n",
+			   mac_dev->phy_node ?
+				mac_dev->phy_node->full_name :
+				mac_dev->fixed_bus_id);
+		return (!phy_dev) ? -ENODEV : PTR_ERR(phy_dev);
+	}
+
+	/* Remove any features not supported by the controller */
+	phy_dev->supported &= mac_dev->if_support;
+	/* Enable the symmetric and asymmetric PAUSE frame advertisements,
+	 * as most of the PHY drivers do not enable them by default.
+	 */
+	phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+	phy_dev->advertising = phy_dev->supported;
+
+	mac_dev->phy_dev = phy_dev;
+
+	return 0;
+}
+
+static int __cold uninit(struct fm_mac_dev *fm_mac_dev)
+{
+	int			 _errno, __errno;
+
+	_errno = fm_mac_disable(fm_mac_dev, COMM_MODE_RX_AND_TX);
+	__errno = fm_mac_free(fm_mac_dev);
+
+	if (unlikely(__errno < 0))
+		_errno = __errno;
+
+	return _errno;
+}
+
+static struct fm_mac_dev *get_mac_handle(struct mac_device *mac_dev)
+{
+	const struct mac_priv_s	*priv;
+
+	priv = macdev_priv(mac_dev);
+
+	return priv->fm_mac;
+}
+
+static void __cold setup_dtsec(struct mac_device *mac_dev)
+{
+	mac_dev->init_phy	= dtsec_init_phy;
+	mac_dev->init		= init;
+	mac_dev->start		= start;
+	mac_dev->stop		= stop;
+	mac_dev->set_promisc	= fm_mac_set_promiscuous;
+	mac_dev->change_addr    = fm_mac_modify_mac_addr;
+	mac_dev->set_multi      = set_multi;
+	mac_dev->uninit		= uninit;
+	mac_dev->get_mac_handle		= get_mac_handle;
+	mac_dev->set_tx_pause		= fm_mac_set_tx_pause_frames;
+	mac_dev->set_rx_pause		= fm_mac_set_rx_pause_frames;
+}
+
+static void __cold setup_xgmac(struct mac_device *mac_dev)
+{
+	mac_dev->init_phy	= xgmac_init_phy;
+	mac_dev->init		= init;
+	mac_dev->start		= start;
+	mac_dev->stop		= stop;
+	mac_dev->set_promisc	= fm_mac_set_promiscuous;
+	mac_dev->change_addr    = fm_mac_modify_mac_addr;
+	mac_dev->set_multi      = set_multi;
+	mac_dev->uninit		= uninit;
+	mac_dev->get_mac_handle	= get_mac_handle;
+	mac_dev->set_tx_pause	= fm_mac_set_tx_pause_frames;
+	mac_dev->set_rx_pause	= fm_mac_set_rx_pause_frames;
+}
+
+static void __cold setup_memac(struct mac_device *mac_dev)
+{
+	mac_dev->init_phy	= memac_init_phy;
+	mac_dev->init		= memac_init;
+	mac_dev->start		= start;
+	mac_dev->stop		= stop;
+	mac_dev->set_promisc	= fm_mac_set_promiscuous;
+	mac_dev->change_addr    = fm_mac_modify_mac_addr;
+	mac_dev->set_multi      = set_multi;
+	mac_dev->uninit		= uninit;
+	mac_dev->get_mac_handle		= get_mac_handle;
+	mac_dev->set_tx_pause		= fm_mac_set_tx_pause_frames;
+	mac_dev->set_rx_pause		= fm_mac_set_rx_pause_frames;
+}
+
+void (*const mac_setup[])(struct mac_device *mac_dev) = {
+	[DTSEC] = setup_dtsec,
+	[XGMAC] = setup_xgmac,
+	[MEMAC] = setup_memac
+};
diff --git a/drivers/net/ethernet/freescale/fman/mac/mac.c b/drivers/net/ethernet/freescale/fman/mac/mac.c
new file mode 100644
index 0000000..4eb8f7c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/mac.c
@@ -0,0 +1,527 @@
+/* Copyright 2008-2015 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+	KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+	KBUILD_BASENAME ".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+	KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/device.h>
+#include <linux/phy.h>
+
+#include "mac.h"
+
+#define DTSEC_SUPPORTED \
+	(SUPPORTED_10baseT_Half \
+	| SUPPORTED_10baseT_Full \
+	| SUPPORTED_100baseT_Half \
+	| SUPPORTED_100baseT_Full \
+	| SUPPORTED_Autoneg \
+	| SUPPORTED_Pause \
+	| SUPPORTED_Asym_Pause \
+	| SUPPORTED_MII)
+
+static DEFINE_MUTEX(eth_lock);
+
+static const char phy_str[][11] = {
+	[PHY_INTERFACE_MODE_MII]	= "mii",
+	[PHY_INTERFACE_MODE_GMII]	= "gmii",
+	[PHY_INTERFACE_MODE_SGMII]	= "sgmii",
+	[PHY_INTERFACE_MODE_TBI]	= "tbi",
+	[PHY_INTERFACE_MODE_RMII]	= "rmii",
+	[PHY_INTERFACE_MODE_RGMII]	= "rgmii",
+	[PHY_INTERFACE_MODE_RGMII_ID]	= "rgmii-id",
+	[PHY_INTERFACE_MODE_RGMII_RXID]	= "rgmii-rxid",
+	[PHY_INTERFACE_MODE_RGMII_TXID]	= "rgmii-txid",
+	[PHY_INTERFACE_MODE_RTBI]	= "rtbi",
+	[PHY_INTERFACE_MODE_XGMII]	= "xgmii"
+};
+
+static phy_interface_t __pure __attribute__((nonnull)) str2phy(const char *str)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(phy_str); i++)
+		if (strcmp(str, phy_str[i]) == 0)
+			return (phy_interface_t)i;
+
+	return PHY_INTERFACE_MODE_MII;
+}
+
+static const u16 phy2speed[] = {
+	[PHY_INTERFACE_MODE_MII]	= SPEED_100,
+	[PHY_INTERFACE_MODE_GMII]	= SPEED_1000,
+	[PHY_INTERFACE_MODE_SGMII]	= SPEED_1000,
+	[PHY_INTERFACE_MODE_TBI]	= SPEED_1000,
+	[PHY_INTERFACE_MODE_RMII]	= SPEED_100,
+	[PHY_INTERFACE_MODE_RGMII]	= SPEED_1000,
+	[PHY_INTERFACE_MODE_RGMII_ID]	= SPEED_1000,
+	[PHY_INTERFACE_MODE_RGMII_RXID]	= SPEED_1000,
+	[PHY_INTERFACE_MODE_RGMII_TXID]	= SPEED_1000,
+	[PHY_INTERFACE_MODE_RTBI]	= SPEED_1000,
+	[PHY_INTERFACE_MODE_XGMII]	= SPEED_10000
+};
+
+static struct mac_device * __cold
+alloc_macdev(struct device *dev, size_t sizeof_priv,
+	     void (*setup)(struct mac_device *mac_dev))
+{
+	struct mac_device	*mac_dev;
+
+	mac_dev = devm_kzalloc(dev, sizeof(*mac_dev) + sizeof_priv, GFP_KERNEL);
+	if (unlikely(!mac_dev)) {
+		mac_dev = ERR_PTR(-ENOMEM);
+	} else {
+		mac_dev->dev = dev;
+		dev_set_drvdata(dev, mac_dev);
+		setup(mac_dev);
+	}
+
+	return mac_dev;
+}
+
+static int __cold free_macdev(struct mac_device *mac_dev)
+{
+	dev_set_drvdata(mac_dev->dev, NULL);
+
+	return mac_dev->uninit(mac_dev->get_mac_handle(mac_dev));
+}
+
+static struct platform_device *dpaa_eth_add_device(int fman_id,
+						   struct mac_device *mac_dev,
+						   struct device_node *node)
+{
+	struct platform_device *pdev;
+	struct dpaa_eth_data data;
+	static int dpaa_eth_dev_cnt;
+	int ret;
+
+	data.mac_dev = mac_dev;
+	data.mac_hw_id = mac_dev->cell_index;
+	data.fman_hw_id = fman_id;
+	data.mac_node = node;
+
+	mutex_lock(&eth_lock);
+
+	pdev = platform_device_alloc("dpaa-ethernet", dpaa_eth_dev_cnt);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto no_mem;
+	}
+
+	ret = platform_device_add_data(pdev, &data, sizeof(data));
+	if (ret)
+		goto err;
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto err;
+
+	dpaa_eth_dev_cnt++;
+	mutex_unlock(&eth_lock);
+
+	return pdev;
+
+err:
+	platform_device_put(pdev);
+no_mem:
+	mutex_unlock(&eth_lock);
+
+	return ERR_PTR(ret);
+}
+
+static void dpaa_eth_remove_device(struct platform_device *pdev)
+{
+	platform_device_unregister(pdev);
+}
+
+static const struct of_device_id mac_match[] = {
+	[DTSEC] = {
+		.compatible	= "fsl,fman-dtsec"
+	},
+	[XGMAC] = {
+		.compatible	= "fsl,fman-xgec"
+	},
+	[MEMAC] = {
+		.compatible	= "fsl,fman-memac"
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, mac_match);
+
+static int __cold mac_probe(struct platform_device *_of_dev)
+{
+	int			 _errno, i, lenp;
+	struct device		*dev;
+	struct device_node	*mac_node, *dev_node;
+	struct mac_device	*mac_dev;
+	struct platform_device	*of_dev;
+	struct resource		 res;
+	const u8		*mac_addr;
+	const char		*char_prop;
+	const u32		*uint32_prop;
+	const struct of_device_id *match;
+	u8			 fman_id;
+
+	const phandle           *phandle_prop;
+
+	dev = &_of_dev->dev;
+	mac_node = dev->of_node;
+
+	match = of_match_device(mac_match, dev);
+	if (!match)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(mac_match) - 1 && match != mac_match + i;
+			i++)
+		;
+	BUG_ON(i >= ARRAY_SIZE(mac_match) - 1);
+
+	mac_dev = alloc_macdev(dev, mac_sizeof_priv[i], mac_setup[i]);
+	if (IS_ERR(mac_dev)) {
+		_errno = PTR_ERR(mac_dev);
+		dev_err(dev, "alloc_macdev() = %d\n", _errno);
+		goto _return;
+	}
+
+	INIT_LIST_HEAD(&mac_dev->mc_addr_list);
+
+	/* Get the FM node */
+	dev_node = of_get_parent(mac_node);
+	if (unlikely(!dev_node)) {
+		dev_err(dev, "of_get_parent(%s) failed\n",
+			mac_node->full_name);
+		_errno = -EINVAL;
+		goto _return_dev_set_drvdata;
+	}
+
+	of_dev = of_find_device_by_node(dev_node);
+	if (unlikely(!of_dev)) {
+		dev_err(dev, "of_find_device_by_node(%s) failed\n",
+			dev_node->full_name);
+		_errno = -EINVAL;
+		goto _return_of_node_put;
+	}
+
+	/* Get the FMan cell-index */
+	uint32_prop = of_get_property(dev_node, "cell-index", &lenp);
+	if (unlikely(!uint32_prop)) {
+		dev_err(dev, "of_get_property(%s, cell-index) failed\n",
+			dev_node->full_name);
+		_errno = -EINVAL;
+		goto _return_of_node_put;
+	}
+	BUG_ON(lenp != sizeof(u32));
+	fman_id = (u8)*uint32_prop + 1; /* cell-index 0 => FMan id 1 */
+
+	mac_dev->fm_dev = fm_bind(&of_dev->dev);
+	if (unlikely(!mac_dev->fm_dev)) {
+		dev_err(dev, "fm_bind(%s) failed\n", dev_node->full_name);
+		_errno = -ENODEV;
+		goto _return_of_node_put;
+	}
+
+	mac_dev->fm = (void *)fm_get_handle(mac_dev->fm_dev);
+	of_node_put(dev_node);
+
+	/* Get the address of the memory mapped registers */
+	_errno = of_address_to_resource(mac_node, 0, &res);
+	if (unlikely(_errno < 0)) {
+		dev_err(dev, "of_address_to_resource(%s) = %d\n",
+			mac_node->full_name, _errno);
+		goto _return_dev_set_drvdata;
+	}
+
+	mac_dev->res =
+		__devm_request_region(dev, fm_get_mem_region(mac_dev->fm_dev),
+				      res.start, res.end + 1 - res.start,
+				      "mac");
+	if (unlikely(!mac_dev->res)) {
+		dev_err(dev, "__devm_request_mem_region(mac) failed\n");
+		_errno = -EBUSY;
+		goto _return_dev_set_drvdata;
+	}
+
+	mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start,
+				      mac_dev->res->end + 1
+				      - mac_dev->res->start);
+	if (unlikely(!mac_dev->vaddr)) {
+		dev_err(dev, "devm_ioremap() failed\n");
+		_errno = -EIO;
+		goto _return_dev_set_drvdata;
+	}
+
+#define TBIPA_OFFSET		0x1c
+#define TBIPA_DEFAULT_ADDR	5 /* override if used as external PHY addr. */
+	mac_dev->tbi_node = of_parse_phandle(mac_node, "tbi-handle", 0);
+	if (mac_dev->tbi_node) {
+		u32 tbiaddr = TBIPA_DEFAULT_ADDR;
+
+		uint32_prop = of_get_property(mac_dev->tbi_node, "reg", NULL);
+		if (uint32_prop)
+			tbiaddr = *uint32_prop;
+		out_be32(mac_dev->vaddr + TBIPA_OFFSET, tbiaddr);
+	}
+
+	if (!of_device_is_available(mac_node)) {
+		devm_iounmap(dev, mac_dev->vaddr);
+		__devm_release_region(dev, fm_get_mem_region(mac_dev->fm_dev),
+				      res.start, res.end + 1 - res.start);
+		fm_unbind(mac_dev->fm_dev);
+		devm_kfree(dev, mac_dev);
+		dev_set_drvdata(dev, NULL);
+		return -ENODEV;
+	}
+
+	/* Get the cell-index */
+	uint32_prop = of_get_property(mac_node, "cell-index", &lenp);
+	if (unlikely(!uint32_prop)) {
+		dev_err(dev, "of_get_property(%s, cell-index) failed\n",
+			mac_node->full_name);
+		_errno = -EINVAL;
+		goto _return_dev_set_drvdata;
+	}
+	BUG_ON(lenp != sizeof(u32));
+	mac_dev->cell_index = (u8)*uint32_prop;
+
+	/* Get the MAC address */
+	mac_addr = of_get_mac_address(mac_node);
+	if (unlikely(!mac_addr)) {
+		dev_err(dev, "of_get_mac_address(%s) failed\n",
+			mac_node->full_name);
+		_errno = -EINVAL;
+		goto _return_dev_set_drvdata;
+	}
+	memcpy(mac_dev->addr, mac_addr, sizeof(mac_dev->addr));
+
+	/* Get the port handles */
+	phandle_prop = of_get_property(mac_node, "fsl,fman-ports", &lenp);
+	if (unlikely(!phandle_prop)) {
+		dev_err(dev, "of_get_property(%s, fsl,fman-ports) failed\n",
+			mac_node->full_name);
+		_errno = -EINVAL;
+		goto _return_dev_set_drvdata;
+	}
+	BUG_ON(lenp != sizeof(phandle) * ARRAY_SIZE(mac_dev->port_dev));
+
+	for_each_port_device(i, mac_dev->port_dev) {
+		/* Find the port node */
+		dev_node = of_find_node_by_phandle(phandle_prop[i]);
+		if (unlikely(!dev_node)) {
+			dev_err(dev, "of_find_node_by_phandle() failed\n");
+			_errno = -EINVAL;
+			goto _return_of_node_put;
+		}
+
+		of_dev = of_find_device_by_node(dev_node);
+		if (unlikely(!of_dev)) {
+			dev_err(dev, "of_find_device_by_node(%s) failed\n",
+				dev_node->full_name);
+			_errno = -EINVAL;
+			goto _return_of_node_put;
+		}
+
+		mac_dev->port_dev[i] = fm_port_bind(&of_dev->dev);
+		if (unlikely(!mac_dev->port_dev[i])) {
+			dev_err(dev, "dev_get_drvdata(%s) failed\n",
+				dev_node->full_name);
+			_errno = -EINVAL;
+			goto _return_of_node_put;
+		}
+		of_node_put(dev_node);
+	}
+
+	/* Get the PHY connection type */
+	char_prop = (const char *)of_get_property(mac_node,
+						"phy-connection-type", NULL);
+	if (unlikely(!char_prop)) {
+		dev_warn(dev,
+			 "of_get_property(%s, phy-connection-type) failed. Defaulting to MII\n",
+			 mac_node->full_name);
+		mac_dev->phy_if = PHY_INTERFACE_MODE_MII;
+	} else {
+		mac_dev->phy_if = str2phy(char_prop);
+	}
+
+	mac_dev->link		= false;
+	mac_dev->speed		= phy2speed[mac_dev->phy_if];
+	mac_dev->max_speed	= mac_dev->speed;
+	mac_dev->if_support = DTSEC_SUPPORTED;
+	/* We don't support half-duplex in SGMII mode */
+	if (strstr(char_prop, "sgmii"))
+		mac_dev->if_support &= ~(SUPPORTED_10baseT_Half |
+					SUPPORTED_100baseT_Half);
+
+	/* Gigabit support (no half-duplex) */
+	if (mac_dev->max_speed == 1000)
+		mac_dev->if_support |= SUPPORTED_1000baseT_Full;
+
+	/* The 10G interface only supports one mode */
+	if (strstr(char_prop, "xgmii"))
+		mac_dev->if_support = SUPPORTED_10000baseT_Full;
+
+	/* Get the rest of the PHY information */
+	mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0);
+	if (!mac_dev->phy_node) {
+		int sz;
+		const u32 *phy_id = of_get_property(mac_node, "fixed-link",
+							&sz);
+		if (!phy_id || sz < sizeof(*phy_id)) {
+			dev_err(dev, "No PHY (or fixed link) found\n");
+			_errno = -EINVAL;
+			goto _return_dev_set_drvdata;
+		}
+
+		sprintf(mac_dev->fixed_bus_id, PHY_ID_FMT, "fixed-0",
+			phy_id[0]);
+	}
+
+	_errno = mac_dev->init(mac_dev);
+	if (unlikely(_errno < 0)) {
+		dev_err(dev, "mac_dev->init() = %d\n", _errno);
+		goto _return_dev_set_drvdata;
+	}
+
+	/* pause frame autonegotiation enabled*/
+	mac_dev->autoneg_pause = true;
+
+	/* by intializing the values to false, force FMD to enable PAUSE frames
+	 * on RX and TX
+	 */
+	mac_dev->rx_pause_req = true;
+	mac_dev->tx_pause_req = true;
+	mac_dev->rx_pause_active = false;
+	mac_dev->tx_pause_active = false;
+	_errno = set_mac_active_pause(mac_dev, true, true);
+	if (unlikely(_errno < 0))
+		dev_err(dev, "set_mac_active_pause() = %d\n", _errno);
+
+	dev_info(dev,
+		 "FMan MAC address: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n",
+		     mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2],
+		     mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5]);
+
+	mac_dev->eth_dev = dpaa_eth_add_device(fman_id, mac_dev,
+					       mac_node);
+	if (IS_ERR(mac_dev->eth_dev)) {
+		dev_err(dev, "failed to add Ethernet platform device for MAC %d\n",
+			mac_dev->cell_index);
+		mac_dev->eth_dev = NULL;
+	}
+
+	goto _return;
+
+_return_of_node_put:
+	of_node_put(dev_node);
+_return_dev_set_drvdata:
+	dev_set_drvdata(dev, NULL);
+_return:
+	return _errno;
+}
+
+static int __cold mac_remove(struct platform_device *of_dev)
+{
+	int			 i, _errno;
+	struct device		*dev;
+	struct mac_device	*mac_dev;
+
+	dev = &of_dev->dev;
+	mac_dev = (struct mac_device *)dev_get_drvdata(dev);
+
+	dpaa_eth_remove_device(mac_dev->eth_dev);
+
+	for_each_port_device(i, mac_dev->port_dev)
+		fm_port_unbind(mac_dev->port_dev[i]);
+
+	fm_unbind(mac_dev->fm_dev);
+
+	_errno = free_macdev(mac_dev);
+
+	return _errno;
+}
+
+static struct platform_driver mac_driver = {
+	.driver = {
+		.name		= KBUILD_MODNAME,
+		.of_match_table	= mac_match,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= mac_probe,
+	.remove		= mac_remove
+};
+
+static int __init __cold mac_load(void)
+{
+	int	 _errno;
+
+	pr_debug(KBUILD_MODNAME ": -> %s:%s()\n",
+		 KBUILD_BASENAME ".c", __func__);
+
+	pr_info(KBUILD_MODNAME ": %s\n",
+		mac_driver_description);
+
+	_errno = platform_driver_register(&mac_driver);
+	if (unlikely(_errno < 0)) {
+		pr_err(KBUILD_MODNAME ": %s:%hu:%s(): platform_driver_register() = %d\n",
+		       KBUILD_BASENAME ".c", __LINE__, __func__, _errno);
+		goto _return;
+	}
+
+	goto _return;
+
+_return:
+	pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+		 KBUILD_BASENAME ".c", __func__);
+
+	return _errno;
+}
+module_init(mac_load);
+
+static void __exit __cold mac_unload(void)
+{
+	pr_debug(KBUILD_MODNAME ": -> %s:%s()\n",
+		 KBUILD_BASENAME ".c", __func__);
+
+	platform_driver_unregister(&mac_driver);
+
+	pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+		 KBUILD_BASENAME ".c", __func__);
+}
+module_exit(mac_unload);
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC,v3,04/12] fsl/fman: Add the FMan port FLIB
@ 2015-04-29  9:27 Igal.Liberman
  0 siblings, 0 replies; 13+ messages in thread
From: Igal.Liberman @ 2015-04-29  9:27 UTC (permalink / raw)
  To: netdev; +Cc: Igal Liberman, linuxppc-dev, linux-kernel, madalin.bucur

From: Igal Liberman <Igal.Liberman@freescale.com>

The FMan Port FLib provides basic API used by the drivers to
configure and control the FMan Port hardware.

Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
 drivers/net/ethernet/freescale/fman/Kconfig        |    1 +
 drivers/net/ethernet/freescale/fman/Makefile       |    2 +
 drivers/net/ethernet/freescale/fman/port/Makefile  |    3 +
 .../net/ethernet/freescale/fman/port/fman_port.c   |  728 ++++++++++++++++++++
 4 files changed, 734 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/fman/port/Makefile
 create mode 100644 drivers/net/ethernet/freescale/fman/port/fman_port.c

diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
index 8aeae29..af42c3a 100644
--- a/drivers/net/ethernet/freescale/fman/Kconfig
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -5,3 +5,4 @@ config FSL_FMAN
 	help
 		Freescale Data-Path Acceleration Architecture Frame Manager
 		(FMan) support
+
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index a718f7c..a9ae0aa 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -3,3 +3,5 @@ subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib
 obj-y		+= fsl_fman.o
 
 fsl_fman-objs			:= fman.o
+
+obj-y	+= port/
diff --git a/drivers/net/ethernet/freescale/fman/port/Makefile b/drivers/net/ethernet/freescale/fman/port/Makefile
new file mode 100644
index 0000000..54b1fa4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/port/Makefile
@@ -0,0 +1,3 @@
+obj-y	+= fsl_fman_port.o
+
+fsl_fman_port-objs		:= fman_port.o
diff --git a/drivers/net/ethernet/freescale/fman/port/fman_port.c b/drivers/net/ethernet/freescale/fman/port/fman_port.c
new file mode 100644
index 0000000..7d04084
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/port/fman_port.c
@@ -0,0 +1,728 @@
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "common/general.h"
+
+#include "fman_common.h"
+#include "fsl_fman_port.h"
+
+/* problem Eyal: the following should not be here*/
+#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME	0x00000028
+
+static uint32_t get_no_pcd_nia_bmi_ac_enc_frame(struct fman_port_cfg *cfg)
+{
+	if (cfg->errata_A006675)
+		return NIA_ENG_FM_CTL |
+		    NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME;
+	else
+		return NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME;
+}
+
+static int init_bmi_rx(struct fman_port *port,
+		       struct fman_port_cfg *cfg,
+		       struct fman_port_params *params)
+{
+	struct fman_port_rx_bmi_regs __iomem *regs = &port->bmi_regs->rx;
+	uint32_t tmp;
+
+	/* Rx Configuration register */
+	tmp = 0;
+	if (cfg->discard_override)
+		tmp |= BMI_PORT_CFG_FDOVR;
+	iowrite32be(tmp, &regs->fmbm_rcfg);
+
+	/* DMA attributes */
+	tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+	if (cfg->dma_ic_stash_on)
+		tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+	if (cfg->dma_header_stash_on)
+		tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+	if (cfg->dma_sg_stash_on)
+		tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+	if (cfg->dma_write_optimize)
+		tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
+	iowrite32be(tmp, &regs->fmbm_rda);
+
+	/* Rx FIFO parameters */
+	tmp = (cfg->rx_pri_elevation / FMAN_PORT_BMI_FIFO_UNITS - 1) <<
+	    BMI_RX_FIFO_PRI_ELEVATION_SHIFT;
+	tmp |= cfg->rx_fifo_thr / FMAN_PORT_BMI_FIFO_UNITS - 1;
+	iowrite32be(tmp, &regs->fmbm_rfp);
+
+	if (cfg->excessive_threshold_register)
+		/* always allow access to the extra resources */
+		iowrite32be(BMI_RX_FIFO_THRESHOLD_ETHE, &regs->fmbm_reth);
+
+	/* Frame end data */
+	tmp = (uint32_t)cfg->checksum_bytes_ignore <<
+	    BMI_RX_FRAME_END_CS_IGNORE_SHIFT;
+	tmp |= (uint32_t)cfg->rx_cut_end_bytes << BMI_RX_FRAME_END_CUT_SHIFT;
+	if (cfg->errata_A006320)
+		tmp &= 0xffe0ffff;
+	iowrite32be(tmp, &regs->fmbm_rfed);
+
+	/* Internal context parameters */
+	tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_TO_EXT_SHIFT;
+	tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_FROM_INT_SHIFT;
+	tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+	iowrite32be(tmp, &regs->fmbm_ricp);
+
+	/* Internal buffer offset */
+	tmp = ((uint32_t)cfg->int_buf_start_margin / FMAN_PORT_IC_OFFSET_UNITS)
+	    << BMI_INT_BUF_MARG_SHIFT;
+	iowrite32be(tmp, &regs->fmbm_rim);
+
+	/* External buffer margins */
+	tmp = (uint32_t)cfg->ext_buf_start_margin <<
+	    BMI_EXT_BUF_MARG_START_SHIFT;
+	tmp |= (uint32_t)cfg->ext_buf_end_margin;
+	if (cfg->fmbm_rebm_has_sgd && cfg->no_scatter_gather)
+		tmp |= BMI_SG_DISABLE;
+	iowrite32be(tmp, &regs->fmbm_rebm);
+
+	/* Frame attributes */
+	tmp = BMI_CMD_RX_MR_DEF;
+	tmp |= BMI_CMD_ATTR_ORDER;
+	tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+	if (cfg->sync_req)
+		tmp |= BMI_CMD_ATTR_SYNC;
+
+	iowrite32be(tmp, &regs->fmbm_rfca);
+
+	/* NIA */
+	tmp = (uint32_t)cfg->rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT;
+	tmp |= get_no_pcd_nia_bmi_ac_enc_frame(cfg);
+
+	iowrite32be(tmp, &regs->fmbm_rfne);
+
+	/* Enqueue NIA */
+	iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, &regs->fmbm_rfene);
+
+	/* Default/error queues */
+	iowrite32be((params->dflt_fqid & 0x00FFFFFF), &regs->fmbm_rfqid);
+	iowrite32be((params->err_fqid & 0x00FFFFFF), &regs->fmbm_refqid);
+
+	/* Discard/error masks */
+	iowrite32be(params->discard_mask, &regs->fmbm_rfsdm);
+	iowrite32be(params->err_mask, &regs->fmbm_rfsem);
+
+	/* Statistics counters */
+	tmp = 0;
+	if (cfg->stats_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_rstc);
+
+	/* Performance counters */
+	fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+	tmp = 0;
+	if (cfg->perf_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_rpc);
+
+	return 0;
+}
+
+static int init_bmi_tx(struct fman_port *port,
+		       struct fman_port_cfg *cfg,
+		       struct fman_port_params *params)
+{
+	struct fman_port_tx_bmi_regs __iomem *regs = &port->bmi_regs->tx;
+	uint32_t tmp;
+
+	/* Tx Configuration register */
+	tmp = 0;
+	iowrite32be(tmp, &regs->fmbm_tcfg);
+
+	/* DMA attributes */
+	tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+	if (cfg->dma_ic_stash_on)
+		tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+	if (cfg->dma_header_stash_on)
+		tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+	if (cfg->dma_sg_stash_on)
+		tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+	iowrite32be(tmp, &regs->fmbm_tda);
+
+	/* Tx FIFO parameters */
+	tmp = (cfg->tx_fifo_min_level / FMAN_PORT_BMI_FIFO_UNITS) <<
+	    BMI_TX_FIFO_MIN_FILL_SHIFT;
+	tmp |= ((uint32_t)cfg->tx_fifo_deq_pipeline_depth - 1) <<
+	    BMI_FIFO_PIPELINE_DEPTH_SHIFT;
+	tmp |= (uint32_t)(cfg->tx_fifo_low_comf_level /
+			   FMAN_PORT_BMI_FIFO_UNITS - 1);
+	iowrite32be(tmp, &regs->fmbm_tfp);
+
+	/* Frame end data */
+	tmp = (uint32_t)cfg->checksum_bytes_ignore <<
+	    BMI_FRAME_END_CS_IGNORE_SHIFT;
+	iowrite32be(tmp, &regs->fmbm_tfed);
+
+	/* Internal context parameters */
+	tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_TO_EXT_SHIFT;
+	tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_FROM_INT_SHIFT;
+	tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+	iowrite32be(tmp, &regs->fmbm_ticp);
+
+	/* Frame attributes */
+	tmp = BMI_CMD_TX_MR_DEF;
+	tmp |= BMI_CMD_ATTR_ORDER;
+	tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+	iowrite32be(tmp, &regs->fmbm_tfca);
+
+	/* Dequeue NIA + enqueue NIA */
+	iowrite32be(NIA_ENG_QMI_DEQ, &regs->fmbm_tfdne);
+	iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, &regs->fmbm_tfene);
+	if (cfg->fmbm_tfne_has_features)
+		iowrite32be(!params->dflt_fqid ?
+			    BMI_EBD_EN | NIA_BMI_AC_FETCH_ALL_FRAME :
+			    NIA_BMI_AC_FETCH_ALL_FRAME, &regs->fmbm_tfne);
+	if (!params->dflt_fqid && params->dont_release_buf) {
+		iowrite32be(0x00FFFFFF, &regs->fmbm_tcfqid);
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE,
+			    &regs->fmbm_tfene);
+		if (cfg->fmbm_tfne_has_features)
+			iowrite32be(ioread32be(&regs->fmbm_tfne) & ~BMI_EBD_EN,
+				    &regs->fmbm_tfne);
+	}
+
+	/* Confirmation/error queues */
+	if (params->dflt_fqid || !params->dont_release_buf)
+		iowrite32be(params->dflt_fqid & 0x00FFFFFF, &regs->fmbm_tcfqid);
+	iowrite32be((params->err_fqid & 0x00FFFFFF), &regs->fmbm_tefqid);
+
+	/* Statistics counters */
+	tmp = 0;
+	if (cfg->stats_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_tstc);
+
+	/* Performance counters */
+	fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+	tmp = 0;
+	if (cfg->perf_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_tpc);
+
+	return 0;
+}
+
+static int init_bmi_oh(struct fman_port *port,
+		       struct fman_port_cfg *cfg,
+		       struct fman_port_params *params)
+{
+	struct fman_port_oh_bmi_regs __iomem *regs = &port->bmi_regs->oh;
+	uint32_t tmp;
+
+	/* OP Configuration register */
+	tmp = 0;
+	if (cfg->discard_override)
+		tmp |= BMI_PORT_CFG_FDOVR;
+	iowrite32be(tmp, &regs->fmbm_ocfg);
+
+	/* DMA attributes */
+	tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+	if (cfg->dma_ic_stash_on)
+		tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+	if (cfg->dma_header_stash_on)
+		tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+	if (cfg->dma_sg_stash_on)
+		tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+	if (cfg->dma_write_optimize)
+		tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
+	iowrite32be(tmp, &regs->fmbm_oda);
+
+	/* Tx FIFO parameters */
+	tmp = ((uint32_t)cfg->tx_fifo_deq_pipeline_depth - 1) <<
+	    BMI_FIFO_PIPELINE_DEPTH_SHIFT;
+	iowrite32be(tmp, &regs->fmbm_ofp);
+
+	/* Internal context parameters */
+	tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_TO_EXT_SHIFT;
+	tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+	    BMI_IC_FROM_INT_SHIFT;
+	tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+	iowrite32be(tmp, &regs->fmbm_oicp);
+
+	/* Frame attributes */
+	tmp = BMI_CMD_OP_MR_DEF;
+	tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+	if (cfg->sync_req)
+		tmp |= BMI_CMD_ATTR_SYNC;
+	if (port->type == E_FMAN_PORT_TYPE_OP)
+		tmp |= BMI_CMD_ATTR_ORDER;
+	iowrite32be(tmp, &regs->fmbm_ofca);
+
+	/* Internal buffer offset */
+	tmp = ((uint32_t)cfg->int_buf_start_margin / FMAN_PORT_IC_OFFSET_UNITS)
+	    << BMI_INT_BUF_MARG_SHIFT;
+	iowrite32be(tmp, &regs->fmbm_oim);
+
+	/* Dequeue NIA */
+	iowrite32be(NIA_ENG_QMI_DEQ, &regs->fmbm_ofdne);
+
+	/* NIA and Enqueue NIA */
+	iowrite32be(get_no_pcd_nia_bmi_ac_enc_frame(cfg),
+		    &regs->fmbm_ofne);
+	iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR,
+		    &regs->fmbm_ofene);
+
+	/* Default/error queues */
+	iowrite32be((params->dflt_fqid & 0x00FFFFFF), &regs->fmbm_ofqid);
+	iowrite32be((params->err_fqid & 0x00FFFFFF), &regs->fmbm_oefqid);
+
+	/* Discard/error masks */
+	if (port->type == E_FMAN_PORT_TYPE_OP) {
+		iowrite32be(params->discard_mask, &regs->fmbm_ofsdm);
+		iowrite32be(params->err_mask, &regs->fmbm_ofsem);
+	}
+
+	/* Statistics counters */
+	tmp = 0;
+	if (cfg->stats_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_ostc);
+
+	/* Performance counters */
+	fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+	tmp = 0;
+	if (cfg->perf_counters_enable)
+		tmp = BMI_COUNTERS_EN;
+	iowrite32be(tmp, &regs->fmbm_opc);
+
+	return 0;
+}
+
+static int init_qmi(struct fman_port *port,
+		    struct fman_port_cfg *cfg, struct fman_port_params *params)
+{
+	struct fman_port_qmi_regs __iomem *regs = port->qmi_regs;
+	uint32_t tmp;
+
+	tmp = 0;
+	if (cfg->queue_counters_enable)
+		tmp |= QMI_PORT_CFG_EN_COUNTERS;
+	iowrite32be(tmp, &regs->fmqm_pnc);
+
+	/* Rx port configuration */
+	if ((port->type == E_FMAN_PORT_TYPE_RX) ||
+	    (port->type == E_FMAN_PORT_TYPE_RX_10G)) {
+		/* Enqueue NIA */
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, &regs->fmqm_pnen);
+		return 0;
+	}
+
+	/* Continue with Tx and O/H port configuration */
+	if ((port->type == E_FMAN_PORT_TYPE_TX) ||
+	    (port->type == E_FMAN_PORT_TYPE_TX_10G)) {
+		/* Enqueue NIA */
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE,
+			    &regs->fmqm_pnen);
+		/* Dequeue NIA */
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX, &regs->fmqm_pndn);
+	} else {
+		/* Enqueue NIA */
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, &regs->fmqm_pnen);
+		/* Dequeue NIA */
+		iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_FETCH, &regs->fmqm_pndn);
+	}
+
+	/* Dequeue Configuration register */
+	tmp = 0;
+	if (cfg->deq_high_pri)
+		tmp |= QMI_DEQ_CFG_PRI;
+
+	switch (cfg->deq_type) {
+	case E_FMAN_PORT_DEQ_BY_PRI:
+		tmp |= QMI_DEQ_CFG_TYPE1;
+		break;
+	case E_FMAN_PORT_DEQ_ACTIVE_FQ:
+		tmp |= QMI_DEQ_CFG_TYPE2;
+		break;
+	case E_FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS:
+		tmp |= QMI_DEQ_CFG_TYPE3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (cfg->qmi_deq_options_support) {
+		switch (cfg->deq_prefetch_opt) {
+		case E_FMAN_PORT_DEQ_NO_PREFETCH:
+			break;
+		case E_FMAN_PORT_DEQ_PART_PREFETCH:
+			tmp |= QMI_DEQ_CFG_PREFETCH_PARTIAL;
+			break;
+		case E_FMAN_PORT_DEQ_FULL_PREFETCH:
+			tmp |= QMI_DEQ_CFG_PREFETCH_FULL;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+	tmp |= (uint32_t)(params->deq_sp & QMI_DEQ_CFG_SP_MASK) <<
+		QMI_DEQ_CFG_SP_SHIFT;
+	tmp |= cfg->deq_byte_cnt;
+	iowrite32be(tmp, &regs->fmqm_pndc);
+
+	return 0;
+}
+
+void fman_port_defconfig(struct fman_port_cfg *cfg, enum fman_port_type type)
+{
+	cfg->dma_swap_data = E_FMAN_PORT_DMA_NO_SWAP;
+	cfg->dma_ic_stash_on = false;
+	cfg->dma_header_stash_on = false;
+	cfg->dma_sg_stash_on = false;
+	cfg->dma_write_optimize = true;
+	cfg->color = E_FMAN_PORT_COLOR_GREEN;
+	cfg->discard_override = false;
+	cfg->checksum_bytes_ignore = 0;
+	cfg->rx_cut_end_bytes = 4;
+	cfg->rx_pri_elevation = ((0x3FF + 1) * FMAN_PORT_BMI_FIFO_UNITS);
+	cfg->rx_fifo_thr = ((0x3FF + 1) * FMAN_PORT_BMI_FIFO_UNITS);
+	cfg->rx_fd_bits = 0;
+	cfg->ic_ext_offset = 0;
+	cfg->ic_int_offset = 0;
+	cfg->ic_size = 0;
+	cfg->int_buf_start_margin = 0;
+	cfg->ext_buf_start_margin = 0;
+	cfg->ext_buf_end_margin = 0;
+	cfg->tx_fifo_min_level = 0;
+	cfg->tx_fifo_low_comf_level = (5 * 1024);
+	cfg->stats_counters_enable = true;
+	cfg->perf_counters_enable = true;
+	cfg->deq_type = E_FMAN_PORT_DEQ_BY_PRI;
+
+	cfg->sync_req = true;
+	cfg->deq_prefetch_opt = E_FMAN_PORT_DEQ_FULL_PREFETCH;
+
+	if (type == E_FMAN_PORT_TYPE_TX_10G) {
+		cfg->tx_fifo_deq_pipeline_depth = 4;
+		cfg->deq_high_pri = true;
+		cfg->deq_byte_cnt = 0x1400;
+	} else {
+		if (type == E_FMAN_PORT_TYPE_OP)
+			cfg->tx_fifo_deq_pipeline_depth = 2;
+		else
+			cfg->tx_fifo_deq_pipeline_depth = 1;
+
+		cfg->deq_high_pri = false;
+		cfg->deq_byte_cnt = 0x400;
+	}
+	cfg->no_scatter_gather = DEFAULT_FMAN_SP_NO_SCATTER_GATHER;
+}
+
+int fman_port_init(struct fman_port *port,
+		   struct fman_port_cfg *cfg, struct fman_port_params *params)
+{
+	int err;
+
+	/* Init BMI registers */
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+		err = init_bmi_rx(port, cfg, params);
+		break;
+	case E_FMAN_PORT_TYPE_TX:
+	case E_FMAN_PORT_TYPE_TX_10G:
+		err = init_bmi_tx(port, cfg, params);
+		break;
+	case E_FMAN_PORT_TYPE_OP:
+		err = init_bmi_oh(port, cfg, params);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (err)
+		return err;
+
+	/* Init QMI registers */
+	err = init_qmi(port, cfg, params);
+	return err;
+
+	return 0;
+}
+
+int fman_port_enable(struct fman_port *port)
+{
+	uint32_t __iomem *bmi_cfg_reg;
+	uint32_t tmp;
+	bool rx_port;
+
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+		bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg;
+		rx_port = true;
+		break;
+	case E_FMAN_PORT_TYPE_TX:
+	case E_FMAN_PORT_TYPE_TX_10G:
+		bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg;
+		rx_port = false;
+		break;
+	case E_FMAN_PORT_TYPE_OP:
+		bmi_cfg_reg = &port->bmi_regs->oh.fmbm_ocfg;
+		rx_port = false;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Enable QMI */
+	if (!rx_port) {
+		tmp = ioread32be(&port->qmi_regs->fmqm_pnc) | QMI_PORT_CFG_EN;
+		iowrite32be(tmp, &port->qmi_regs->fmqm_pnc);
+	}
+
+	/* Enable BMI */
+	tmp = ioread32be(bmi_cfg_reg) | BMI_PORT_CFG_EN;
+	iowrite32be(tmp, bmi_cfg_reg);
+
+	return 0;
+}
+
+int fman_port_disable(const struct fman_port *port)
+{
+	uint32_t __iomem *bmi_cfg_reg, *bmi_status_reg;
+	uint32_t tmp;
+	bool rx_port, failure = false;
+	int count;
+
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+		bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg;
+		bmi_status_reg = &port->bmi_regs->rx.fmbm_rst;
+		rx_port = true;
+		break;
+	case E_FMAN_PORT_TYPE_TX:
+	case E_FMAN_PORT_TYPE_TX_10G:
+		bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg;
+		bmi_status_reg = &port->bmi_regs->tx.fmbm_tst;
+		rx_port = false;
+		break;
+	case E_FMAN_PORT_TYPE_OP:
+		bmi_cfg_reg = &port->bmi_regs->oh.fmbm_ocfg;
+		bmi_status_reg = &port->bmi_regs->oh.fmbm_ost;
+		rx_port = false;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Disable QMI */
+	if (!rx_port) {
+		tmp = ioread32be(&port->qmi_regs->fmqm_pnc) & ~QMI_PORT_CFG_EN;
+		iowrite32be(tmp, &port->qmi_regs->fmqm_pnc);
+
+		/* Wait for QMI to finish FD handling */
+		count = 100;
+		do {
+			usleep_range(10, 11);
+			tmp = ioread32be(&port->qmi_regs->fmqm_pns);
+		} while ((tmp & QMI_PORT_STATUS_DEQ_FD_BSY) && --count);
+
+		if (count == 0) {
+			/* Timeout */
+			failure = true;
+		}
+	}
+
+	/* Disable BMI */
+	tmp = ioread32be(bmi_cfg_reg) & ~BMI_PORT_CFG_EN;
+	iowrite32be(tmp, bmi_cfg_reg);
+
+	/* Wait for graceful stop end */
+	count = 500;
+	do {
+		usleep_range(10, 11);
+		tmp = ioread32be(bmi_status_reg);
+	} while ((tmp & BMI_PORT_STATUS_BSY) && --count);
+
+	if (count == 0) {
+		/* Timeout */
+		failure = true;
+	}
+
+	if (failure)
+		return -EBUSY;
+
+	return 0;
+}
+
+int fman_port_set_bpools(const struct fman_port *port,
+			 const struct fman_port_bpools *bp)
+{
+	uint32_t __iomem *bp_reg, *bp_depl_reg;
+	uint32_t tmp;
+	uint8_t i, max_bp_num;
+	bool grp_depl_used = false, rx_port;
+
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+		max_bp_num = port->ext_pools_num;
+		rx_port = true;
+		bp_reg = port->bmi_regs->rx.fmbm_ebmpi;
+		bp_depl_reg = &port->bmi_regs->rx.fmbm_mpd;
+		break;
+	case E_FMAN_PORT_TYPE_OP:
+		if (port->fm_rev_maj != 4)
+			return -EINVAL;
+		max_bp_num = FMAN_PORT_OBS_EXT_POOLS_NUM;
+		rx_port = false;
+		bp_reg = port->bmi_regs->oh.fmbm_oebmpi;
+		bp_depl_reg = &port->bmi_regs->oh.fmbm_ompd;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (rx_port) {
+		/* Check buffers are provided in ascending order */
+		for (i = 0; (i < (bp->count - 1) &&
+			     (i < FMAN_PORT_MAX_EXT_POOLS_NUM - 1)); i++) {
+			if (bp->bpool[i].size > bp->bpool[i + 1].size)
+				return -EINVAL;
+		}
+	}
+
+	/* Set up external buffers pools */
+	for (i = 0; i < bp->count; i++) {
+		tmp = BMI_EXT_BUF_POOL_VALID;
+		tmp |= ((uint32_t)bp->bpool[i].bpid <<
+			BMI_EXT_BUF_POOL_ID_SHIFT) & BMI_EXT_BUF_POOL_ID_MASK;
+
+		if (rx_port) {
+			if (bp->counters_enable)
+				tmp |= BMI_EXT_BUF_POOL_EN_COUNTER;
+
+			if (bp->bpool[i].is_backup)
+				tmp |= BMI_EXT_BUF_POOL_BACKUP;
+
+			tmp |= (uint32_t)bp->bpool[i].size;
+		}
+
+		iowrite32be(tmp, &bp_reg[i]);
+	}
+
+	/* Clear unused pools */
+	for (i = bp->count; i < max_bp_num; i++)
+		iowrite32be(0, &bp_reg[i]);
+
+	/* Pools depletion */
+	tmp = 0;
+	for (i = 0; i < FMAN_PORT_MAX_EXT_POOLS_NUM; i++) {
+		if (bp->bpool[i].grp_bp_depleted) {
+			grp_depl_used = true;
+			tmp |= 0x80000000 >> i;
+		}
+
+		if (bp->bpool[i].single_bp_depleted)
+			tmp |= 0x80 >> i;
+	}
+
+	if (grp_depl_used)
+		tmp |= ((uint32_t)bp->grp_bp_depleted_num - 1) <<
+		    BMI_POOL_DEP_NUM_OF_POOLS_SHIFT;
+
+	iowrite32be(tmp, bp_depl_reg);
+	return 0;
+}
+
+int fman_port_set_perf_cnt_params(struct fman_port *port,
+				  struct fman_port_perf_cnt_params *params)
+{
+	uint32_t __iomem *pcp_reg;
+	uint32_t tmp;
+
+	/* Obtain register address and check parameters are in range */
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+		pcp_reg = &port->bmi_regs->rx.fmbm_rpcp;
+		if ((params->queue_val == 0) ||
+		    (params->queue_val > MAX_PERFORMANCE_RX_QUEUE_COMP))
+			return -EINVAL;
+		break;
+	case E_FMAN_PORT_TYPE_TX:
+	case E_FMAN_PORT_TYPE_TX_10G:
+		pcp_reg = &port->bmi_regs->tx.fmbm_tpcp;
+		if ((params->queue_val == 0) ||
+		    (params->queue_val > MAX_PERFORMANCE_TX_QUEUE_COMP))
+			return -EINVAL;
+		break;
+	case E_FMAN_PORT_TYPE_OP:
+		pcp_reg = &port->bmi_regs->oh.fmbm_opcp;
+		if (params->queue_val != 0)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if ((params->task_val == 0) ||
+	    (params->task_val > MAX_PERFORMANCE_TASK_COMP))
+		return -EINVAL;
+	if ((params->dma_val == 0) ||
+	    (params->dma_val > MAX_PERFORMANCE_DMA_COMP))
+		return -EINVAL;
+	if ((params->fifo_val == 0) ||
+	    ((params->fifo_val / FMAN_PORT_BMI_FIFO_UNITS) >
+	     MAX_PERFORMANCE_FIFO_COMP))
+		return -EINVAL;
+	tmp = (uint32_t)(params->task_val - 1) <<
+	    BMI_PERFORMANCE_TASK_COMP_SHIFT;
+	tmp |= (uint32_t)(params->dma_val - 1) <<
+	    BMI_PERFORMANCE_DMA_COMP_SHIFT;
+	tmp |= (uint32_t)(params->fifo_val / FMAN_PORT_BMI_FIFO_UNITS - 1);
+
+	switch (port->type) {
+	case E_FMAN_PORT_TYPE_RX:
+	case E_FMAN_PORT_TYPE_RX_10G:
+	case E_FMAN_PORT_TYPE_TX:
+	case E_FMAN_PORT_TYPE_TX_10G:
+		tmp |= (uint32_t)(params->queue_val - 1) <<
+		    BMI_PERFORMANCE_QUEUE_COMP_SHIFT;
+		break;
+	default:
+		break;
+	}
+
+	iowrite32be(tmp, pcp_reg);
+	return 0;
+}
-- 
1.7.9.5

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-05-07 13:21 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-07 13:05 [RFC,v3 01/12] fsl/fman: Add the FMan FLIB headers Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 02/12] fsl/fman: Add the FMan FLIB Madalin Bucur
2015-05-07 13:05   ` [RFC,v3 03/12] fsl/fman: Add the FMan port FLIB headers Madalin Bucur
2015-05-07 13:05     ` [RFC,v3 04/12] fsl/fman: Add the FMan port FLIB Madalin Bucur
2015-05-07 13:05       ` [RFC,v3 05/12] fsl/fman: Add the FMan MAC FLIB headers Madalin Bucur
2015-05-07 13:05         ` [RFC,v3 06/12] fsl/fman: Add the FMan MAC FLIB Madalin Bucur
2015-05-07 13:05           ` [RFC,v3 07/12] fsl/fman: Add FMan MURAM support Madalin Bucur
2015-05-07 13:05             ` [RFC,v3 08/12] fsl/fman: Add Frame Manager support Madalin Bucur
2015-05-07 13:05               ` [RFC,v3 09/12] fsl/fman: Add FMan MAC support Madalin Bucur
2015-05-07 13:05                 ` [RFC,v3 10/12] fsl/fman: Add FMan SP support Madalin Bucur
2015-05-07 13:05                   ` [RFC,v3 11/12] fsl/fman: Add FMan Port Support Madalin Bucur
2015-05-07 13:05                     ` [RFC,v3 12/12] fsl/fman: Add FMan MAC driver Madalin Bucur
  -- strict thread matches above, loose matches on Subject: below --
2015-04-29  9:27 [RFC,v3,04/12] fsl/fman: Add the FMan port FLIB Igal.Liberman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).