layerscape: add ls1088ardb device support
[openwrt/staging/yousong.git] / target / linux / layerscape / patches-4.4 / 7208-staging-fsl-dpaa2-mac-Added-MAC-PHY-interface-driver.patch
diff --git a/target/linux/layerscape/patches-4.4/7208-staging-fsl-dpaa2-mac-Added-MAC-PHY-interface-driver.patch b/target/linux/layerscape/patches-4.4/7208-staging-fsl-dpaa2-mac-Added-MAC-PHY-interface-driver.patch
new file mode 100644 (file)
index 0000000..42a23a5
--- /dev/null
@@ -0,0 +1,2347 @@
+From ecaf55d2907835cd0580903e134cdf08416ff694 Mon Sep 17 00:00:00 2001
+From: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+Date: Tue, 15 Sep 2015 10:27:19 -0500
+Subject: [PATCH 208/226] staging: fsl-dpaa2: mac: Added MAC / PHY interface
+ driver
+
+This is a commit of the cummulative, squashed dpmac patches.
+All the commit logs are preserved below.
+
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+
+--------------------------------------------------------------
+
+flib,dpmac: add dpmac files (Rebasing onto kernel 3.19, MC 0.6)
+
+patches moved from 4.0 kernel
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+[Stuart: cherry-picked patch and split it up]
+Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+staging: fsl-dpaa2: mac: Added MAC / PHY interface driver.
+
+This driver works as a proxy between phylib including phy drivers and
+the MC firmware.  It receives updates on link state changes from PHY
+lib and forwards them to MC and receives interrupt from MC whenever
+a request is made to change the link state.
+
+Signed-off-by: Alex Marginean <alexandru.marginean@freescale.com>
+Change-Id: I8097ea69ea8effded3bddd43b9d326bbb59ba6c8
+Reviewed-on: http://git.am.freescale.net:8181/35113
+Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
+Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+fsl-dpaa2: mac: Change IRQ flags
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+Change-Id: Ia86570858f9cf7f673089cd7c2078662d56b2f01
+Reviewed-on: http://git.am.freescale.net:8181/35581
+Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
+Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+fsl-dpaa2: mac: Check for actual link state change
+
+Do not invoke the MC firmware if the link state hasn't changed.
+
+Signed-off-by: Alex Marginean <alexandru.marginean@freescale.com>
+Change-Id: Iba59d8b52c72334efa28f6126e50ec821c802852
+Reviewed-on: http://git.am.freescale.net:8181/35582
+Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
+Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+fsl-dpaa2: mac: Fix "dpmac netdevs" probing
+
+Fixup code under DPAA2_MAC_NETDEVS to probe again. In particular, remove
+the temporary addition of "fixed.c" in the mac/ folder.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+Change-Id: Iea6768f3c5cd9b2de2c8421c03ecebf155b9792b
+Reviewed-on: http://git.am.freescale.net:8181/37673
+Reviewed-by: Ruxandra Ioana Radulescu <ruxandra.radulescu@freescale.com>
+Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
+Tested-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+flib: Remove duplicate header files
+
+These files are included by the DPAA2 mac driver files.
+
+Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
+Change-Id: Ieff56e3c34393ef65a5ac1123aaf00bacefa050c
+Reviewed-on: http://git.am.freescale.net:8181/37257
+Reviewed-by: Alexandru Marginean <Alexandru.Marginean@freescale.com>
+Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
+Tested-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+fsl-dpaa2: mac: Add dependency on CONFIG_FIXED_PHY
+
+The DPAA2 DPMAC driver currently relies on fixed links, so it will fail
+to probe in unusual ways if CONFIG_FIXED_PHY is not enabled.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+Change-Id: Ibc53226a215ed85a2ba22c55b18595fb939e7418
+Reviewed-on: http://git.am.freescale.net:8181/37687
+Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
+Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+fsl-dpaa2: mac: Fix macro
+
+Remove macro ending backslash.
+
+Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
+Change-Id: Ib0c4a41eee8fbe4aa7c991fc7fdb87771d3bf594
+Reviewed-on: http://git.am.freescale.net:8181/37254
+Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
+Reviewed-by: Alexandru Marginean <Alexandru.Marginean@freescale.com>
+Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+fsl-dpaa2: mac: migrated remaining flibs for MC fw 8.0.0
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+[Stuart: split mac part out of original patch, updated subject]
+Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+staging: fsl-dpaa2: mac: Port to MC-0.7 Flibs
+
+Change-Id: Ief731e245bdc207f1bf8e7ff4dfdabb445d6010e
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+Reviewed-on: http://git.am.freescale.net:8181/39151
+Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
+Tested-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+staging: fsl-dpaa2: mac: Do programing of MSIs in devm_request_threaded_irq()
+
+With the new dprc_set_obj_irq() we can now program MSIS in the device
+in the callback invoked from devm_request_threaded_irq().
+Since this callback is invoked with interrupts disabled, we need to
+use an atomic portal, instead of the root DPRC's built-in portal
+which is non-atomic.
+
+Signed-off-by: Itai Katz <itai.katz@freescale.com>
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+[Stuart: split original patch up by component]
+Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
+
+fsl-dpaa2: mac: Fix driver probing
+
+The DPMAC probing function was broken in many ways. This patch adds
+the following fixes:
+ - Look up PHY nodes based on the phy-handle property of the respective
+   DPMAC node;
+ - Defer DPMAC device probing until the MDIO MUX driver probes first (we
+   depend on that for configuring the PHYs on PCIe riser cards on
+   LS2085A QDS boards.
+ - Add Kconfig dependencies on XGMAC_MDIO and MDIO_BUS_MUX_MMIOREG.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+
+fsl-dpaa2: mac: Fix interrupt handling
+
+The DPMAC has two interrupt events muxed on a single interrupt line.
+Both the PHY and the DPNI can initiate a link event.
+
+When the link event is initiated by the PHY (possibly as the effect of an
+earlier link change request initiated by a DPNI), we must make sure
+dpmac_set_link_state() is explicitly called in order for the event to be
+propagated (back) to the DPNI.
+
+Finally, DPMAC interrupt mask has to be explicitly specified before calling
+dpmac_set_irq_enabled().
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+
+fsl-dpaa2: mac: Fix print in case device is not initialized
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+
+fsl-dpaa2: mac: Fix error paths at probe
+
+Merge error condition checks. Add error codes to the early exit paths.
+Fix swapped goto labels.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+
+fsl-dpaa2: mac: Remove unused function prototype
+
+fixed_phy_register_2() was a leftover since we had to backport fixed PHY
+implementation on kernel v3.10.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+
+fsl-dpaa2/mac: Update dpmac binary interface to v3.2
+
+Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
+
+fsl-dpaa2: mac: Update Flib to MC 0.8.1
+
+In practice, this adds a counter for "good" egress frames.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Add counter for "good" egress frames
+
+Now available with the 0.8.1 Flibs.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Update dpmac_set_link_state() error checking
+
+As of 0.8.1 Flibs, dpmac_set_link_state() no longer returns what we'd
+consider spurious errors. This allows for cleaner error checking on
+DPMAC-side.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Remove __cold attribute
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Check DPMAC FLIB version
+
+Make sure we support the DPMAC version, otherwise abort probing
+early on and provide an error message.
+
+Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
+
+fsl-dpaa2: mac: Replace uintX_t with uX
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Fix crash on error path
+
+If the fixed-phy cannot be correctly registered, unregister_netdev()
+receives a non-NULL, yet invalid phydev. Force the phydev reference to
+NULL to avoid a crash on the probe routine's error path.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Remove TODOs comments from the code
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Fix ppx_eth_iface_mode order
+
+ppx_eth_iface_mode must be kept in sync with enum dpmac_eth_if, but some
+array values weren't in the right order.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Remove forward declarations of functions
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Remove ppx_{err,warn,info} macros
+
+Replace with their straighforward equivalents, their contexts being
+non-ambiguous.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Use non-atomic MC portal
+
+The DPMAC driver does not make MC calls from atomic contexts, so it is
+safe to request non-atomic MC portals.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: Replace "ppx" prefix with "dpaa2_mac"
+
+Use a similar naming convention as for the Ethernet driver,
+replacing "ppx" with "dpaa2_mac" as prefix for functions and
+structures.
+
+Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
+
+fsl-dpaa2: mac: Remove unnecessary blank line
+
+Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
+
+fsl-dpaa2: mac: Do not handle link change confirmation interrupt
+
+The need for that interrupt is more about debugging.
+
+Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
+
+fsl-dpaa2: mac: resolve compile issues on uprev to 4.5
+
+-interrupt info in mc struct changed upstream
+-fixed_phy_register() had new argument
+
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+---
+ MAINTAINERS                               |    6 +
+ drivers/staging/fsl-dpaa2/Kconfig         |    1 +
+ drivers/staging/fsl-dpaa2/Makefile        |    1 +
+ drivers/staging/fsl-dpaa2/mac/Kconfig     |   24 +
+ drivers/staging/fsl-dpaa2/mac/Makefile    |   10 +
+ drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h |  195 ++++++++
+ drivers/staging/fsl-dpaa2/mac/dpmac.c     |  422 ++++++++++++++++
+ drivers/staging/fsl-dpaa2/mac/dpmac.h     |  593 ++++++++++++++++++++++
+ drivers/staging/fsl-dpaa2/mac/mac.c       |  767 +++++++++++++++++++++++++++++
+ 9 files changed, 2019 insertions(+)
+ create mode 100644 drivers/staging/fsl-dpaa2/mac/Kconfig
+ create mode 100644 drivers/staging/fsl-dpaa2/mac/Makefile
+ create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
+ create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.c
+ create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.h
+ create mode 100644 drivers/staging/fsl-dpaa2/mac/mac.c
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4554,6 +4554,12 @@ S:      Maintained
+ F:    drivers/staging/fsl-mc/bus/mc-ioctl.h
+ F:    drivers/staging/fsl-mc/bus/mc-restool.c
++FREESCALE DPAA2 MAC/PHY INTERFACE DRIVER
++M:    Alex Marginean <Alexandru.Marginean@freescale.com>
++L:    linux-kernel@vger.kernel.org
++S:    Maintained
++F:    drivers/staging/fsl-dpaa2/mac/
++
+ FREEVXFS FILESYSTEM
+ M:    Christoph Hellwig <hch@infradead.org>
+ W:    ftp://ftp.openlinux.org/pub/people/hch/vxfs
+--- a/drivers/staging/fsl-dpaa2/Kconfig
++++ b/drivers/staging/fsl-dpaa2/Kconfig
+@@ -9,3 +9,4 @@ config FSL_DPAA2
+         Build drivers for Freescale DataPath Acceleration Architecture (DPAA2) family of SoCs.
+ # TODO move DPIO driver in-here?
+ source "drivers/staging/fsl-dpaa2/ethernet/Kconfig"
++source "drivers/staging/fsl-dpaa2/mac/Kconfig"
+--- a/drivers/staging/fsl-dpaa2/Makefile
++++ b/drivers/staging/fsl-dpaa2/Makefile
+@@ -3,3 +3,4 @@
+ #
+ obj-$(CONFIG_FSL_DPAA2_ETH)   += ethernet/
++obj-$(CONFIG_FSL_DPAA2_MAC)   += mac/
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/mac/Kconfig
+@@ -0,0 +1,24 @@
++config FSL_DPAA2_MAC
++      tristate "DPAA2 MAC / PHY interface"
++      depends on FSL_MC_BUS && FSL_DPAA2
++      select MDIO_BUS_MUX_MMIOREG
++      select FSL_XGMAC_MDIO
++      select FIXED_PHY
++      ---help---
++      Prototype driver for DPAA2 MAC / PHY interface object.
++      This driver works as a proxy between phylib including phy drivers and
++      the MC firmware.  It receives updates on link state changes from PHY
++      lib and forwards them to MC and receives interrupt from MC whenever
++      a request is made to change the link state.
++
++
++config FSL_DPAA2_MAC_NETDEVS
++      bool "Expose net interfaces for PHYs"
++      default n
++      depends on FSL_DPAA2_MAC
++      ---help---
++      Exposes macX net interfaces which allow direct control over MACs and
++      PHYs.
++      .
++      Leave disabled if unsure.
++
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/mac/Makefile
+@@ -0,0 +1,10 @@
++
++obj-$(CONFIG_FSL_DPAA2_MAC) += dpaa2-mac.o
++
++dpaa2-mac-objs := mac.o dpmac.o
++
++all:
++      make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
++
++clean:
++      make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
+@@ -0,0 +1,195 @@
++/* Copyright 2013-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 the above-listed copyright holders nor the
++ * names of any 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDERS OR CONTRIBUTORS 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_DPMAC_CMD_H
++#define _FSL_DPMAC_CMD_H
++
++/* DPMAC Version */
++#define DPMAC_VER_MAJOR                               3
++#define DPMAC_VER_MINOR                               2
++
++/* Command IDs */
++#define DPMAC_CMDID_CLOSE                     0x800
++#define DPMAC_CMDID_OPEN                      0x80c
++#define DPMAC_CMDID_CREATE                    0x90c
++#define DPMAC_CMDID_DESTROY                   0x900
++
++#define DPMAC_CMDID_GET_ATTR                  0x004
++#define DPMAC_CMDID_RESET                     0x005
++
++#define DPMAC_CMDID_SET_IRQ                   0x010
++#define DPMAC_CMDID_GET_IRQ                   0x011
++#define DPMAC_CMDID_SET_IRQ_ENABLE            0x012
++#define DPMAC_CMDID_GET_IRQ_ENABLE            0x013
++#define DPMAC_CMDID_SET_IRQ_MASK              0x014
++#define DPMAC_CMDID_GET_IRQ_MASK              0x015
++#define DPMAC_CMDID_GET_IRQ_STATUS            0x016
++#define DPMAC_CMDID_CLEAR_IRQ_STATUS          0x017
++
++#define DPMAC_CMDID_MDIO_READ                 0x0c0
++#define DPMAC_CMDID_MDIO_WRITE                        0x0c1
++#define DPMAC_CMDID_GET_LINK_CFG              0x0c2
++#define DPMAC_CMDID_SET_LINK_STATE            0x0c3
++#define DPMAC_CMDID_GET_COUNTER                       0x0c4
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_CREATE(cmd, cfg) \
++      MC_CMD_OP(cmd, 0, 0,  32, int,      cfg->mac_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_OPEN(cmd, dpmac_id) \
++      MC_CMD_OP(cmd, 0, 0,  32, int,      dpmac_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  irq_index);\
++      MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\
++      MC_CMD_OP(cmd, 1, 0,  64, uint64_t, irq_cfg->addr); \
++      MC_CMD_OP(cmd, 2, 0,  32, int,      irq_cfg->irq_num); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_GET_IRQ(cmd, irq_index) \
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_RSP_GET_IRQ(cmd, type, irq_cfg) \
++do { \
++      MC_RSP_OP(cmd, 0, 0,  32, uint32_t, irq_cfg->val); \
++      MC_RSP_OP(cmd, 1, 0,  64, uint64_t, irq_cfg->addr); \
++      MC_RSP_OP(cmd, 2, 0,  32, int,      irq_cfg->irq_num); \
++      MC_RSP_OP(cmd, 2, 32, 32, int,      type); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  en); \
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_RSP_GET_IRQ_ENABLE(cmd, en) \
++      MC_RSP_OP(cmd, 0, 0,  8,  uint8_t,  en)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  32, uint32_t, mask);\
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_GET_IRQ_MASK(cmd, irq_index) \
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_RSP_GET_IRQ_MASK(cmd, mask) \
++      MC_RSP_OP(cmd, 0, 0,  32, uint32_t, mask)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  32, uint32_t, status);\
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_RSP_GET_IRQ_STATUS(cmd, status) \
++      MC_RSP_OP(cmd, 0, 0,  32, uint32_t, status)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  32, uint32_t, status); \
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
++} while (0)
++
++/*                cmd, param, offset, width, type,    arg_name */
++#define DPMAC_RSP_GET_ATTRIBUTES(cmd, attr) \
++do { \
++      MC_RSP_OP(cmd, 0, 0,  32, int,                  attr->phy_id);\
++      MC_RSP_OP(cmd, 0, 32, 32, int,                  attr->id);\
++      MC_RSP_OP(cmd, 1, 0,  16, uint16_t,             attr->version.major);\
++      MC_RSP_OP(cmd, 1, 16, 16, uint16_t,             attr->version.minor);\
++      MC_RSP_OP(cmd, 1, 32,  8, enum dpmac_link_type, attr->link_type);\
++      MC_RSP_OP(cmd, 1, 40,  8, enum dpmac_eth_if,    attr->eth_if);\
++      MC_RSP_OP(cmd, 2, 0,  32, uint32_t,             attr->max_rate);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_MDIO_READ(cmd, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  cfg->phy_addr); \
++      MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  cfg->reg); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_RSP_MDIO_READ(cmd, data) \
++      MC_RSP_OP(cmd, 0, 16, 16, uint16_t, data)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_MDIO_WRITE(cmd, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  cfg->phy_addr); \
++      MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  cfg->reg); \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->data); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_RSP_GET_LINK_CFG(cmd, cfg) \
++do { \
++      MC_RSP_OP(cmd, 0, 0,  64, uint64_t, cfg->options); \
++      MC_RSP_OP(cmd, 1, 0,  32, uint32_t, cfg->rate); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_SET_LINK_STATE(cmd, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  64, uint64_t, cfg->options); \
++      MC_CMD_OP(cmd, 1, 0,  32, uint32_t, cfg->rate); \
++      MC_CMD_OP(cmd, 2, 0,  1,  int,      cfg->up); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_CMD_GET_COUNTER(cmd, type) \
++      MC_CMD_OP(cmd, 0, 0,  8, enum dpmac_counter, type)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPMAC_RSP_GET_COUNTER(cmd, counter) \
++      MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter)
++
++#endif /* _FSL_DPMAC_CMD_H */
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/mac/dpmac.c
+@@ -0,0 +1,422 @@
++/* Copyright 2013-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 the above-listed copyright holders nor the
++ * names of any 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDERS OR CONTRIBUTORS 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-mc/include/mc-sys.h"
++#include "../../fsl-mc/include/mc-cmd.h"
++#include "dpmac.h"
++#include "dpmac-cmd.h"
++
++int dpmac_open(struct fsl_mc_io *mc_io,
++             uint32_t cmd_flags,
++             int dpmac_id,
++             uint16_t *token)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN,
++                                        cmd_flags,
++                                        0);
++      DPMAC_CMD_OPEN(cmd, dpmac_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
++
++      return err;
++}
++
++int dpmac_close(struct fsl_mc_io *mc_io,
++              uint32_t cmd_flags,
++              uint16_t token)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpmac_create(struct fsl_mc_io *mc_io,
++               uint32_t cmd_flags,
++               const struct dpmac_cfg *cfg,
++               uint16_t *token)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE,
++                                        cmd_flags,
++                                        0);
++      DPMAC_CMD_CREATE(cmd, cfg);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
++
++      return 0;
++}
++
++int dpmac_destroy(struct fsl_mc_io *mc_io,
++                uint32_t cmd_flags,
++                uint16_t token)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpmac_set_irq(struct fsl_mc_io    *mc_io,
++                uint32_t              cmd_flags,
++                uint16_t              token,
++                uint8_t               irq_index,
++                struct dpmac_irq_cfg  *irq_cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_SET_IRQ(cmd, irq_index, irq_cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpmac_get_irq(struct fsl_mc_io    *mc_io,
++                uint32_t              cmd_flags,
++                uint16_t              token,
++                uint8_t               irq_index,
++                int                   *type,
++                struct dpmac_irq_cfg  *irq_cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_GET_IRQ(cmd, irq_index);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPMAC_RSP_GET_IRQ(cmd, *type, irq_cfg);
++
++      return 0;
++}
++
++int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       uint8_t irq_index,
++                       uint8_t en)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       uint8_t irq_index,
++                       uint8_t *en)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_ENABLE,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_GET_IRQ_ENABLE(cmd, irq_index);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPMAC_RSP_GET_IRQ_ENABLE(cmd, *en);
++
++      return 0;
++}
++
++int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
++                     uint32_t cmd_flags,
++                     uint16_t token,
++                     uint8_t irq_index,
++                     uint32_t mask)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_SET_IRQ_MASK(cmd, irq_index, mask);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
++                     uint32_t cmd_flags,
++                     uint16_t token,
++                     uint8_t irq_index,
++                     uint32_t *mask)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_MASK,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_GET_IRQ_MASK(cmd, irq_index);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPMAC_RSP_GET_IRQ_MASK(cmd, *mask);
++
++      return 0;
++}
++
++int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       uint8_t irq_index,
++                       uint32_t *status)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_STATUS,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_GET_IRQ_STATUS(cmd, irq_index, *status);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPMAC_RSP_GET_IRQ_STATUS(cmd, *status);
++
++      return 0;
++}
++
++int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
++                         uint32_t cmd_flags,
++                         uint16_t token,
++                         uint8_t irq_index,
++                         uint32_t status)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpmac_get_attributes(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       struct dpmac_attr *attr)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPMAC_RSP_GET_ATTRIBUTES(cmd, attr);
++
++      return 0;
++}
++
++int dpmac_mdio_read(struct fsl_mc_io *mc_io,
++                  uint32_t cmd_flags,
++                  uint16_t token,
++                  struct dpmac_mdio_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_READ,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_MDIO_READ(cmd, cfg);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPMAC_RSP_MDIO_READ(cmd, cfg->data);
++
++      return 0;
++}
++
++int dpmac_mdio_write(struct fsl_mc_io *mc_io,
++                   uint32_t cmd_flags,
++                   uint16_t token,
++                   struct dpmac_mdio_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_WRITE,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_MDIO_WRITE(cmd, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
++                     uint32_t cmd_flags,
++                     uint16_t token,
++                     struct dpmac_link_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err = 0;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      DPMAC_RSP_GET_LINK_CFG(cmd, cfg);
++
++      return 0;
++}
++
++int dpmac_set_link_state(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       struct dpmac_link_state *link_state)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_SET_LINK_STATE(cmd, link_state);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpmac_get_counter(struct fsl_mc_io *mc_io,
++                    uint32_t cmd_flags,
++                    uint16_t token,
++                    enum dpmac_counter type,
++                    uint64_t *counter)
++{
++      struct mc_command cmd = { 0 };
++      int err = 0;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER,
++                                        cmd_flags,
++                                        token);
++      DPMAC_CMD_GET_COUNTER(cmd, type);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      DPMAC_RSP_GET_COUNTER(cmd, *counter);
++
++      return 0;
++}
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/mac/dpmac.h
+@@ -0,0 +1,593 @@
++/* Copyright 2013-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 the above-listed copyright holders nor the
++ * names of any 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDERS OR CONTRIBUTORS 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_DPMAC_H
++#define __FSL_DPMAC_H
++
++/* Data Path MAC API
++ * Contains initialization APIs and runtime control APIs for DPMAC
++ */
++
++struct fsl_mc_io;
++
++/**
++ * dpmac_open() - Open a control session for the specified object.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @dpmac_id: DPMAC unique ID
++ * @token:    Returned token; use in subsequent API calls
++ *
++ * This function can be used to open a control session for an
++ * already created object; an object may have been declared in
++ * the DPL or by calling the dpmac_create function.
++ * This function returns a unique authentication token,
++ * associated with the specific object ID and the specific MC
++ * portal; this token must be used in all subsequent commands for
++ * this specific object
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_open(struct fsl_mc_io       *mc_io,
++             uint32_t         cmd_flags,
++             int                      dpmac_id,
++             uint16_t         *token);
++
++/**
++ * dpmac_close() - Close the control session of the object
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ *
++ * After this function is called, no further operations are
++ * allowed on the object without opening a new control session.
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_close(struct fsl_mc_io      *mc_io,
++              uint32_t                cmd_flags,
++              uint16_t                token);
++
++/**
++ * enum dpmac_link_type -  DPMAC link type
++ * @DPMAC_LINK_TYPE_NONE: No link
++ * @DPMAC_LINK_TYPE_FIXED: Link is fixed type
++ * @DPMAC_LINK_TYPE_PHY: Link by PHY ID
++ * @DPMAC_LINK_TYPE_BACKPLANE: Backplane link type
++ */
++enum dpmac_link_type {
++      DPMAC_LINK_TYPE_NONE,
++      DPMAC_LINK_TYPE_FIXED,
++      DPMAC_LINK_TYPE_PHY,
++      DPMAC_LINK_TYPE_BACKPLANE
++};
++
++/**
++ * enum dpmac_eth_if - DPMAC Ethrnet interface
++ * @DPMAC_ETH_IF_MII: MII interface
++ * @DPMAC_ETH_IF_RMII: RMII interface
++ * @DPMAC_ETH_IF_SMII: SMII interface
++ * @DPMAC_ETH_IF_GMII: GMII interface
++ * @DPMAC_ETH_IF_RGMII: RGMII interface
++ * @DPMAC_ETH_IF_SGMII: SGMII interface
++ * @DPMAC_ETH_IF_QSGMII: QSGMII interface
++ * @DPMAC_ETH_IF_XAUI: XAUI interface
++ * @DPMAC_ETH_IF_XFI: XFI interface
++ */
++enum dpmac_eth_if {
++      DPMAC_ETH_IF_MII,
++      DPMAC_ETH_IF_RMII,
++      DPMAC_ETH_IF_SMII,
++      DPMAC_ETH_IF_GMII,
++      DPMAC_ETH_IF_RGMII,
++      DPMAC_ETH_IF_SGMII,
++      DPMAC_ETH_IF_QSGMII,
++      DPMAC_ETH_IF_XAUI,
++      DPMAC_ETH_IF_XFI
++};
++
++/**
++ * struct dpmac_cfg - Structure representing DPMAC configuration
++ * @mac_id:   Represents the Hardware MAC ID; in case of multiple WRIOP,
++ *            the MAC IDs are continuous.
++ *            For example:  2 WRIOPs, 16 MACs in each:
++ *                            MAC IDs for the 1st WRIOP: 1-16,
++ *                            MAC IDs for the 2nd WRIOP: 17-32.
++ */
++struct dpmac_cfg {
++      int mac_id;
++};
++
++/**
++ * dpmac_create() - Create the DPMAC object.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @cfg:      Configuration structure
++ * @token:    Returned token; use in subsequent API calls
++ *
++ * Create the DPMAC object, allocate required resources and
++ * perform required initialization.
++ *
++ * The object can be created either by declaring it in the
++ * DPL file, or by calling this function.
++ * This function returns a unique authentication token,
++ * associated with the specific object ID and the specific MC
++ * portal; this token must be used in all subsequent calls to
++ * this specific object. For objects that are created using the
++ * DPL file, call dpmac_open function to get an authentication
++ * token first.
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_create(struct fsl_mc_io     *mc_io,
++               uint32_t               cmd_flags,
++               const struct dpmac_cfg *cfg,
++               uint16_t               *token);
++
++/**
++ * dpmac_destroy() - Destroy the DPMAC object and release all its resources.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ *
++ * Return:    '0' on Success; error code otherwise.
++ */
++int dpmac_destroy(struct fsl_mc_io    *mc_io,
++                uint32_t              cmd_flags,
++                uint16_t              token);
++
++/**
++ * DPMAC IRQ Index and Events
++ */
++
++/**
++ * IRQ index
++ */
++#define DPMAC_IRQ_INDEX                                               0
++/**
++ * IRQ event - indicates a change in link state
++ */
++#define DPMAC_IRQ_EVENT_LINK_CFG_REQ          0x00000001
++/**
++ * IRQ event - Indicates that the link state changed
++ */
++#define DPMAC_IRQ_EVENT_LINK_CHANGED          0x00000002
++
++/**
++ * struct dpmac_irq_cfg - IRQ configuration
++ * @addr:     Address that must be written to signal a message-based interrupt
++ * @val:      Value to write into irq_addr address
++ * @irq_num: A user defined number associated with this IRQ
++ */
++struct dpmac_irq_cfg {
++           uint64_t           addr;
++           uint32_t           val;
++           int                irq_num;
++};
++
++/**
++ * dpmac_set_irq() - Set IRQ information for the DPMAC to trigger an interrupt.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @irq_index:        Identifies the interrupt index to configure
++ * @irq_cfg:  IRQ configuration
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_set_irq(struct fsl_mc_io    *mc_io,
++                uint32_t              cmd_flags,
++                uint16_t              token,
++                uint8_t               irq_index,
++                struct dpmac_irq_cfg  *irq_cfg);
++
++/**
++ * dpmac_get_irq() - Get IRQ information from the DPMAC.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @irq_index:        The interrupt index to configure
++ * @type:     Interrupt type: 0 represents message interrupt
++ *            type (both irq_addr and irq_val are valid)
++ * @irq_cfg:  IRQ attributes
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_get_irq(struct fsl_mc_io    *mc_io,
++                uint32_t              cmd_flags,
++                uint16_t              token,
++                uint8_t               irq_index,
++                int                   *type,
++                struct dpmac_irq_cfg  *irq_cfg);
++
++/**
++ * dpmac_set_irq_enable() - Set overall interrupt state.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @irq_index:        The interrupt index to configure
++ * @en:       Interrupt state - enable = 1, disable = 0
++ *
++ * Allows GPP software to control when interrupts are generated.
++ * Each interrupt can have up to 32 causes.  The enable/disable control's the
++ * overall interrupt state. if the interrupt is disabled no causes will cause
++ * an interrupt.
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_set_irq_enable(struct fsl_mc_io     *mc_io,
++                       uint32_t               cmd_flags,
++                       uint16_t               token,
++                       uint8_t                irq_index,
++                       uint8_t                en);
++
++/**
++ * dpmac_get_irq_enable() - Get overall interrupt state
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @irq_index:        The interrupt index to configure
++ * @en:               Returned interrupt state - enable = 1, disable = 0
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_get_irq_enable(struct fsl_mc_io     *mc_io,
++                       uint32_t               cmd_flags,
++                       uint16_t               token,
++                       uint8_t                irq_index,
++                       uint8_t                *en);
++
++/**
++ * dpmac_set_irq_mask() - Set interrupt mask.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @irq_index:        The interrupt index to configure
++ * @mask:     Event mask to trigger interrupt;
++ *                    each bit:
++ *                            0 = ignore event
++ *                            1 = consider event for asserting IRQ
++ *
++ * Every interrupt can have up to 32 causes and the interrupt model supports
++ * masking/unmasking each cause independently
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
++                     uint32_t cmd_flags,
++                     uint16_t         token,
++                     uint8_t          irq_index,
++                     uint32_t         mask);
++
++/**
++ * dpmac_get_irq_mask() - Get interrupt mask.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @irq_index:        The interrupt index to configure
++ * @mask:     Returned event mask to trigger interrupt
++ *
++ * Every interrupt can have up to 32 causes and the interrupt model supports
++ * masking/unmasking each cause independently
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
++                     uint32_t cmd_flags,
++                     uint16_t         token,
++                     uint8_t          irq_index,
++                     uint32_t         *mask);
++
++/**
++ * dpmac_get_irq_status() - Get the current status of any pending interrupts.
++ *
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @irq_index:        The interrupt index to configure
++ * @status:   Returned interrupts status - one bit per cause:
++ *                    0 = no interrupt pending
++ *                    1 = interrupt pending
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_get_irq_status(struct fsl_mc_io     *mc_io,
++                       uint32_t               cmd_flags,
++                       uint16_t               token,
++                       uint8_t                irq_index,
++                       uint32_t               *status);
++
++/**
++ * dpmac_clear_irq_status() - Clear a pending interrupt's status
++ *
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @irq_index:        The interrupt index to configure
++ * @status:   Bits to clear (W1C) - one bit per cause:
++ *                                    0 = don't change
++ *                                    1 = clear status bit
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_clear_irq_status(struct fsl_mc_io   *mc_io,
++                         uint32_t             cmd_flags,
++                         uint16_t             token,
++                         uint8_t              irq_index,
++                         uint32_t             status);
++
++/**
++ * struct dpmac_attr - Structure representing DPMAC attributes
++ * @id:               DPMAC object ID
++ * @phy_id:   PHY ID
++ * @link_type: link type
++ * @eth_if: Ethernet interface
++ * @max_rate: Maximum supported rate - in Mbps
++ * @version:  DPMAC version
++ */
++struct dpmac_attr {
++      int                     id;
++      int                     phy_id;
++      enum dpmac_link_type    link_type;
++      enum dpmac_eth_if       eth_if;
++      uint32_t                max_rate;
++      /**
++       * struct version - Structure representing DPMAC version
++       * @major:      DPMAC major version
++       * @minor:      DPMAC minor version
++       */
++      struct {
++              uint16_t major;
++              uint16_t minor;
++      } version;
++};
++
++/**
++ * dpmac_get_attributes - Retrieve DPMAC attributes.
++ *
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @attr:     Returned object's attributes
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_get_attributes(struct fsl_mc_io     *mc_io,
++                       uint32_t               cmd_flags,
++                       uint16_t               token,
++                       struct dpmac_attr      *attr);
++
++/**
++ * struct dpmac_mdio_cfg - DPMAC MDIO read/write parameters
++ * @phy_addr: MDIO device address
++ * @reg: Address of the register within the Clause 45 PHY device from which data
++ *    is to be read
++ * @data: Data read/write from/to MDIO
++ */
++struct dpmac_mdio_cfg {
++      uint8_t         phy_addr;
++      uint8_t         reg;
++      uint16_t        data;
++};
++
++/**
++ * dpmac_mdio_read() - Perform MDIO read transaction
++ * @mc_io:    Pointer to opaque I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @cfg:      Structure with MDIO transaction parameters
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_mdio_read(struct fsl_mc_io          *mc_io,
++                  uint32_t                    cmd_flags,
++                  uint16_t                    token,
++                  struct dpmac_mdio_cfg       *cfg);
++
++/**
++ * dpmac_mdio_write() - Perform MDIO write transaction
++ * @mc_io:    Pointer to opaque I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @cfg:      Structure with MDIO transaction parameters
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_mdio_write(struct fsl_mc_io         *mc_io,
++                   uint32_t                   cmd_flags,
++                   uint16_t                   token,
++                   struct dpmac_mdio_cfg      *cfg);
++
++/**
++ * DPMAC link configuration/state options
++ */
++
++/**
++ * Enable auto-negotiation
++ */
++#define DPMAC_LINK_OPT_AUTONEG                0x0000000000000001ULL
++/**
++ * Enable half-duplex mode
++ */
++#define DPMAC_LINK_OPT_HALF_DUPLEX    0x0000000000000002ULL
++/**
++ * Enable pause frames
++ */
++#define DPMAC_LINK_OPT_PAUSE          0x0000000000000004ULL
++/**
++ * Enable a-symmetric pause frames
++ */
++#define DPMAC_LINK_OPT_ASYM_PAUSE     0x0000000000000008ULL
++
++/**
++ * struct dpmac_link_cfg - Structure representing DPMAC link configuration
++ * @rate: Link's rate - in Mbps
++ * @options: Enable/Disable DPMAC link cfg features (bitmap)
++ */
++struct dpmac_link_cfg {
++      uint32_t rate;
++      uint64_t options;
++};
++
++/**
++ * dpmac_get_link_cfg() - Get Ethernet link configuration
++ * @mc_io:    Pointer to opaque I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @cfg:      Returned structure with the link configuration
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_get_link_cfg(struct fsl_mc_io       *mc_io,
++                     uint32_t         cmd_flags,
++                     uint16_t         token,
++                     struct dpmac_link_cfg    *cfg);
++
++/**
++ * struct dpmac_link_state - DPMAC link configuration request
++ * @rate: Rate in Mbps
++ * @options: Enable/Disable DPMAC link cfg features (bitmap)
++ * @up: Link state
++ */
++struct dpmac_link_state {
++      uint32_t        rate;
++      uint64_t        options;
++      int             up;
++};
++
++/**
++ * dpmac_set_link_state() - Set the Ethernet link status
++ * @mc_io:    Pointer to opaque I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @link_state:       Link state configuration
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpmac_set_link_state(struct fsl_mc_io             *mc_io,
++                       uint32_t                       cmd_flags,
++                       uint16_t                       token,
++                       struct dpmac_link_state        *link_state);
++
++/**
++ * enum dpmac_counter - DPMAC counter types
++ * @DPMAC_CNT_ING_FRAME_64: counts 64-bytes frames, good or bad.
++ * @DPMAC_CNT_ING_FRAME_127: counts 65- to 127-bytes frames, good or bad.
++ * @DPMAC_CNT_ING_FRAME_255: counts 128- to 255-bytes frames, good or bad.
++ * @DPMAC_CNT_ING_FRAME_511: counts 256- to 511-bytes frames, good or bad.
++ * @DPMAC_CNT_ING_FRAME_1023: counts 512- to 1023-bytes frames, good or bad.
++ * @DPMAC_CNT_ING_FRAME_1518: counts 1024- to 1518-bytes frames, good or bad.
++ * @DPMAC_CNT_ING_FRAME_1519_MAX: counts 1519-bytes frames and larger
++ *                              (up to max frame length specified),
++ *                              good or bad.
++ * @DPMAC_CNT_ING_FRAG: counts frames which are shorter than 64 bytes received
++ *                    with a wrong CRC
++ * @DPMAC_CNT_ING_JABBER: counts frames longer than the maximum frame length
++ *                      specified, with a bad frame check sequence.
++ * @DPMAC_CNT_ING_FRAME_DISCARD: counts dropped frames due to internal errors.
++ *                             Occurs when a receive FIFO overflows.
++ *                             Includes also frames truncated as a result of
++ *                             the receive FIFO overflow.
++ * @DPMAC_CNT_ING_ALIGN_ERR: counts frames with an alignment error
++ *                         (optional used for wrong SFD).
++ * @DPMAC_CNT_EGR_UNDERSIZED: counts frames transmitted that was less than 64
++ *                          bytes long with a good CRC.
++ * @DPMAC_CNT_ING_OVERSIZED: counts frames longer than the maximum frame length
++ *                         specified, with a good frame check sequence.
++ * @DPMAC_CNT_ING_VALID_PAUSE_FRAME: counts valid pause frames (regular and PFC)
++ * @DPMAC_CNT_EGR_VALID_PAUSE_FRAME: counts valid pause frames transmitted
++ *                                 (regular and PFC).
++ * @DPMAC_CNT_ING_BYTE: counts bytes received except preamble for all valid
++ *                    frames and valid pause frames.
++ * @DPMAC_CNT_ING_MCAST_FRAME: counts received multicast frames.
++ * @DPMAC_CNT_ING_BCAST_FRAME: counts received broadcast frames.
++ * @DPMAC_CNT_ING_ALL_FRAME: counts each good or bad frames received.
++ * @DPMAC_CNT_ING_UCAST_FRAME: counts received unicast frames.
++ * @DPMAC_CNT_ING_ERR_FRAME: counts frames received with an error
++ *                         (except for undersized/fragment frame).
++ * @DPMAC_CNT_EGR_BYTE: counts bytes transmitted except preamble for all valid
++ *                    frames and valid pause frames transmitted.
++ * @DPMAC_CNT_EGR_MCAST_FRAME: counts transmitted multicast frames.
++ * @DPMAC_CNT_EGR_BCAST_FRAME: counts transmitted broadcast frames.
++ * @DPMAC_CNT_EGR_UCAST_FRAME: counts transmitted unicast frames.
++ * @DPMAC_CNT_EGR_ERR_FRAME: counts frames transmitted with an error.
++ * @DPMAC_CNT_ING_GOOD_FRAME: counts frames received without error, including
++ *                          pause frames.
++ * @DPMAC_CNT_ENG_GOOD_FRAME: counts frames transmitted without error, including
++ *                          pause frames.
++ */
++enum dpmac_counter {
++      DPMAC_CNT_ING_FRAME_64,
++      DPMAC_CNT_ING_FRAME_127,
++      DPMAC_CNT_ING_FRAME_255,
++      DPMAC_CNT_ING_FRAME_511,
++      DPMAC_CNT_ING_FRAME_1023,
++      DPMAC_CNT_ING_FRAME_1518,
++      DPMAC_CNT_ING_FRAME_1519_MAX,
++      DPMAC_CNT_ING_FRAG,
++      DPMAC_CNT_ING_JABBER,
++      DPMAC_CNT_ING_FRAME_DISCARD,
++      DPMAC_CNT_ING_ALIGN_ERR,
++      DPMAC_CNT_EGR_UNDERSIZED,
++      DPMAC_CNT_ING_OVERSIZED,
++      DPMAC_CNT_ING_VALID_PAUSE_FRAME,
++      DPMAC_CNT_EGR_VALID_PAUSE_FRAME,
++      DPMAC_CNT_ING_BYTE,
++      DPMAC_CNT_ING_MCAST_FRAME,
++      DPMAC_CNT_ING_BCAST_FRAME,
++      DPMAC_CNT_ING_ALL_FRAME,
++      DPMAC_CNT_ING_UCAST_FRAME,
++      DPMAC_CNT_ING_ERR_FRAME,
++      DPMAC_CNT_EGR_BYTE,
++      DPMAC_CNT_EGR_MCAST_FRAME,
++      DPMAC_CNT_EGR_BCAST_FRAME,
++      DPMAC_CNT_EGR_UCAST_FRAME,
++      DPMAC_CNT_EGR_ERR_FRAME,
++      DPMAC_CNT_ING_GOOD_FRAME,
++      DPMAC_CNT_ENG_GOOD_FRAME
++};
++
++/**
++ * dpmac_get_counter() - Read a specific DPMAC counter
++ * @mc_io:    Pointer to opaque I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPMAC object
++ * @type:     The requested counter
++ * @counter:  Returned counter value
++ *
++ * Return:    The requested counter; '0' otherwise.
++ */
++int dpmac_get_counter(struct fsl_mc_io                *mc_io,
++                    uint32_t                  cmd_flags,
++                    uint16_t                  token,
++                    enum dpmac_counter         type,
++                    uint64_t                  *counter);
++
++#endif /* __FSL_DPMAC_H */
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/mac/mac.c
+@@ -0,0 +1,767 @@
++/* Copyright 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/module.h>
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/if_vlan.h>
++
++#include <uapi/linux/if_bridge.h>
++#include <net/netlink.h>
++
++#include <linux/of.h>
++#include <linux/of_mdio.h>
++#include <linux/of_net.h>
++#include <linux/phy.h>
++#include <linux/phy_fixed.h>
++#include <linux/interrupt.h>
++#include <linux/msi.h>
++
++#include "../../fsl-mc/include/mc.h"
++#include "../../fsl-mc/include/mc-sys.h"
++
++#include "dpmac.h"
++#include "dpmac-cmd.h"
++
++#define DPAA2_SUPPORTED_DPMAC_VERSION 3
++
++struct dpaa2_mac_priv {
++      struct net_device               *netdev;
++      struct fsl_mc_device            *mc_dev;
++      struct dpmac_attr               attr;
++      struct dpmac_link_state         old_state;
++};
++
++/* TODO: fix the 10G modes, mapping can't be right:
++ *  XGMII is paralel
++ *  XAUI is serial, using 8b/10b encoding
++ *  XFI is also serial but using 64b/66b encoding
++ * they can't all map to XGMII...
++ *
++ * This must be kept in sync with enum dpmac_eth_if.
++ */
++static phy_interface_t dpaa2_mac_iface_mode[] =  {
++      /* DPMAC_ETH_IF_MII */
++      PHY_INTERFACE_MODE_MII,
++      /* DPMAC_ETH_IF_RMII */
++      PHY_INTERFACE_MODE_RMII,
++      /* DPMAC_ETH_IF_SMII */
++      PHY_INTERFACE_MODE_SMII,
++      /* DPMAC_ETH_IF_GMII */
++      PHY_INTERFACE_MODE_GMII,
++      /* DPMAC_ETH_IF_RGMII */
++      PHY_INTERFACE_MODE_RGMII,
++      /* DPMAC_ETH_IF_SGMII */
++      PHY_INTERFACE_MODE_SGMII,
++      /* DPMAC_ETH_IF_QSGMII */
++      PHY_INTERFACE_MODE_QSGMII,
++      /* DPMAC_ETH_IF_XAUI */
++      PHY_INTERFACE_MODE_XGMII,
++      /* DPMAC_ETH_IF_XFI */
++      PHY_INTERFACE_MODE_XGMII,
++};
++
++static void dpaa2_mac_link_changed(struct net_device *netdev)
++{
++      struct phy_device       *phydev;
++      struct dpmac_link_state state = { 0 };
++      struct dpaa2_mac_priv   *priv = netdev_priv(netdev);
++      int                     err;
++
++      /* the PHY just notified us of link state change */
++      phydev = netdev->phydev;
++
++      state.up = !!phydev->link;
++      if (phydev->link) {
++              state.rate = phydev->speed;
++
++              if (!phydev->duplex)
++                      state.options |= DPMAC_LINK_OPT_HALF_DUPLEX;
++              if (phydev->autoneg)
++                      state.options |= DPMAC_LINK_OPT_AUTONEG;
++
++              netif_carrier_on(netdev);
++      } else {
++              netif_carrier_off(netdev);
++      }
++
++      if (priv->old_state.up != state.up ||
++          priv->old_state.rate != state.rate ||
++          priv->old_state.options != state.options) {
++              priv->old_state = state;
++              phy_print_status(phydev);
++      }
++
++      /* We must call into the MC firmware at all times, because we don't know
++       * when and whether a potential DPNI may have read the link state.
++       */
++      err = dpmac_set_link_state(priv->mc_dev->mc_io, 0,
++                                 priv->mc_dev->mc_handle, &state);
++      if (unlikely(err))
++              dev_err(&priv->mc_dev->dev, "dpmac_set_link_state: %d\n", err);
++}
++
++/* IRQ bits that we handle */
++static const u32 dpmac_irq_mask =  DPMAC_IRQ_EVENT_LINK_CFG_REQ;
++
++#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
++static netdev_tx_t dpaa2_mac_drop_frame(struct sk_buff *skb,
++                                      struct net_device *dev)
++{
++      /* we don't support I/O for now, drop the frame */
++      dev_kfree_skb_any(skb);
++      return NETDEV_TX_OK;
++}
++
++static int dpaa2_mac_open(struct net_device *netdev)
++{
++      /* start PHY state machine */
++      phy_start(netdev->phydev);
++
++      return 0;
++}
++
++static int dpaa2_mac_stop(struct net_device *netdev)
++{
++      if (!netdev->phydev)
++              goto done;
++
++      /* stop PHY state machine */
++      phy_stop(netdev->phydev);
++
++      /* signal link down to firmware */
++      netdev->phydev->link = 0;
++      dpaa2_mac_link_changed(netdev);
++
++done:
++      return 0;
++}
++
++static int dpaa2_mac_get_settings(struct net_device *netdev,
++                                struct ethtool_cmd *cmd)
++{
++      return phy_ethtool_gset(netdev->phydev, cmd);
++}
++
++static int dpaa2_mac_set_settings(struct net_device *netdev,
++                                struct ethtool_cmd *cmd)
++{
++      return phy_ethtool_sset(netdev->phydev, cmd);
++}
++
++static struct rtnl_link_stats64
++*dpaa2_mac_get_stats(struct net_device *netdev,
++                   struct rtnl_link_stats64 *storage)
++{
++      struct dpaa2_mac_priv   *priv = netdev_priv(netdev);
++      u64                     tmp;
++      int                     err;
++
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_EGR_MCAST_FRAME,
++                              &storage->tx_packets);
++      if (err)
++              goto error;
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_EGR_BCAST_FRAME, &tmp);
++      if (err)
++              goto error;
++      storage->tx_packets += tmp;
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_EGR_UCAST_FRAME, &tmp);
++      if (err)
++              goto error;
++      storage->tx_packets += tmp;
++
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_EGR_UNDERSIZED, &storage->tx_dropped);
++      if (err)
++              goto error;
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_EGR_BYTE, &storage->tx_bytes);
++      if (err)
++              goto error;
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_EGR_ERR_FRAME, &storage->tx_errors);
++      if (err)
++              goto error;
++
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_ING_ALL_FRAME, &storage->rx_packets);
++      if (err)
++              goto error;
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_ING_MCAST_FRAME, &storage->multicast);
++      if (err)
++              goto error;
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_ING_FRAME_DISCARD,
++                              &storage->rx_dropped);
++      if (err)
++              goto error;
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_ING_ALIGN_ERR, &storage->rx_errors);
++      if (err)
++              goto error;
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_ING_OVERSIZED, &tmp);
++      if (err)
++              goto error;
++      storage->rx_errors += tmp;
++      err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
++                              DPMAC_CNT_ING_BYTE, &storage->rx_bytes);
++      if (err)
++              goto error;
++
++      return storage;
++
++error:
++      netdev_err(netdev, "dpmac_get_counter err %d\n", err);
++      return storage;
++}
++
++static struct {
++      enum dpmac_counter id;
++      char name[ETH_GSTRING_LEN];
++} dpaa2_mac_counters[] =  {
++      {DPMAC_CNT_ING_ALL_FRAME,               "rx all frames"},
++      {DPMAC_CNT_ING_GOOD_FRAME,              "rx frames ok"},
++      {DPMAC_CNT_ING_ERR_FRAME,               "rx frame errors"},
++      {DPMAC_CNT_ING_FRAME_DISCARD,           "rx frame discards"},
++      {DPMAC_CNT_ING_UCAST_FRAME,             "rx u-cast"},
++      {DPMAC_CNT_ING_BCAST_FRAME,             "rx b-cast"},
++      {DPMAC_CNT_ING_MCAST_FRAME,             "rx m-cast"},
++      {DPMAC_CNT_ING_FRAME_64,                "rx 64 bytes"},
++      {DPMAC_CNT_ING_FRAME_127,               "rx 65-127 bytes"},
++      {DPMAC_CNT_ING_FRAME_255,               "rx 128-255 bytes"},
++      {DPMAC_CNT_ING_FRAME_511,               "rx 256-511 bytes"},
++      {DPMAC_CNT_ING_FRAME_1023,              "rx 512-1023 bytes"},
++      {DPMAC_CNT_ING_FRAME_1518,              "rx 1024-1518 bytes"},
++      {DPMAC_CNT_ING_FRAME_1519_MAX,          "rx 1519-max bytes"},
++      {DPMAC_CNT_ING_FRAG,                    "rx frags"},
++      {DPMAC_CNT_ING_JABBER,                  "rx jabber"},
++      {DPMAC_CNT_ING_ALIGN_ERR,               "rx align errors"},
++      {DPMAC_CNT_ING_OVERSIZED,               "rx oversized"},
++      {DPMAC_CNT_ING_VALID_PAUSE_FRAME,       "rx pause"},
++      {DPMAC_CNT_ING_BYTE,                    "rx bytes"},
++      {DPMAC_CNT_ENG_GOOD_FRAME,              "tx frames ok"},
++      {DPMAC_CNT_EGR_UCAST_FRAME,             "tx u-cast"},
++      {DPMAC_CNT_EGR_MCAST_FRAME,             "tx m-cast"},
++      {DPMAC_CNT_EGR_BCAST_FRAME,             "tx b-cast"},
++      {DPMAC_CNT_EGR_ERR_FRAME,               "tx frame errors"},
++      {DPMAC_CNT_EGR_UNDERSIZED,              "tx undersized"},
++      {DPMAC_CNT_EGR_VALID_PAUSE_FRAME,       "tx b-pause"},
++      {DPMAC_CNT_EGR_BYTE,                    "tx bytes"},
++
++};
++
++static void dpaa2_mac_get_strings(struct net_device *netdev,
++                                u32 stringset, u8 *data)
++{
++      int i;
++
++      switch (stringset) {
++      case ETH_SS_STATS:
++              for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++)
++                      memcpy(data + i * ETH_GSTRING_LEN,
++                             dpaa2_mac_counters[i].name,
++                             ETH_GSTRING_LEN);
++              break;
++      }
++}
++
++static void dpaa2_mac_get_ethtool_stats(struct net_device *netdev,
++                                      struct ethtool_stats *stats,
++                                      u64 *data)
++{
++      struct dpaa2_mac_priv   *priv = netdev_priv(netdev);
++      int                     i;
++      int                     err;
++
++      for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++) {
++              err = dpmac_get_counter(priv->mc_dev->mc_io,
++                                      0,
++                                      priv->mc_dev->mc_handle,
++                                      dpaa2_mac_counters[i].id, &data[i]);
++              if (err)
++                      netdev_err(netdev, "dpmac_get_counter[%s] err %d\n",
++                                 dpaa2_mac_counters[i].name, err);
++      }
++}
++
++static int dpaa2_mac_get_sset_count(struct net_device *dev, int sset)
++{
++      switch (sset) {
++      case ETH_SS_STATS:
++              return ARRAY_SIZE(dpaa2_mac_counters);
++      default:
++              return -EOPNOTSUPP;
++      }
++}
++
++static const struct net_device_ops dpaa2_mac_ndo_ops = {
++      .ndo_start_xmit         = &dpaa2_mac_drop_frame,
++      .ndo_open               = &dpaa2_mac_open,
++      .ndo_stop               = &dpaa2_mac_stop,
++      .ndo_get_stats64        = &dpaa2_mac_get_stats,
++};
++
++static const struct ethtool_ops dpaa2_mac_ethtool_ops = {
++      .get_settings           = &dpaa2_mac_get_settings,
++      .set_settings           = &dpaa2_mac_set_settings,
++      .get_strings            = &dpaa2_mac_get_strings,
++      .get_ethtool_stats      = &dpaa2_mac_get_ethtool_stats,
++      .get_sset_count         = &dpaa2_mac_get_sset_count,
++};
++#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
++
++static int configure_link(struct dpaa2_mac_priv *priv,
++                        struct dpmac_link_cfg *cfg)
++{
++      struct phy_device *phydev = priv->netdev->phydev;
++
++      if (!phydev) {
++              dev_warn(priv->netdev->dev.parent,
++                       "asked to change PHY settings but PHY ref is NULL, ignoring\n");
++              return 0;
++      }
++
++      phydev->speed = cfg->rate;
++      phydev->duplex  = !!(cfg->options & DPMAC_LINK_OPT_HALF_DUPLEX);
++
++      if (cfg->options & DPMAC_LINK_OPT_AUTONEG) {
++              phydev->autoneg = 1;
++              phydev->advertising |= ADVERTISED_Autoneg;
++      } else {
++              phydev->autoneg = 0;
++              phydev->advertising &= ~ADVERTISED_Autoneg;
++      }
++
++      phy_start_aneg(phydev);
++
++      return 0;
++}
++
++static irqreturn_t dpaa2_mac_irq_handler(int irq_num, void *arg)
++{
++      struct device *dev = (struct device *)arg;
++      struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
++      struct dpaa2_mac_priv *priv = dev_get_drvdata(dev);
++      struct dpmac_link_cfg link_cfg;
++      u8 irq_index = DPMAC_IRQ_INDEX;
++      u32 status, clear = 0;
++      int err;
++
++      if (mc_dev->irqs[0]->msi_desc->irq != irq_num) {
++              dev_err(dev, "received unexpected interrupt %d!\n", irq_num);
++              goto err;
++      }
++
++      err = dpmac_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
++                                 irq_index, &status);
++      if (err) {
++              dev_err(dev, "dpmac_get_irq_status err %d\n", err);
++              clear = ~0x0u;
++              goto out;
++      }
++
++      /* DPNI-initiated link configuration; 'ifconfig up' also calls this */
++      if (status & DPMAC_IRQ_EVENT_LINK_CFG_REQ) {
++              dev_dbg(dev, "DPMAC IRQ %d - LINK_CFG_REQ\n", irq_num);
++              clear |= DPMAC_IRQ_EVENT_LINK_CFG_REQ;
++
++              err = dpmac_get_link_cfg(mc_dev->mc_io, 0, mc_dev->mc_handle,
++                                       &link_cfg);
++              if (err) {
++                      dev_err(dev, "dpmac_get_link_cfg err %d\n", err);
++                      goto out;
++              }
++
++              err = configure_link(priv, &link_cfg);
++              if (err) {
++                      dev_err(dev, "cannot configure link\n");
++                      goto out;
++              }
++      }
++
++out:
++      err = dpmac_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
++                                   irq_index, clear);
++      if (err < 0)
++              dev_err(&mc_dev->dev, "dpmac_clear_irq_status() err %d\n", err);
++
++      return IRQ_HANDLED;
++
++err:
++      dev_warn(dev, "DPMAC IRQ %d was not handled!\n", irq_num);
++      return IRQ_NONE;
++}
++
++static int setup_irqs(struct fsl_mc_device *mc_dev)
++{
++      int err;
++
++      err = fsl_mc_allocate_irqs(mc_dev);
++      if (err) {
++              dev_err(&mc_dev->dev, "fsl_mc_allocate_irqs err %d\n", err);
++              return err;
++      }
++
++      err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
++                               DPMAC_IRQ_INDEX, dpmac_irq_mask);
++      if (err < 0) {
++              dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
++              goto free_irq;
++      }
++      err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
++                                 DPMAC_IRQ_INDEX, 0);
++      if (err) {
++              dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
++              goto free_irq;
++      }
++
++      err = devm_request_threaded_irq(&mc_dev->dev,
++                                      mc_dev->irqs[0]->msi_desc->irq,
++                                      NULL, &dpaa2_mac_irq_handler,
++                                      IRQF_NO_SUSPEND | IRQF_ONESHOT,
++                                      dev_name(&mc_dev->dev), &mc_dev->dev);
++      if (err) {
++              dev_err(&mc_dev->dev, "devm_request_threaded_irq err %d\n",
++                      err);
++              goto free_irq;
++      }
++
++      err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
++                               DPMAC_IRQ_INDEX, dpmac_irq_mask);
++      if (err < 0) {
++              dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
++              goto free_irq;
++      }
++      err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
++                                 DPMAC_IRQ_INDEX, 1);
++      if (err) {
++              dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
++              goto unregister_irq;
++      }
++
++      return 0;
++
++unregister_irq:
++      devm_free_irq(&mc_dev->dev, mc_dev->irqs[0]->msi_desc->irq, &mc_dev->dev);
++free_irq:
++      fsl_mc_free_irqs(mc_dev);
++
++      return err;
++}
++
++static void teardown_irqs(struct fsl_mc_device *mc_dev)
++{
++      int err;
++
++      err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
++                               DPMAC_IRQ_INDEX, dpmac_irq_mask);
++      if (err < 0)
++              dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
++
++      err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
++                                 DPMAC_IRQ_INDEX, 0);
++      if (err < 0)
++              dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
++
++      devm_free_irq(&mc_dev->dev, mc_dev->irqs[0]->msi_desc->irq, &mc_dev->dev);
++      fsl_mc_free_irqs(mc_dev);
++}
++
++static struct device_node *lookup_node(struct device *dev, int dpmac_id)
++{
++      struct device_node *dpmacs, *dpmac = NULL;
++      struct device_node *mc_node = dev->of_node;
++      const void *id;
++      int lenp;
++      int dpmac_id_be32 = cpu_to_be32(dpmac_id);
++
++      dpmacs = of_find_node_by_name(mc_node, "dpmacs");
++      if (!dpmacs) {
++              dev_err(dev, "No dpmacs subnode in device-tree\n");
++              return NULL;
++      }
++
++      while ((dpmac = of_get_next_child(dpmacs, dpmac))) {
++              id = of_get_property(dpmac, "reg", &lenp);
++              if (!id || lenp != sizeof(int)) {
++                      dev_warn(dev, "Unsuitable reg property in dpmac node\n");
++                      continue;
++              }
++              if (*(int *)id == dpmac_id_be32)
++                      return dpmac;
++      }
++
++      return NULL;
++}
++
++static int check_dpmac_version(struct dpaa2_mac_priv *priv)
++{
++      struct device *dev = &priv->mc_dev->dev;
++      int mc_version = priv->attr.version.major;
++
++      /* Check that the FLIB-defined version matches the one reported by MC */
++      if (mc_version != DPMAC_VER_MAJOR) {
++              dev_err(dev, "DPMAC FLIB version mismatch: MC says %d, we have %d\n",
++                      mc_version, DPMAC_VER_MAJOR);
++              return -EINVAL;
++      }
++
++      /* ... and that we actually support it */
++      if (mc_version < DPAA2_SUPPORTED_DPMAC_VERSION) {
++              dev_err(dev, "Unsupported DPMAC FLIB version (%d)\n",
++                      mc_version);
++              return -EINVAL;
++      }
++
++      dev_dbg(dev, "Using DPMAC FLIB version %d\n", mc_version);
++
++      return 0;
++}
++
++static int dpaa2_mac_probe(struct fsl_mc_device *mc_dev)
++{
++      struct device           *dev;
++      struct dpaa2_mac_priv   *priv = NULL;
++      struct device_node      *phy_node, *dpmac_node;
++      struct net_device       *netdev;
++      phy_interface_t         if_mode;
++      int                     err = 0;
++
++      /* just being completely paranoid */
++      if (!mc_dev)
++              return -EFAULT;
++      dev = &mc_dev->dev;
++
++      /* prepare a net_dev structure to make the phy lib API happy */
++      netdev = alloc_etherdev(sizeof(*priv));
++      if (!netdev) {
++              dev_err(dev, "alloc_etherdev error\n");
++              err = -ENOMEM;
++              goto err_exit;
++      }
++      priv = netdev_priv(netdev);
++      priv->mc_dev = mc_dev;
++      priv->netdev = netdev;
++
++      SET_NETDEV_DEV(netdev, dev);
++      snprintf(netdev->name, IFNAMSIZ, "mac%d", mc_dev->obj_desc.id);
++
++      dev_set_drvdata(dev, priv);
++
++      err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io);
++      if (err || !mc_dev->mc_io) {
++              dev_err(dev, "fsl_mc_portal_allocate error: %d\n", err);
++              err = -ENODEV;
++              goto err_free_netdev;
++      }
++
++      err = dpmac_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
++                       &mc_dev->mc_handle);
++      if (err || !mc_dev->mc_handle) {
++              dev_err(dev, "dpmac_open error: %d\n", err);
++              err = -ENODEV;
++              goto err_free_mcp;
++      }
++
++      err = dpmac_get_attributes(mc_dev->mc_io, 0,
++                                 mc_dev->mc_handle, &priv->attr);
++      if (err) {
++              dev_err(dev, "dpmac_get_attributes err %d\n", err);
++              err = -EINVAL;
++              goto err_close;
++      }
++
++      err = check_dpmac_version(priv);
++      if (err)
++              goto err_close;
++
++      /* Look up the DPMAC node in the device-tree. */
++      dpmac_node = lookup_node(dev, priv->attr.id);
++      if (!dpmac_node) {
++              dev_err(dev, "No dpmac@%d subnode found.\n", priv->attr.id);
++              err = -ENODEV;
++              goto err_close;
++      }
++
++      err = setup_irqs(mc_dev);
++      if (err) {
++              err = -EFAULT;
++              goto err_close;
++      }
++
++#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
++      /* OPTIONAL, register netdev just to make it visible to the user */
++      netdev->netdev_ops = &dpaa2_mac_ndo_ops;
++      netdev->ethtool_ops = &dpaa2_mac_ethtool_ops;
++
++      /* phy starts up enabled so netdev should be up too */
++      netdev->flags |= IFF_UP;
++
++      err = register_netdev(priv->netdev);
++      if (err < 0) {
++              dev_err(dev, "register_netdev error %d\n", err);
++              err = -ENODEV;
++              goto err_free_irq;
++      }
++#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
++
++      /* probe the PHY as a fixed-link if the link type declared in DPC
++       * explicitly mandates this
++       */
++      if (priv->attr.link_type == DPMAC_LINK_TYPE_FIXED)
++              goto probe_fixed_link;
++
++      if (priv->attr.eth_if < ARRAY_SIZE(dpaa2_mac_iface_mode)) {
++              if_mode = dpaa2_mac_iface_mode[priv->attr.eth_if];
++              dev_dbg(dev, "\tusing if mode %s for eth_if %d\n",
++                      phy_modes(if_mode), priv->attr.eth_if);
++      } else {
++              dev_warn(dev, "Unexpected interface mode %d, will probe as fixed link\n",
++                       priv->attr.eth_if);
++              goto probe_fixed_link;
++      }
++
++      /* try to connect to the PHY */
++      phy_node = of_parse_phandle(dpmac_node, "phy-handle", 0);
++      if (!phy_node) {
++              if (!phy_node) {
++                      dev_err(dev, "dpmac node has no phy-handle property\n");
++                      err = -ENODEV;
++                      goto err_no_phy;
++              }
++      }
++      netdev->phydev = of_phy_connect(netdev, phy_node,
++                                      &dpaa2_mac_link_changed, 0, if_mode);
++      if (!netdev->phydev) {
++              /* No need for dev_err(); the kernel's loud enough as it is. */
++              dev_dbg(dev, "Can't of_phy_connect() now.\n");
++              /* We might be waiting for the MDIO MUX to probe, so defer
++               * our own probing.
++               */
++              err = -EPROBE_DEFER;
++              goto err_defer;
++      }
++      dev_info(dev, "Connected to %s PHY.\n", phy_modes(if_mode));
++
++probe_fixed_link:
++      if (!netdev->phydev) {
++              struct fixed_phy_status status = {
++                      .link = 1,
++                      /* fixed-phys don't support 10Gbps speed for now */
++                      .speed = 1000,
++                      .duplex = 1,
++              };
++
++              /* try to register a fixed link phy */
++              netdev->phydev = fixed_phy_register(PHY_POLL, &status, -1, NULL);
++              if (!netdev->phydev || IS_ERR(netdev->phydev)) {
++                      dev_err(dev, "error trying to register fixed PHY\n");
++                      /* So we don't crash unregister_netdev() later on */
++                      netdev->phydev = NULL;
++                      err = -EFAULT;
++                      goto err_no_phy;
++              }
++              dev_info(dev, "Registered fixed PHY.\n");
++      }
++
++      /* start PHY state machine */
++#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
++      dpaa2_mac_open(netdev);
++#else /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
++      phy_start(netdev->phydev);
++#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
++      return 0;
++
++err_defer:
++err_no_phy:
++#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
++      unregister_netdev(netdev);
++err_free_irq:
++#endif
++      teardown_irqs(mc_dev);
++err_close:
++      dpmac_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
++err_free_mcp:
++      fsl_mc_portal_free(mc_dev->mc_io);
++err_free_netdev:
++      free_netdev(netdev);
++err_exit:
++      return err;
++}
++
++static int dpaa2_mac_remove(struct fsl_mc_device *mc_dev)
++{
++      struct device           *dev = &mc_dev->dev;
++      struct dpaa2_mac_priv   *priv = dev_get_drvdata(dev);
++
++      unregister_netdev(priv->netdev);
++      teardown_irqs(priv->mc_dev);
++      dpmac_close(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle);
++      fsl_mc_portal_free(priv->mc_dev->mc_io);
++      free_netdev(priv->netdev);
++
++      dev_set_drvdata(dev, NULL);
++      kfree(priv);
++
++      return 0;
++}
++
++static const struct fsl_mc_device_match_id dpaa2_mac_match_id_table[] = {
++      {
++              .vendor = FSL_MC_VENDOR_FREESCALE,
++              .obj_type = "dpmac",
++              .ver_major = DPMAC_VER_MAJOR,
++              .ver_minor = DPMAC_VER_MINOR,
++      },
++      {}
++};
++
++static struct fsl_mc_driver dpaa2_mac_drv = {
++      .driver = {
++              .name           = KBUILD_MODNAME,
++              .owner          = THIS_MODULE,
++      },
++      .probe          = dpaa2_mac_probe,
++      .remove         = dpaa2_mac_remove,
++      .match_id_table = dpaa2_mac_match_id_table,
++};
++
++module_fsl_mc_driver(dpaa2_mac_drv);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("DPAA2 PHY proxy interface driver");