You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2348 lines
71 KiB
Diff
2348 lines
71 KiB
Diff
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");
|