aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-4.4/7208-staging-fsl-dpaa2-mac-Added-MAC-PHY-interface-driver.patch
diff options
context:
space:
mode:
authorYutang Jiang <yutang.jiang@nxp.com>2016-12-24 01:11:32 +0800
committerJo-Philipp Wich <jo@mein.io>2017-01-03 15:19:15 +0100
commit1866368a8ab8cacf73aa47f67138040d5620439d (patch)
tree2b0dd1ba578016957856f59bf4b2edc54d6a46c5 /target/linux/layerscape/patches-4.4/7208-staging-fsl-dpaa2-mac-Added-MAC-PHY-interface-driver.patch
parentc6d3a62919a7f993be625391d8593c84423aa021 (diff)
downloadupstream-1866368a8ab8cacf73aa47f67138040d5620439d.tar.gz
upstream-1866368a8ab8cacf73aa47f67138040d5620439d.tar.bz2
upstream-1866368a8ab8cacf73aa47f67138040d5620439d.zip
layerscape: add ls1088ardb device support
LS1088A is an ARMv8 implementation combining eight ARM A53 processor cores. The LS1088ARDB is an evaluatoin platform that supports the LS1088A family SoCs. Features summary: - Eight 64-bit ARM v8 Cortex-A53 CPUs - Data path acceleration architecture 2.0 (DPAA2) - Ethernet interfaces - QUADSPI flash, 3 PCIe, 2 USB, 1 SD, 2 DUARTs etc Signed-off-by: Yutang Jiang <yutang.jiang@nxp.com>
Diffstat (limited to 'target/linux/layerscape/patches-4.4/7208-staging-fsl-dpaa2-mac-Added-MAC-PHY-interface-driver.patch')
-rw-r--r--target/linux/layerscape/patches-4.4/7208-staging-fsl-dpaa2-mac-Added-MAC-PHY-interface-driver.patch2347
1 files changed, 2347 insertions, 0 deletions
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
index 0000000000..42a23a598c
--- /dev/null
+++ b/target/linux/layerscape/patches-4.4/7208-staging-fsl-dpaa2-mac-Added-MAC-PHY-interface-driver.patch
@@ -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");