netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink
@ 2022-06-17 20:32 Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding Sean Anderson
                   ` (27 more replies)
  0 siblings, 28 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Ioana Ciornei, Jonathan Corbet,
	Kishon Vijay Abraham I, Krzysztof Kozlowski, Li Yang,
	Rob Herring, Shawn Guo, Vinod Koul, devicetree, linux-phy

This series converts the DPAA driver to phylink. Additionally,
it also adds a serdes driver to allow for dynamic reconfiguration
between 1g and 10g interfaces (such as in an SFP+ slot). These changes
are submitted together for this RFC, but they will eventually be
submitted separately to the appropriate subsystem maintainers.

Only the mEMAC driver has gotten the phylink treatment for this RFC. I
would appreciate any help towards converting/testing the 10GEC and dTSEC
drivers. I don't have any boards with those MACs, so a large conversion
like this has a high risk of breakage.

I have tried to maintain backwards compatibility with existing device
trees whereever possible. However, one area where I was unable to
achieve this was with QSGMII. Please refer to patch 2 for details.

The serdes driver is mostly functional (but not quite, see patch 25).
However, I am not quite sure about the implementation details. I have made
a fairly extensive commentary on the driver in patch 1, so hopefully that
can provide some context. This series only adds support for the
LS1046ARDB SerDes, but it should be fairly straightforward to add
support for other SoCs and boards. Patches 26-27 should show the typical
steps.

Most of this series can be applied as-is. In particular, patches 4-21
are essentially cleanups which stand on their own merits.

Patches 4-8 were first submitted as [1].

[1] https://lore.kernel.org/netdev/20220531195851.1592220-1-sean.anderson@seco.com/


Sean Anderson (28):
  dt-bindings: phy: Add QorIQ SerDes binding
  dt-bindings: net: fman: Add additional interface properties
  phy: fsl: Add QorIQ SerDes driver
  net: fman: Convert to SPDX identifiers
  net: fman: Don't pass comm_mode to enable/disable
  net: fman: Store en/disable in mac_device instead of mac_priv_s
  net: fman: dtsec: Always gracefully stop/start
  net: fman: Get PCS node in per-mac init
  net: fman: Store initialization function in match data
  net: fman: Move struct dev to mac_device
  net: fman: Configure fixed link in memac_initialization
  net: fman: Export/rename some common functions
  net: fman: memac: Use params instead of priv for max_speed
  net: fman: Move initialization to mac-specific files
  net: fman: Mark mac methods static
  net: fman: Inline several functions into initialization
  net: fman: Remove internal_phy_node from params
  net: fman: Map the base address once
  net: fman: Pass params directly to mac init
  net: fman: Use mac_dev for some params
  net: fman: Clean up error handling
  net: fman: memac: Add serdes support
  net: fman: memac: Use lynx pcs driver
  net: dpaa: Use mac_dev variable in dpaa_netdev_init
  [RFC] net: dpaa: Convert to phylink
  arm64: dts: ls1046ardb: Add serdes bindings
  arm64: dts: ls1046a: Add SerDes bindings
  arm64: dts: ls1046a: Specify which MACs support RGMII

 .../devicetree/bindings/net/fsl-fman.txt      |   49 +-
 .../bindings/phy/fsl,qoriq-serdes.yaml        |   78 +
 Documentation/driver-api/phy/index.rst        |    1 +
 Documentation/driver-api/phy/qoriq.rst        |   91 ++
 MAINTAINERS                                   |    6 +
 .../boot/dts/freescale/fsl-ls1046-post.dtsi   |    8 +
 .../boot/dts/freescale/fsl-ls1046a-rdb.dts    |   32 +
 .../arm64/boot/dts/freescale/fsl-ls1046a.dtsi |   12 +
 drivers/net/ethernet/freescale/dpaa/Kconfig   |    4 +-
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  100 +-
 .../ethernet/freescale/dpaa/dpaa_eth_sysfs.c  |    2 +-
 .../ethernet/freescale/dpaa/dpaa_ethtool.c    |   82 +-
 drivers/net/ethernet/freescale/fman/Makefile  |    3 +-
 drivers/net/ethernet/freescale/fman/fman.c    |   31 +-
 drivers/net/ethernet/freescale/fman/fman.h    |   31 +-
 .../net/ethernet/freescale/fman/fman_dtsec.c  |  319 ++--
 .../net/ethernet/freescale/fman/fman_dtsec.h  |   58 +-
 .../net/ethernet/freescale/fman/fman_keygen.c |   29 +-
 .../net/ethernet/freescale/fman/fman_keygen.h |   29 +-
 .../net/ethernet/freescale/fman/fman_mac.h    |   29 -
 .../net/ethernet/freescale/fman/fman_memac.c  |  864 +++++-----
 .../net/ethernet/freescale/fman/fman_memac.h  |   57 +-
 .../net/ethernet/freescale/fman/fman_muram.c  |   31 +-
 .../net/ethernet/freescale/fman/fman_muram.h  |   32 +-
 .../net/ethernet/freescale/fman/fman_port.c   |   29 +-
 .../net/ethernet/freescale/fman/fman_port.h   |   29 +-
 drivers/net/ethernet/freescale/fman/fman_sp.c |   29 +-
 drivers/net/ethernet/freescale/fman/fman_sp.h |   28 +-
 .../net/ethernet/freescale/fman/fman_tgec.c   |  155 +-
 .../net/ethernet/freescale/fman/fman_tgec.h   |   54 +-
 drivers/net/ethernet/freescale/fman/mac.c     |  645 +-------
 drivers/net/ethernet/freescale/fman/mac.h     |   62 +-
 drivers/phy/freescale/Kconfig                 |   19 +
 drivers/phy/freescale/Makefile                |    1 +
 drivers/phy/freescale/phy-qoriq.c             | 1441 +++++++++++++++++
 35 files changed, 2562 insertions(+), 1908 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
 create mode 100644 Documentation/driver-api/phy/qoriq.rst
 create mode 100644 drivers/phy/freescale/phy-qoriq.c

-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 23:27   ` Rob Herring
  2022-06-18  1:15   ` Krzysztof Kozlowski
  2022-06-17 20:32 ` [PATCH net-next 02/28] dt-bindings: net: fman: Add additional interface properties Sean Anderson
                   ` (26 subsequent siblings)
  27 siblings, 2 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Kishon Vijay Abraham I,
	Krzysztof Kozlowski, Rob Herring, Vinod Koul, devicetree,
	linux-phy

This adds a binding for the SerDes module found on QorIQ processors. The
phy reference has two cells, one for the first lane and one for the
last. This should allow for good support of multi-lane protocols when
(if) they are added. There is no protocol option, because the driver is
designed to be able to completely reconfigure lanes at runtime.
Generally, the phy consumer can select the appropriate protocol using
set_mode. For the most part there is only one protocol controller
(consumer) per lane/protocol combination. The exception to this is the
B4860 processor, which has some lanes which can be connected to
multiple MACs. For that processor, I anticipate the easiest way to
resolve this will be to add an additional cell with a "protocol
controller instance" property.

Each serdes has a unique set of supported protocols (and lanes). The
support matrix is stored in the driver and is selected based on the
compatible string. It is anticipated that a new compatible string will
need to be added for each serdes on each SoC that drivers support is
added for.

There are two PLLs, each of which can be used as the master clock for
each lane. Each PLL has its own reference. For the moment they are
required, because it simplifies the driver implementation. Absent
reference clocks can be modeled by a fixed-clock with a rate of 0.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../bindings/phy/fsl,qoriq-serdes.yaml        | 78 +++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml

diff --git a/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml b/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
new file mode 100644
index 000000000000..4b9c1fcdab10
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/fsl,qoriq-serdes.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP QorIQ SerDes Device Tree Bindings
+
+maintainers:
+  - Sean Anderson <sean.anderson@seco.com>
+
+description: |
+  This binding describes the SerDes devices found in NXP's QorIQ line of
+  processors. The SerDes provides up to eight lanes. Each lane may be
+  configured individually, or may be combined with adjacent lanes for a
+  multi-lane protocol. The SerDes supports a variety of protocols, including up
+  to 10G Ethernet, PCIe, SATA, and others. The specific protocols supported for
+  each lane depend on the particular SoC.
+
+properties:
+  "#phy-cells":
+    const: 2
+    description: |
+      The cells contain the following arguments.
+
+      - description: |
+          The first lane in the group. Lanes are numbered based on the register
+          offsets, not the I/O ports. This corresponds to the letter-based
+          ("Lane A") naming scheme, and not the number-based ("Lane 0") naming
+          scheme. On most SoCs, "Lane A" is "Lane 0", but not always.
+        minimum: 0
+        maximum: 7
+      - description: |
+          Last lane. For single-lane protocols, this should be the same as the
+          first lane.
+        minimum: 0
+        maximum: 7
+
+  compatible:
+    enum:
+      - fsl,ls1046a-serdes-1
+      - fsl,ls1046a-serdes-2
+
+  clocks:
+    minItems: 2
+    maxItems: 2
+    description: |
+      Clock for each PLL reference clock input.
+
+  clock-names:
+    minItems: 2
+    maxItems: 2
+    items:
+      pattern: "^ref[0-1]$"
+
+  reg:
+    maxItems: 1
+
+required:
+  - "#phy-cells"
+  - compatible
+  - clocks
+  - clock-names
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    serdes1: phy@1ea0000 {
+      #phy-cells = <2>;
+      compatible = "fsl,ls1046a-serdes-1";
+      reg = <0x0 0x1ea0000 0x0 0x2000>;
+      clocks = <&clk_100mhz>, <&clk_156mhz>;
+      clock-names = "ref0", "ref1";
+    };
+
+...
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 02/28] dt-bindings: net: fman: Add additional interface properties
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-18  1:16   ` Krzysztof Kozlowski
  2022-06-17 20:32 ` [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver Sean Anderson
                   ` (25 subsequent siblings)
  27 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Krzysztof Kozlowski, Rob Herring,
	devicetree

At the moment, MEMACs are configured almost completely based on the
phy-connection-type. That is, if the phy interface is RGMII, it assumed
that RGMII is supported. For some interfaces, it is assumed that the
RCW/bootloader has set up the SerDes properly. The actual link state is
never reported.

To address these shortcomings, the driver will need additional
information. First, it needs to know how to access the PCS/PMAs (in
order to configure them and get the link status). The SGMII PCS/PMA is
the only currently-described PCS/PMA. Add the XFI and QSGMII PCS/PMAs as
well. The XFI (and 1GBase-KR) PCS/PMA is a c45 "phy" which sits on the
same MDIO bus as SGMII PCS/PMA. By default they will have conflicting
addresses, but they are also not enabled at the same time by default.
Therefore, we can let the default address for the XFI PCS/PMA be the
same as for SGMII. This will allow for backwards-compatibility.

QSGMII, however, cannot work with the current binding. This is because
the QSGMII PCS/PMAs are only present on one MAC's MDIO bus. At the
moment this is worked around by having every MAC write to the PCS/PMA
addresses (without checking if they are present). This only works if
each MAC has the same configuration, and only if we don't need to know
the status. Because the QSGMII PCS/PMA will typically be located on a
different MDIO bus than the MAC's SGMII PCS/PMA, there is no fallback
for the QSGMII PCS/PMA.

MEMACs (across all SoCs) support the following protocols:

- MII
- RGMII
- SGMII, 1000Base-X, and 1000Base-KX
- 2500Base-X (aka 2.5G SGMII)
- QSGMII
- 10GBase-R (aka XFI) and 10GBase-KR
- XAUI and HiGig

Each line documents a set of orthogonal protocols (e.g. XAUI is
supported if and only if HiGig is supported). Additionally,

- XAUI implies support for 10GBase-R
- 10GBase-R is supported if and only if RGMII is not supported
- 2500Base-X implies support for 1000Base-X
- MII implies support for RGMII

To switch between different protocols, we must reconfigure the SerDes.
This is done by using the standard phys property. We can also use it to
validate whether different protocols are supported (e.g. using
phy_validate). This will work for serial protocols, but not RGMII or
MII. Additionally, we still need to be compatible when there is no
SerDes.

While we can detect 10G support by examining the port speed (as set by
fsl,fman-10g-port), we cannot determine support for any of the other
protocols based on the existing binding. In fact, the binding works
against us in some respects, because pcsphy-handle is required even if
there is no possible PCS/PMA for that MAC. To allow for backwards-
compatibility, we use a boolean-style property for RGMII (instead of
presence/absence-style). When the property for RGMII is missing, we will
assume that it is supported. The exception is MII, since no existing
device trees use it (as far as I could tell).

Unfortunately, QSGMII support will be broken for old device trees. There
is nothing we can do about this because of the PCS/PMA situation (as
described above).

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../devicetree/bindings/net/fsl-fman.txt      | 49 +++++++++++++++++--
 1 file changed, 45 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/fsl-fman.txt b/Documentation/devicetree/bindings/net/fsl-fman.txt
index 801efc7d6818..25c7288e1db2 100644
--- a/Documentation/devicetree/bindings/net/fsl-fman.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fman.txt
@@ -322,10 +322,50 @@ PROPERTIES
 		Value type: <phandle>
 		Definition: A phandle for 1EEE1588 timer.
 
+- phys
+		Usage optional for "fsl,fman-memac" MACs
+		Value type: <prop-encoded-array>
+		Definition: A phandle for the SerDes lanes which should be
+		used. This property is required if a pcsphy-handle is
+		specified.
+
+- phy-names
+		Usage optional for "fsl,fman-memac" MACs
+		Value type: <stringlist>
+		Definition: Should be "serdes". Must be present if phys is.
+
 - pcsphy-handle
+		Usage optional for "fsl,fman-memac" MACs
+		Value type: <prop-encoded-array>
+		Definition: An array of phandles for PCS/PMA devices. Without a
+		pcs-names property (see below) this should contain a phandle
+		referencing the SGMII PCS/PMA. This property may be absent if
+		no serial interfaces are supported.
+
+- pcs-names
+		Usage optional for "fsl,fman-memac" MACs
+		Value type: <stringlist>
+		Definition: The type of each PCS/PMA, corresponding to
+		pcsphy-handle. Each value may be one of
+		- "sgmii"
+		- "qsgmii"
+		- "xfi"
+		If "xfi" is absent, it will default to the value of "sgmii". If
+		this property is absent, the first phandle in pcsphy-handle
+		will be assumed to be "sgmii".
+
+- rgmii
 		Usage required for "fsl,fman-memac" MACs
-		Value type: <phandle>
-		Definition: A phandle for pcsphy.
+		Value type: <u32>
+		Definition: This property should be 1 if RGMII is supported and
+		0 otherwise.
+
+- mii
+		Usage optional for "fsl,fman-memac" MACs
+		Value type: <empty>
+		Definition: This property should be present if MII is
+		supported. rgmii must be enabled for this property to be
+		effective.
 
 - tbi-handle
 		Usage required for "fsl,fman-dtsec" MACs
@@ -446,8 +486,9 @@ For internal PHY device on internal mdio bus, a PHY node should be created.
 See the definition of the PHY node in booting-without-of.txt for an
 example of how to define a PHY (Internal PHY has no interrupt line).
 - For "fsl,fman-mdio" compatible internal mdio bus, the PHY is TBI PHY.
-- For "fsl,fman-memac-mdio" compatible internal mdio bus, the PHY is PCS PHY,
-  PCS PHY addr must be '0'.
+- For "fsl,fman-memac-mdio" compatible internal mdio bus, the PHY is PCS PHY.
+  The PCS PHY address should correspond to the value of the appropriate
+  MDEV_PORT.
 
 EXAMPLE
 
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 02/28] dt-bindings: net: fman: Add additional interface properties Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-18  3:02   ` kernel test robot
       [not found]   ` <GV1PR04MB905598703F5E9A0989662EFDE0AE9@GV1PR04MB9055.eurprd04.prod.outlook.com>
  2022-06-17 20:32 ` [PATCH net-next 04/28] net: fman: Convert to SPDX identifiers Sean Anderson
                   ` (24 subsequent siblings)
  27 siblings, 2 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Ioana Ciornei, Jonathan Corbet,
	Kishon Vijay Abraham I, Krzysztof Kozlowski, Rob Herring,
	Vinod Koul, devicetree, linux-phy

This adds support for the "SerDes" devices found on various NXP QorIQ SoCs.
There may be up to four SerDes devices on each SoC, each supporting up to
eight lanes. Protocol support for each SerDes is highly heterogeneous, with
each SoC typically having a totally different selection of supported
protocols for each lane. Additionally, the SerDes devices on each SoC also
have differing support. One SerDes will typically support Ethernet on most
lanes, while the other will typically support PCIe on most lanes.

There is wide hardware support for this SerDes. I have not done extensive
digging, but it seems to be used on almost every QorIQ device, including
the AMP and Layerscape series. Because each SoC typically has specific
instructions and exceptions for its SerDes, I have limited the initial
scope of this module to just the LS1046A. Additionally, I have only added
support for Ethernet protocols. There is not a great need for dynamic
reconfiguration for other protocols (SATA and PCIe handle rate changes in
hardware), so support for them may never be added.

Nevertheless, I have tried to provide an obvious path for adding support
for other SoCs as well as other protocols. SATA just needs support for
configuring LNmSSCR0. PCIe may need to configure the equalization
registers. It also uses multiple lanes. I have tried to write the driver
with multi-lane support in mind, so there should not need to be any large
changes. Although there are 6 protocols supported, I have only tested SGMII
and XFI. The rest have been implemented as described in the datasheet.

The PLLs are modeled as clocks proper. This lets us take advantage of the
existing clock infrastructure. I have not given the same treatment to the
lane "clocks" (dividers) because they need to be programmed in-concert with
the rest of the lane settings. One tricky thing is that the VCO (pll) rate
exceeds 2^32 (maxing out at around 5GHz). This will be a problem on 32-bit
platforms, since clock rates are stored as unsigned longs. To work around
this, the pll clock rate is generally treated in units of kHz.

The PLLs are configured rather interestingly. Instead of the usual direct
programming of the appropriate divisors, the input and output clock rates
are selected directly. Generally, the only restriction is that the input
and output must be integer multiples of each other. This suggests some kind
of internal look-up table. The datasheets generally list out the supported
combinations explicitly, and not all input/output combinations are
documented. I'm not sure if this is due to lack of support, or due to an
oversight. If this becomes an issue, then some combinations can be
blacklisted (or whitelisted). This may also be necessary for other SoCs
which have more stringent clock requirements.

The general API call list for this PHY is documented under the driver-api
docs. I think this is rather standard, except that most driverts configure
the mode (protocol) at xlate-time. Unlike some other phys where e.g. PCIe
x4 will use 4 separate phys all configured for PCIe, this driver uses one
phy configured to use 4 lanes. This is because while the individual lanes
may be configured individually, the protocol selection acts on all lanes at
once. Additionally, the order which lanes should be configured in is
specified by the datasheet.  To coordinate this, lanes are reserved in
phy_init, and released in phy_exit.

When getting a phy, if a phy already exists for those lanes, it is reused.
This is to make things like QSGMII work. Four MACs will all want to ensure
that the lane is configured properly, and we need to ensure they can all
call phy_init, etc. There is refcounting for phy_init and phy_power_on, so
the phy will only be powered on once. However, there is no refcounting for
phy_set_mode. A "rogue" MAC could set the mode to something non-QSGMII and
break the other MACs. Perhaps there is an opportunity for future
enhancement here.

This driver was written with reference to the LS1046A reference manual.
However, it was informed by reference manuals for all processors with
MEMACs, especially the T4240 (which appears to have a "maxed-out"
configuration).

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---
This appears to be the same underlying hardware as the Lynx 28G phy
added in 8f73b37cf3fb ("phy: add support for the Layerscape SerDes
28G"). I was working off an older Linux when preparing this series, so I
did not notice it. However, I believe this implementation is more
comprehensive/versatile. I will look into resolving the differences in
the future.

 Documentation/driver-api/phy/index.rst |    1 +
 Documentation/driver-api/phy/qoriq.rst |   91 ++
 MAINTAINERS                            |    6 +
 drivers/phy/freescale/Kconfig          |   19 +
 drivers/phy/freescale/Makefile         |    1 +
 drivers/phy/freescale/phy-qoriq.c      | 1441 ++++++++++++++++++++++++
 6 files changed, 1559 insertions(+)
 create mode 100644 Documentation/driver-api/phy/qoriq.rst
 create mode 100644 drivers/phy/freescale/phy-qoriq.c

diff --git a/Documentation/driver-api/phy/index.rst b/Documentation/driver-api/phy/index.rst
index 69ba1216de72..cc7ded8b969c 100644
--- a/Documentation/driver-api/phy/index.rst
+++ b/Documentation/driver-api/phy/index.rst
@@ -7,6 +7,7 @@ Generic PHY Framework
 .. toctree::
 
    phy
+   qoriq
    samsung-usb2
 
 .. only::  subproject and html
diff --git a/Documentation/driver-api/phy/qoriq.rst b/Documentation/driver-api/phy/qoriq.rst
new file mode 100644
index 000000000000..ea60fb75a295
--- /dev/null
+++ b/Documentation/driver-api/phy/qoriq.rst
@@ -0,0 +1,91 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+QorIQ SerDes
+============
+
+Using this phy
+--------------
+
+The general order of calls should be::
+
+    [devm_][of_]phy_get()
+    phy_init()
+    phy_power_on()
+    phy_set_mode[_ext]()
+    ...
+    phy_power_off()
+    phy_exit()
+    [[of_]phy_put()]
+
+:c:func:`phy_get` just gets (or creates) a new :c:type:`phy` with the lanes
+described in the phandle. :c:func:`phy_init` is what actually reserves the
+lanes for use. Unlike some other drivers, when the phy is created, there is no
+default protocol. :c:func:`phy_set_mode <phy_set_mode_ext>` must be called in
+order to set the protocol.
+
+Supporting SoCs
+---------------
+
+Each new SoC needs a :c:type:`struct qs_conf <qs_conf>` for each SerDes. The
+most important member is `modes`, which is an array of :c:type:`struct qs_mode
+<qs_mode>`. Each "mode" represents a configuration which can be programmed into
+a protocol control register. Modes can support multiple lanes (such for PCIe x2
+or x4), as well as multiple protocols (such as SGMII and 1000Base-KX). There
+are several helper macros to make configuring each mode easier. It is important
+that the list of modes is complete, even if not all protocols are supported.
+This lets the driver know which lanes are available, and which have been
+configured by the RCW.
+
+If a protocol is missing, add it to :c:type:`enum qs_protocol <qs_protocol>`,
+and to ``UNSUPPORTED_PROTOS``. If the PCCR shifts/masks for your protocol are
+missing, you will need to add them to :c:func:`qs_proto_mode_mask` and
+:c:func:`qs_proto_mode_shift`.
+
+For example, the configuration for SerDes1 of the LS1046A is::
+
+    static const struct qs_mode ls1046a_modes1[] = {
+        CONF_SINGLE(1, PCIE, 0x0, 1, 0b001),
+        CONF_1000BASEKX(0, 0x8, 0, 0b001),
+        CONF_SGMII25KX(1, 0x8, 1, 0b001),
+        CONF_SGMII25KX(2, 0x8, 2, 0b001),
+        CONF_SGMII25KX(3, 0x8, 3, 0b001),
+        CONF_SINGLE(1, QSGMII, 0x9, 2, 0b001),
+        CONF_XFI(2, 0xB, 0, 0b010),
+        CONF_XFI(3, 0xB, 1, 0b001),
+    };
+
+    static const struct qs_conf ls1046a_conf1 = {
+        .modes = ls1046a_modes1,
+        .mode_count = ARRAY_SIZE(ls1046a_modes1),
+        .lanes = 4,
+        .endian = REGMAP_ENDIAN_BIG,
+    };
+
+There is an additional set of configuration for SerDes2, which supports a
+different set of modes. Both configurations should be added to the match table::
+
+    { .compatible = "fsl,ls1046-serdes-1", .data = &ls1046a_conf1 },
+    { .compatible = "fsl,ls1046-serdes-2", .data = &ls1046a_conf2 },
+
+Supporting Protocols
+--------------------
+
+Each protocol is a combination of values which must be programmed into the lane
+registers. To add a new protocol, first add it to :c:type:`enum qs_protocol
+<qs_protocol>`. If it is in ``UNSUPPORTED_PROTOS``, remove it. Add a new entry to
+`qs_proto_params`, and populate the appropriate fields. You may need to add
+some new members to support new fields. Modify `qs_lookup_proto` to map the
+:c:type:`enum phy_mode <phy_mode>` to :c:type:`enum qs_protocol <qs_protocol>`.
+Ensure that :c:func:`qs_proto_mode_mask` and :c:func:`qs_proto_mode_shift` have
+been updated with support for your protocol.
+
+You may need to modify :c:func:`qs_set_mode` in order to support your procotol.
+This can happen when you have added members to :c:type:`struct qs_proto_params
+<qs_proto_params>`. It can also happen if you have specific clocking
+requirements, or protocol-specific registers to program.
+
+Internal API Reference
+----------------------
+
+.. kernel-doc:: drivers/phy/freescale/phy-qoriq.c
diff --git a/MAINTAINERS b/MAINTAINERS
index ca95b1833b97..ef65e2acdb48 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7977,6 +7977,12 @@ F:	drivers/ptp/ptp_qoriq.c
 F:	drivers/ptp/ptp_qoriq_debugfs.c
 F:	include/linux/fsl/ptp_qoriq.h
 
+FREESCALE QORIQ SERDES DRIVER
+M:	Sean Anderson <sean.anderson@seco.com>
+S:	Maintained
+F:	Documentation/driver-api/phy/qoriq.rst
+F:	drivers/phy/freescale/phy-qoriq.c
+
 FREESCALE QUAD SPI DRIVER
 M:	Han Xu <han.xu@nxp.com>
 L:	linux-spi@vger.kernel.org
diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
index f9c54cd02036..c65dbcc58565 100644
--- a/drivers/phy/freescale/Kconfig
+++ b/drivers/phy/freescale/Kconfig
@@ -38,3 +38,22 @@ config PHY_FSL_LYNX_28G
 	  found on NXP's Layerscape platforms such as LX2160A.
 	  Used to change the protocol running on SerDes lanes at runtime.
 	  Only useful for a restricted set of Ethernet protocols.
+
+config PHY_QORIQ
+	tristate "QorIQ SerDes support"
+	select GENERIC_PHY
+	select REGMAP_MMIO
+	help
+	  This adds support for the "SerDes" devices found on various QorIQ
+	  SoCs. There may be up to four SerDes devices on each SoC, and each
+	  device supports up to eight lanes. The SerDes is configured by
+	  default by the RCW, but this module is necessary in order to support
+	  dynamic reconfiguration (such as to support 1G and 10G ethernet on
+	  the same interface). The hardware supports a variety of protocols,
+	  including Ethernet, SATA, PCIe, and more exotic links such as
+	  Interlaken and Aurora. This driver only supports Ethernet, but it
+	  will try not to touch lanes configured for other protocols.
+
+	  If you have a QorIQ processor and want to dynamically reconfigure
+	  your SerDes, say Y. If this driver is compiled as a module, it will
+	  be named phy-qoriq.
diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
index 3518d5dbe8a7..2aca938d9e75 100644
--- a/drivers/phy/freescale/Makefile
+++ b/drivers/phy/freescale/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_PHY_FSL_IMX8MQ_USB)	+= phy-fsl-imx8mq-usb.o
 obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY)	+= phy-fsl-imx8-mipi-dphy.o
 obj-$(CONFIG_PHY_FSL_IMX8M_PCIE)	+= phy-fsl-imx8m-pcie.o
 obj-$(CONFIG_PHY_FSL_LYNX_28G)		+= phy-fsl-lynx-28g.o
+obj-$(CONFIG_PHY_QORIQ)			+= phy-qoriq.o
diff --git a/drivers/phy/freescale/phy-qoriq.c b/drivers/phy/freescale/phy-qoriq.c
new file mode 100644
index 000000000000..6edd770a4c4f
--- /dev/null
+++ b/drivers/phy/freescale/phy-qoriq.c
@@ -0,0 +1,1441 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/math64.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/units.h>
+
+#define PLL_STRIDE	0x20
+#define PLLa(a, off)	((a) * PLL_STRIDE + (off))
+#define PLLaRSTCTL(a)	PLLa(a, 0x00)
+#define PLLaCR0(a)	PLLa(a, 0x04)
+
+#define PLLaRSTCTL_RSTREQ	BIT(31)
+#define PLLaRSTCTL_RST_DONE	BIT(30)
+#define PLLaRSTCTL_RST_ERR	BIT(29)
+#define PLLaRSTCTL_PLLRST_B	BIT(7)
+#define PLLaRSTCTL_SDRST_B	BIT(6)
+#define PLLaRSTCTL_SDEN		BIT(5)
+
+#define PLLaCR0_POFF		BIT(31)
+#define PLLaCR0_RFCLK_SEL	GENMASK(30, 28)
+#define PLLaCR0_PLL_LCK		BIT(23)
+#define PLLaCR0_FRATE_SEL	GENMASK(19, 16)
+#define PLLaCR0_DLYDIV_SEL	GENMASK(1, 0)
+
+#define PCCR_BASE	0x200
+#define PCCR_STRIDE	0x4
+#define PCCRn(n)	(PCCR_BASE + n * PCCR_STRIDE)
+
+#define PCCR0_PEXa_MASK		GENMASK(2, 0)
+#define PCCR0_PEXa_SHIFT(a)	(28 - (a) * 4)
+
+#define PCCR2_SATAa_MASK	GENMASK(2, 0)
+#define PCCR2_SATAa_SHIFT(a)	(28 - (a) * 4)
+
+#define PCCR8_SGMIIa_KX(a)	BIT(31 - ((a) * 4))
+#define PCCR8_SGMIIa_MASK	GENMASK(2, 0)
+#define PCCR8_SGMIIa_SHIFT(a)	(28 - (a) * 4)
+
+#define PCCR9_QSGMIIa_MASK	GENMASK(2, 0)
+#define PCCR9_QSGMIIa_SHIFT(a)	(28 - (a) * 4)
+
+#define PCCRB_XFIa_MASK		GENMASK(2, 0)
+#define PCCRB_XFIa_SHIFT(a)	(28 - (a) * 4)
+
+#define LANE_BASE	0x800
+#define LANE_STRIDE	0x40
+#define LNm(m, off)	(LANE_BASE + (m) * LANE_STRIDE + (off))
+#define LNmGCR0(m)	LNm(m, 0x00)
+#define LNmGCR1(m)	LNm(m, 0x04)
+#define LNmSSCR0(m)	LNm(m, 0x0C)
+#define LNmRECR0(m)	LNm(m, 0x10)
+#define LNmRECR1(m)	LNm(m, 0x14)
+#define LNmTECR0(m)	LNm(m, 0x18)
+#define LNmSSCR1(m)	LNm(m, 0x1C)
+#define LNmTTLCR0(m)	LNm(m, 0x20)
+
+#define LNmGCR0_RPLL_LES	BIT(31)
+#define LNmGCR0_RRAT_SEL	GENMASK(29, 28)
+#define LNmGCR0_TPLL_LES	BIT(27)
+#define LNmGCR0_TRAT_SEL	GENMASK(25, 24)
+#define LNmGCR0_RRST_B		BIT(22)
+#define LNmGCR0_TRST_B		BIT(21)
+#define LNmGCR0_RX_PD		BIT(20)
+#define LNmGCR0_TX_PD		BIT(19)
+#define LNmGCR0_IF20BIT_EN	BIT(18)
+#define LNmGCR0_FIRST_LANE	BIT(16)
+#define LNmGCR0_TTRM_VM_SEL	GENMASK(13, 12)
+#define LNmGCR0_PROTS		GENMASK(11, 7)
+
+#define LNmGCR0_RAT_SEL_SAME		0b00
+#define LNmGCR0_RAT_SEL_HALF		0b01
+#define LNmGCR0_RAT_SEL_QUARTER		0b10
+#define LNmGCR0_RAT_SEL_DOUBLE		0b11
+
+#define LNmGCR0_PROTS_PCIE		0b00000
+#define LNmGCR0_PROTS_SGMII		0b00001
+#define LNmGCR0_PROTS_SATA		0b00010
+#define LNmGCR0_PROTS_XFI		0b01010
+
+#define LNmGCR1_RDAT_INV	BIT(31)
+#define LNmGCR1_TDAT_INV	BIT(30)
+#define LNmGCR1_OPAD_CTL	BIT(26)
+#define LNmGCR1_REIDL_TH	GENMASK(22, 20)
+#define LNmGCR1_REIDL_EX_SEL	GENMASK(19, 18)
+#define LNmGCR1_REIDL_ET_SEL	GENMASK(17, 16)
+#define LNmGCR1_REIDL_EX_MSB	BIT(15)
+#define LNmGCR1_REIDL_ET_MSB	BIT(14)
+#define LNmGCR1_REQ_CTL_SNP	BIT(13)
+#define LNmGCR1_REQ_CDR_SNP	BIT(12)
+#define LNmGCR1_TRSTDIR		BIT(7)
+#define LNmGCR1_REQ_BIN_SNP	BIT(6)
+#define LNmGCR1_ISLEW_RCTL	GENMASK(5, 4)
+#define LNmGCR1_OSLEW_RCTL	GENMASK(1, 0)
+
+#define LNmRECR0_GK2OVD		GENMASK(27, 24)
+#define LNmRECR0_GK3OVD		GENMASK(19, 16)
+#define LNmRECR0_GK2OVD_EN	BIT(15)
+#define LNmRECR0_GK3OVD_EN	BIT(16)
+#define LNmRECR0_BASE_WAND	GENMASK(11, 10)
+#define LNmRECR0_OSETOVD	GENMASK(5, 0)
+
+#define LNmRECR0_BASE_WAND_OFF		0b00
+#define LNmRECR0_BASE_WAND_DEFAULT	0b01
+#define LNmRECR0_BASE_WAND_ALTERNATE	0b10
+#define LNmRECR0_BASE_WAND_OSETOVD	0b11
+
+#define LNmTECR0_TEQ_TYPE	GENMASK(29, 28)
+#define LNmTECR0_SGN_PREQ	BIT(26)
+#define LNmTECR0_RATIO_PREQ	GENMASK(25, 22)
+#define LNmTECR0_SGN_POST1Q	BIT(21)
+#define LNmTECR0_RATIO_PST1Q	GENMASK(20, 16)
+#define LNmTECR0_ADPT_EQ	GENMASK(13, 8)
+#define LNmTECR0_AMP_RED	GENMASK(5, 0)
+
+#define LNmTECR0_TEQ_TYPE_NONE		0b00
+#define LNmTECR0_TEQ_TYPE_PRE		0b01
+#define LNmTECR0_TEQ_TYPE_BOTH		0b10
+
+#define LNmTTLCR0_FLT_SEL	GENMASK(29, 24)
+
+#define PCS_STRIDE	0x10
+#define CR_STRIDE	0x4
+#define PCSa(a, base, cr)	(base + (a) * PCS_STRIDE + (cr) * CR_STRIDE)
+
+#define PCSaCR1_MDEV_PORT	GENMASK(31, 27)
+
+#define SGMII_BASE	0x1800
+#define SGMIIaCR1(a)	PCSa(a, SGMII_BASE, 1)
+
+#define SGMIIaCR1_SGPCS_EN	BIT(11)
+
+#define QSGMII_OFFSET	0x1880
+#define QSGMIIaCR1(a)	PCSa(a, QSGMII_BASE, 1)
+
+#define XFI_OFFSET	0x1980
+#define XFIaCR1(a)	PCSa(a, XFI_BASE, 1)
+
+/* The maximum number of lanes in a single serdes */
+#define MAX_LANES	8
+
+enum qs_protocol {
+	QS_PROTO_UNKNOWN = 0,
+	QS_PROTO_SGMII,
+	QS_PROTO_SGMII25,
+	QS_PROTO_1000BASEKX,
+	QS_PROTO_QSGMII,
+	QS_PROTO_XFI,
+	QS_PROTO_10GKR,
+	QS_PROTO_PCIE, /* Not implemented */
+	QS_PROTO_SATA, /* Not implemented */
+	QS_PROTO_LAST,
+};
+
+static const char qs_proto_str[][16] = {
+	[QS_PROTO_UNKNOWN] = "unknown",
+	[QS_PROTO_SGMII] = "SGMII",
+	[QS_PROTO_SGMII25] = "2.5G SGMII",
+	[QS_PROTO_1000BASEKX] = "1000Base-KX",
+	[QS_PROTO_QSGMII] = "QSGMII",
+	[QS_PROTO_XFI] = "XFI",
+	[QS_PROTO_10GKR] = "10GBase-KR",
+	[QS_PROTO_PCIE] = "PCIe",
+	[QS_PROTO_SATA] = "SATA",
+};
+
+#define PROTO_MASK(proto) BIT(QS_PROTO_##proto)
+#define UNSUPPORTED_PROTOS (PROTO_MASK(SATA) | PROTO_MASK(PCIE))
+
+/**
+ * struct qs_proto_params - Parameters for configuring a protocol
+ * @frate_khz: The PLL rate, in kHz
+ * @rat_sel: The divider to get the line rate
+ * @if20bit: Whether the proto is 20 bits or 10 bits
+ * @prots: Lane protocol select
+ * @reidl_th: Receiver electrical idle detection threshold
+ * @reidl_ex: Exit electrical idle filter
+ * @reidl_et: Enter idle filter
+ * @slew: Slew control
+ * @baseline_wander: Enable baseline wander correction
+ * @gain: Adaptive equalization gain override
+ * @offset_override: Adaptive equalization offset override
+ * @teq: Transmit equalization type (none, precursor, or precursor and
+ *       postcursor). The next few values are only used for appropriate
+ *       equalization types.
+ * @preq_ratio: Ratio of full swing transition bit to pre-cursor
+ * @postq_ratio: Ratio of full swing transition bit to first post-cursor.
+ * @adpt_eq: Transmitter Adjustments for 8G/10G
+ * @amp_red: Overall TX Amplitude Reduction
+ * @flt_sel: TTL configuration selector
+ */
+struct qs_proto_params {
+	u32 frate_khz;
+	u8 rat_sel;
+	u8 prots;
+	u8 reidl_th;
+	u8 reidl_ex;
+	u8 reidl_et;
+	u8 slew;
+	u8 gain;
+	u8 baseline_wander;
+	u8 offset_override;
+	u8 teq;
+	u8 preq_ratio;
+	u8 postq_ratio;
+	u8 adpt_eq;
+	u8 amp_red;
+	u8 flt_sel;
+	bool if20bit;
+};
+
+static const struct qs_proto_params qs_proto_params[] = {
+	[QS_PROTO_SGMII] = {
+		.frate_khz = 5000000,
+		.rat_sel = LNmGCR0_RAT_SEL_QUARTER,
+		.if20bit = false,
+		.prots = LNmGCR0_PROTS_SGMII,
+		.reidl_th = 0b001,
+		.reidl_ex = 0b011,
+		.reidl_et = 0b100,
+		.slew = 0b01,
+		.gain = 0b1111,
+		.offset_override = 0b0011111,
+		.teq = LNmTECR0_TEQ_TYPE_NONE,
+		.adpt_eq = 0b110000,
+		.amp_red = 0b000110,
+		.flt_sel = 0b111001,
+	},
+	[QS_PROTO_1000BASEKX] = {
+		.frate_khz = 5000000,
+		.rat_sel = LNmGCR0_RAT_SEL_QUARTER,
+		.if20bit = false,
+		.prots = LNmGCR0_PROTS_SGMII,
+		.slew = 0b01,
+		.gain = 0b1111,
+		.offset_override = 0b0011111,
+		.teq = LNmTECR0_TEQ_TYPE_NONE,
+		.adpt_eq = 0b110000,
+		.flt_sel = 0b111001,
+	},
+	[QS_PROTO_SGMII25] = {
+		.frate_khz = 3125000,
+		.rat_sel = LNmGCR0_RAT_SEL_SAME,
+		.if20bit = false,
+		.prots = LNmGCR0_PROTS_SGMII,
+		.slew = 0b10,
+		.offset_override = 0b0011111,
+		.teq = LNmTECR0_TEQ_TYPE_PRE,
+		.postq_ratio = 0b00110,
+		.adpt_eq = 0b110000,
+	},
+	[QS_PROTO_QSGMII] = {
+		.frate_khz = 5000000,
+		.rat_sel = LNmGCR0_RAT_SEL_SAME,
+		.if20bit = true,
+		.prots = LNmGCR0_PROTS_SGMII,
+		.slew = 0b01,
+		.offset_override = 0b0011111,
+		.teq = LNmTECR0_TEQ_TYPE_PRE,
+		.postq_ratio = 0b00110,
+		.adpt_eq = 0b110000,
+		.amp_red = 0b000010,
+	},
+	[QS_PROTO_XFI] = {
+		.frate_khz = 5156250,
+		.rat_sel = LNmGCR0_RAT_SEL_DOUBLE,
+		.if20bit = true,
+		.prots = LNmGCR0_PROTS_XFI,
+		.slew = 0b01,
+		.baseline_wander = LNmRECR0_BASE_WAND_DEFAULT,
+		.offset_override = 0b1011111,
+		.teq = LNmTECR0_TEQ_TYPE_PRE,
+		.postq_ratio = 0b00011,
+		.adpt_eq = 0b110000,
+		.amp_red = 0b000111,
+	},
+	[QS_PROTO_10GKR] = {
+		.frate_khz = 5156250,
+		.rat_sel = LNmGCR0_RAT_SEL_DOUBLE,
+		.prots = LNmGCR0_PROTS_XFI,
+		.slew = 0b01,
+		.baseline_wander = LNmRECR0_BASE_WAND_DEFAULT,
+		.offset_override = 0b1011111,
+		.teq = LNmTECR0_TEQ_TYPE_BOTH,
+		.preq_ratio = 0b0011,
+		.postq_ratio = 0b01100,
+		.adpt_eq = 0b110000,
+	},
+};
+
+/**
+ * struct qs_mode - A single configuration of a protocol controller
+ * @protos: A bitmask of the &enum qs_protocol this mode supports
+ * @lanes: A bitbask of the lanes which will be used when this config is
+ *         selected
+ * @pccr: The number of the PCCR which contains this mode
+ * @idx: The index of the protocol controller. For example, SGMIIB would have
+ *       index 1.
+ * @cfg: The value to program into the controller to select this mode
+ *
+ * The serdes has multiple protocol controllers which can be each be selected
+ * independently. Depending on their configuration, they may use multiple lanes
+ * at once (e.g. AUI or PCIe x4). Additionally, multiple protocols may be
+ * supported by a single mode (XFI and 10GKR differ only in their protocol
+ * parameters).
+ */
+struct qs_mode {
+	u16 protos;
+	u8 lanes;
+	u8 pccr;
+	u8 idx;
+	u8 cfg;
+};
+
+static_assert(QS_PROTO_LAST - 1 <=
+	      sizeof_field(struct qs_mode, protos) * BITS_PER_BYTE);
+static_assert(MAX_LANES <=
+	      sizeof_field(struct qs_mode, lanes) * BITS_PER_BYTE);
+
+#define CONF(_lanes, _protos, _pccr, _idx, _cfg) { \
+	.lanes = _lanes, \
+	.protos = _protos, \
+	.pccr = _pccr, \
+	.idx = _idx, \
+	.cfg = _cfg, \
+}
+
+#define CONF_SINGLE(lane, proto, pccr, idx, cfg) \
+	CONF(BIT(lane), PROTO_MASK(proto), pccr, idx, cfg)
+
+#define CONF_1000BASEKX(lane, pccr, idx, cfg) \
+	CONF(BIT(lane), PROTO_MASK(SGMII) | PROTO_MASK(1000BASEKX), \
+	     pccr, idx, cfg)
+
+#define CONF_SGMII25(lane, pccr, idx, cfg) \
+	CONF(BIT(lane), PROTO_MASK(SGMII) | PROTO_MASK(SGMII25), \
+	     pccr, idx, cfg)
+
+#define CONF_SGMII25KX(lane, pccr, idx, cfg) \
+	CONF(BIT(lane), \
+	     PROTO_MASK(SGMII) | PROTO_MASK(1000BASEKX) | PROTO_MASK(SGMII25), \
+	     pccr, idx, cfg)
+
+#define CONF_XFI(lane, pccr, idx, cfg) \
+	CONF(BIT(lane), PROTO_MASK(XFI) | PROTO_MASK(10GKR), pccr, idx, cfg)
+
+/**
+ * struct qs_conf - Configuration for a particular serdes
+ * @modes: Valid protocol controller configurations
+ * @mode_count: Number of modes in @modes
+ * @lanes: Number of lanes
+ * @endian: Endianness of the registers
+ */
+struct qs_conf {
+	const struct qs_mode *modes;
+	size_t mode_count;
+	unsigned int lanes;
+	enum regmap_endian endian;
+};
+
+struct qs_priv;
+
+/**
+ * struct qs_clk - Driver data for the PLLs
+ * @hw: The clock hardware
+ * @serdes: The parent serdes
+ * @idx: Which PLL this clock is for
+ */
+struct qs_clk {
+	struct clk_hw hw;
+	struct qs_priv *serdes;
+	unsigned int idx;
+};
+
+struct qs_clk *qs_clk_hw_to_priv(struct clk_hw *hw)
+{
+	return container_of(hw, struct qs_clk, hw);
+}
+
+/**
+ * struct qs_priv - Driver data for the serdes
+ * @lock: A lock protecting "common" registers in @regmap, as well as the
+ *        members of this struct. Lane-specific registers are protected by the
+ *        phy's lock. PLL registers are protected by the clock's lock.
+ * @pll: The PLL clocks
+ * @ref: The reference clocks for the PLLs
+ * @dev: The serdes device
+ * @regmap: The backing regmap
+ * @conf: The configuration for this serdes
+ * @used_lanes: Bitmap of the lanes currently used by phys
+ * @groups: List of the created groups
+ */
+struct qs_priv {
+	struct mutex lock;
+	struct qs_clk pll[2];
+	struct clk *ref[2];
+	struct device *dev;
+	struct regmap *regmap;
+	const struct qs_conf *conf;
+	unsigned int used_lanes;
+	struct list_head groups;
+};
+
+/**
+ * struct qs_group - Driver data for a group of lanes
+ * @groups: List of other groups; protected by @serdes->lock.
+ * @phy: The associated phy
+ * @serdes: The parent serdes
+ * @pll: The currently-used pll
+ * @first_lane: The first lane in the group
+ * @last_lane: The last lane in the group
+ * @proto: The currently-configured protocol
+ * @users: Number of current users; protected by @serdes->lock.
+ */
+struct qs_group {
+	struct list_head groups;
+	struct phy *phy;
+	struct qs_priv *serdes;
+	struct clk *pll;
+	unsigned int first_lane;
+	unsigned int last_lane;
+	enum qs_protocol proto;
+	unsigned int users;
+};
+
+static u32 qs_read(struct qs_priv *serdes, u32 reg)
+{
+	unsigned int ret = 0;
+
+	WARN_ON_ONCE(regmap_read(serdes->regmap, reg, &ret));
+	return ret;
+}
+
+static void qs_write(struct qs_priv *serdes, u32 val, u32 reg)
+{
+	WARN_ON_ONCE(regmap_write(serdes->regmap, reg, val));
+}
+
+/* XXX: The output rate is in kHz to avoid overflow on 32-bit arches */
+
+static void qs_pll_disable(struct clk_hw *hw)
+{
+	struct qs_clk *clk = qs_clk_hw_to_priv(hw);
+	struct qs_priv *serdes = clk->serdes;
+	u32 rstctl = qs_read(serdes, PLLaRSTCTL(clk->idx));
+
+	dev_dbg(clk->serdes->dev, "%s(pll%d)\n", __func__, clk->idx);
+
+	rstctl &= ~PLLaRSTCTL_SDRST_B;
+	qs_write(serdes, rstctl, PLLaRSTCTL(clk->idx));
+	ndelay(50);
+	rstctl &= ~(PLLaRSTCTL_SDEN | PLLaRSTCTL_PLLRST_B);
+	qs_write(serdes, rstctl, PLLaRSTCTL(clk->idx));
+	ndelay(100);
+}
+
+static int qs_pll_enable(struct clk_hw *hw)
+{
+	struct qs_clk *clk = qs_clk_hw_to_priv(hw);
+	struct qs_priv *serdes = clk->serdes;
+	u32 rstctl = qs_read(serdes, PLLaRSTCTL(clk->idx));
+
+	dev_dbg(clk->serdes->dev, "%s(pll%d)\n", __func__, clk->idx);
+
+	rstctl |= PLLaRSTCTL_RSTREQ;
+	qs_write(serdes, rstctl, PLLaRSTCTL(clk->idx));
+
+	rstctl &= ~PLLaRSTCTL_RSTREQ;
+	rstctl |= PLLaRSTCTL_SDEN | PLLaRSTCTL_PLLRST_B | PLLaRSTCTL_SDRST_B;
+	qs_write(serdes, rstctl, PLLaRSTCTL(clk->idx));
+
+	/* TODO: wait for the PLL to lock */
+
+	return 0;
+}
+
+static int qs_pll_is_enabled(struct clk_hw *hw)
+{
+	struct qs_clk *clk = qs_clk_hw_to_priv(hw);
+	struct qs_priv *serdes = clk->serdes;
+	u32 rstctl = qs_read(serdes, PLLaRSTCTL(clk->idx));
+
+	dev_dbg(clk->serdes->dev, "%s(pll%d)\n", __func__, clk->idx);
+
+	return rstctl & PLLaRSTCTL_RST_DONE && !(rstctl & PLLaRSTCTL_RST_ERR);
+}
+
+static const u32 rfclk_sel_map[8] = {
+	[0b000] = 100000000,
+	[0b001] = 125000000,
+	[0b010] = 156250000,
+	[0b011] = 150000000,
+};
+
+/**
+ * qs_rfclk_to_sel() - Convert a reference clock rate to a selector
+ * @rate: The reference clock rate
+ *
+ * To allow for some variation in the reference clock rate, up to 100ppm of
+ * error is allowed.
+ *
+ * Return: An appropriate selector for @rate, or -%EINVAL.
+ */
+static int qs_rfclk_to_sel(u32 rate)
+{
+	int ret;
+
+	for (ret = 0; ret < ARRAY_SIZE(rfclk_sel_map); ret++) {
+		u32 rfclk_rate = rfclk_sel_map[ret];
+		/* Allow an error of 100ppm */
+		u32 error = rfclk_rate / 10000;
+
+		if (rate > rfclk_rate - error && rate < rfclk_rate + error)
+			return ret;
+	}
+
+	return -EINVAL;
+}
+
+static const u32 frate_sel_map[16] = {
+	[0b0000] = 5000000,
+	[0b0101] = 3750000,
+	[0b0110] = 5156250,
+	[0b0111] = 4000000,
+	[0b1001] = 3125000,
+	[0b1010] = 3000000,
+};
+
+/**
+ * qs_frate_to_sel() - Convert a VCO clock rate to a selector
+ * @rate_khz: The VCO frequency, in kHz
+ *
+ * Return: An appropriate selector for @rate_khz, or -%EINVAL.
+ */
+static int qs_frate_to_sel(u32 rate_khz)
+{
+	int ret;
+
+	for (ret = 0; ret < ARRAY_SIZE(frate_sel_map); ret++)
+		if (frate_sel_map[ret] == rate_khz)
+			return ret;
+
+	return -EINVAL;
+}
+
+static u32 qs_pll_ratio(u32 frate_sel, u32 rfclk_sel)
+{
+	u64 frate;
+	u32 rfclk, error, ratio;
+
+	frate = frate_sel_map[frate_sel] * (u64)HZ_PER_KHZ;
+	rfclk = rfclk_sel_map[rfclk_sel];
+
+	if (!frate || !rfclk)
+		return 0;
+
+	ratio = div_u64_rem(frate, rfclk, &error);
+	if (!error)
+		return ratio;
+	return 0;
+}
+
+static unsigned long qs_pll_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct qs_clk *clk = qs_clk_hw_to_priv(hw);
+	struct qs_priv *serdes = clk->serdes;
+	u32 cr0 = qs_read(serdes, PLLaCR0(clk->idx));
+	u32 frate_sel = FIELD_GET(PLLaCR0_FRATE_SEL, cr0);
+	u32 rfclk_sel = FIELD_GET(PLLaCR0_RFCLK_SEL, cr0);
+	unsigned long ret;
+
+	dev_dbg(clk->serdes->dev, "%s(pll%d, %lu)\n", __func__,
+		clk->idx, parent_rate);
+
+	ret = mult_frac(parent_rate, qs_pll_ratio(frate_sel, rfclk_sel),
+			 HZ_PER_KHZ);
+	return ret;
+}
+
+static long qs_pll_round_rate(struct clk_hw *hw, unsigned long rate_khz,
+			      unsigned long *parent_rate)
+{
+	int frate_sel, rfclk_sel;
+	struct qs_clk *clk = qs_clk_hw_to_priv(hw);
+	u32 ratio;
+
+	dev_dbg(clk->serdes->dev, "%s(pll%d, %lu, %lu)\n", __func__,
+		clk->idx, rate_khz, *parent_rate);
+
+	frate_sel = qs_frate_to_sel(rate_khz);
+	if (frate_sel < 0)
+		return frate_sel;
+
+	rfclk_sel = qs_rfclk_to_sel(*parent_rate);
+	if (rfclk_sel >= 0) {
+		ratio = qs_pll_ratio(frate_sel, rfclk_sel);
+		if (ratio)
+			return mult_frac(*parent_rate, ratio, HZ_PER_KHZ);
+	}
+
+	for (rfclk_sel = 0;
+	     rfclk_sel < ARRAY_SIZE(rfclk_sel_map);
+	     rfclk_sel++) {
+		ratio = qs_pll_ratio(frate_sel, rfclk_sel);
+		if (ratio) {
+			*parent_rate = rfclk_sel_map[rfclk_sel];
+			return mult_frac(*parent_rate, ratio, HZ_PER_KHZ);
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int qs_pll_set_rate(struct clk_hw *hw, unsigned long rate_khz,
+			   unsigned long parent_rate)
+{
+	int frate_sel, rfclk_sel, ret;
+	struct qs_clk *clk = qs_clk_hw_to_priv(hw);
+	struct qs_priv *serdes = clk->serdes;
+	u32 ratio, cr0 = qs_read(serdes, PLLaCR0(clk->idx));
+
+	dev_dbg(clk->serdes->dev, "%s(pll%d, %lu, %lu)\n", __func__,
+		clk->idx, rate_khz, parent_rate);
+
+	frate_sel = qs_frate_to_sel(rate_khz);
+	if (frate_sel < 0)
+		return frate_sel;
+
+	/* First try the existing rate */
+	rfclk_sel = qs_rfclk_to_sel(parent_rate);
+	if (rfclk_sel >= 0) {
+		ratio = qs_pll_ratio(frate_sel, rfclk_sel);
+		if (ratio)
+			goto got_rfclk;
+	}
+
+	for (rfclk_sel = 0;
+	     rfclk_sel < ARRAY_SIZE(rfclk_sel_map);
+	     rfclk_sel++) {
+		ratio = qs_pll_ratio(frate_sel, rfclk_sel);
+		if (ratio) {
+			ret = clk_set_rate(serdes->ref[clk->idx],
+					   rfclk_sel_map[rfclk_sel]);
+			if (!ret)
+				goto got_rfclk;
+		}
+	}
+
+	return ret;
+
+got_rfclk:
+	cr0 &= ~(PLLaCR0_RFCLK_SEL | PLLaCR0_FRATE_SEL);
+	cr0 |= FIELD_PREP(PLLaCR0_RFCLK_SEL, rfclk_sel);
+	cr0 |= FIELD_PREP(PLLaCR0_FRATE_SEL, frate_sel);
+	qs_write(serdes, cr0, PLLaCR0(clk->idx));
+	return 0;
+}
+
+static const struct clk_ops qs_pll_clk_ops = {
+	.enable = qs_pll_enable,
+	.disable = qs_pll_disable,
+	.is_enabled = qs_pll_is_enabled,
+	.recalc_rate = qs_pll_recalc_rate,
+	.round_rate = qs_pll_round_rate,
+	.set_rate = qs_pll_set_rate,
+};
+
+/**
+ * qs_lane_bitmap() - Get a bitmap for a group of lanes
+ * @group: The group of lanes
+ *
+ * Return: A mask containing all bits between @group->first and @group->last
+ */
+static unsigned int qs_lane_bitmap(struct qs_group *group)
+{
+	if (group->first_lane > group->last_lane)
+		return GENMASK(group->first_lane, group->last_lane);
+	else
+		return GENMASK(group->last_lane, group->first_lane);
+}
+
+static int qs_init(struct phy *phy)
+{
+	int ret = 0;
+	struct qs_group *group = phy_get_drvdata(phy);
+	struct qs_priv *serdes = group->serdes;
+	unsigned int lane_mask = qs_lane_bitmap(group);
+
+	mutex_lock(&serdes->lock);
+	if (serdes->used_lanes & lane_mask)
+		ret = -EBUSY;
+	else
+		serdes->used_lanes |= lane_mask;
+	mutex_unlock(&serdes->lock);
+	return ret;
+}
+
+static int qs_exit(struct phy *phy)
+{
+	struct qs_group *group = phy_get_drvdata(phy);
+	struct qs_priv *serdes = group->serdes;
+
+	clk_disable_unprepare(group->pll);
+	clk_rate_exclusive_put(group->pll);
+	mutex_lock(&serdes->lock);
+	serdes->used_lanes &= ~qs_lane_bitmap(group);
+	mutex_unlock(&serdes->lock);
+	return 0;
+}
+
+/*
+ * This is tricky. If first_lane=1 and last_lane=0, the condition will see 2,
+ * 1, 0. But the loop body will see 1, 0. We do this to avoid underflow. We
+ * can't pull the same trick when incrementing, because then we might have to
+ * start at -1 if (e.g.) first_lane = 0.
+ */
+#define for_range(val, start, end) \
+	for (val = start < end ? start : start + 1; \
+	     start < end ? val <= end : val-- > end; \
+	     start < end ? val++ : 0)
+#define for_each_lane(lane, group) \
+	for_range(lane, group->first_lane, group->last_lane)
+#define for_each_lane_reverse(lane, group) \
+	for_range(lane, group->last_lane, group->first_lane)
+
+static int qs_power_on(struct phy *phy)
+{
+	int i;
+	struct qs_group *group = phy_get_drvdata(phy);
+	u32 gcr0;
+
+	for_each_lane(i, group) {
+		gcr0 = qs_read(group->serdes, LNmGCR0(i));
+		gcr0 &= ~(LNmGCR0_RX_PD | LNmGCR0_TX_PD);
+		qs_write(group->serdes, gcr0, LNmGCR0(i));
+
+		usleep_range(15, 30);
+		gcr0 |= LNmGCR0_RRST_B | LNmGCR0_TRST_B;
+		qs_write(group->serdes, gcr0, LNmGCR0(i));
+	}
+
+	return 0;
+}
+
+static int qs_power_off(struct phy *phy)
+{
+	int i;
+	struct qs_group *group = phy_get_drvdata(phy);
+	u32 gcr0;
+
+	for_each_lane_reverse(i, group) {
+		gcr0 = qs_read(group->serdes, LNmGCR0(i));
+		gcr0 |= LNmGCR0_RX_PD | LNmGCR0_TX_PD;
+		gcr0 &= ~(LNmGCR0_RRST_B | LNmGCR0_TRST_B);
+		qs_write(group->serdes, gcr0, LNmGCR0(i));
+	}
+
+	return 0;
+}
+
+/**
+ * qs_lookup_proto() - Convert a phy-subsystem mode to a protocol
+ * @mode: The mode to convert
+ * @submode: The submode of @mode
+ *
+ * Return: A corresponding serdes-specific mode
+ */
+static enum qs_protocol qs_lookup_proto(enum phy_mode mode, int submode)
+{
+	switch (mode) {
+	case PHY_MODE_ETHERNET:
+		switch (submode) {
+		case PHY_INTERFACE_MODE_SGMII:
+		case PHY_INTERFACE_MODE_1000BASEX:
+			return QS_PROTO_SGMII;
+		case PHY_INTERFACE_MODE_2500BASEX:
+			return QS_PROTO_SGMII;
+		case PHY_INTERFACE_MODE_QSGMII:
+			return QS_PROTO_QSGMII;
+		case PHY_INTERFACE_MODE_XGMII:
+		case PHY_INTERFACE_MODE_10GBASER:
+			return QS_PROTO_XFI;
+		case PHY_INTERFACE_MODE_10GKR:
+			return QS_PROTO_10GKR;
+		default:
+			return QS_PROTO_UNKNOWN;
+		}
+	/* Not implemented (yet) */
+	case PHY_MODE_PCIE:
+	case PHY_MODE_SATA:
+	default:
+		return QS_PROTO_UNKNOWN;
+	}
+}
+
+/**
+ * qs_lookup_mode() - Get the mode for a group/protocol combination
+ * @group: The group of lanes to use
+ * @proto: The protocol to use
+ *
+ * Return: An appropriate mode to use, or %NULL if none match.
+ */
+static const struct qs_mode *qs_lookup_mode(struct qs_group *group,
+					    enum qs_protocol proto)
+{
+	int i;
+	const struct qs_conf *conf = group->serdes->conf;
+
+	for (i = 0; i < conf->mode_count; i++) {
+		const struct qs_mode *mode = &conf->modes[i];
+
+		if (BIT(proto) & mode->protos &&
+		    qs_lane_bitmap(group) == mode->lanes)
+			return mode;
+	}
+
+	return NULL;
+}
+
+static int qs_validate(struct phy *phy, enum phy_mode phy_mode, int submode,
+		       union phy_configure_opts *opts)
+{
+	enum qs_protocol proto;
+	struct qs_group *group = phy_get_drvdata(phy);
+	const struct qs_mode *mode;
+
+	proto = qs_lookup_proto(phy_mode, submode);
+	if (proto == QS_PROTO_UNKNOWN)
+		return -EINVAL;
+
+	/* Nothing to do */
+	if (proto == group->proto)
+		return 0;
+
+	mode = qs_lookup_mode(group, proto);
+	if (!mode)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * qs_proto_mode_mask() - Get the mask for a PCCR config
+ * @mode: The mode to use
+ *
+ * Return: The mask, shifted down to the lsb.
+ */
+static u32 qs_proto_mode_mask(const struct qs_mode *mode)
+{
+	switch (mode->pccr) {
+	case 0x0:
+		if (mode->protos & PROTO_MASK(PCIE))
+			return PCCR0_PEXa_MASK;
+		break;
+	case 0x2:
+		if (mode->protos & PROTO_MASK(SATA))
+			return PCCR2_SATAa_MASK;
+		break;
+	case 0x8:
+		if (mode->protos & PROTO_MASK(SGMII))
+			return PCCR8_SGMIIa_MASK;
+		break;
+	case 0x9:
+		if (mode->protos & PROTO_MASK(QSGMII))
+			return PCCR9_QSGMIIa_MASK;
+		break;
+	case 0xB:
+		if (mode->protos & PROTO_MASK(XFI))
+			return PCCRB_XFIa_MASK;
+		break;
+	}
+	pr_debug("unknown mode PCCR%X %s%c\n", mode->pccr,
+		 qs_proto_str[mode->protos], 'A' + mode->idx);
+	return 0;
+}
+
+/**
+ * qs_proto_mode_shift() - Get the shift for a PCCR config
+ * @mode: The mode to use
+ *
+ * Return: The amount of bits to shift the mask.
+ */
+static u32 qs_proto_mode_shift(const struct qs_mode *mode)
+{
+	switch (mode->pccr) {
+	case 0x0:
+		if (mode->protos & PROTO_MASK(PCIE))
+			return PCCR0_PEXa_SHIFT(mode->idx);
+		break;
+	case 0x2:
+		if (mode->protos & PROTO_MASK(SATA))
+			return PCCR2_SATAa_SHIFT(mode->idx);
+		break;
+	case 0x8:
+		if (mode->protos & PROTO_MASK(SGMII))
+			return PCCR8_SGMIIa_SHIFT(mode->idx);
+		break;
+	case 0x9:
+		if (mode->protos & PROTO_MASK(QSGMII))
+			return PCCR9_QSGMIIa_SHIFT(mode->idx);
+		break;
+	case 0xB:
+		if (mode->protos & PROTO_MASK(XFI))
+			return PCCRB_XFIa_SHIFT(mode->idx);
+		break;
+	}
+	pr_debug("unknown mode PCCR%X %s%c\n", mode->pccr,
+		 qs_proto_str[mode->protos], 'A' + mode->idx);
+	return 0;
+}
+
+/**
+ * qs_proto_mode_get() - Get the current config for a PCCR mode
+ * @mode: The mode to use
+ * @pccr: The current value of the PCCR
+ *
+ * Return: The current value of the PCCR config for this mode
+ */
+static u32 qs_proto_mode_get(const struct qs_mode *mode, u32 pccr)
+{
+	return (pccr >> qs_proto_mode_shift(mode)) & qs_proto_mode_mask(mode);
+}
+
+/**
+ * qs_proto_mode_prep() - Configure a PCCR for a mode
+ * @mode: The mode to configure
+ * @pccr: The current value of the PCCR
+ * @cfg: The config to program
+ *
+ * Return: The new value for the PCCR
+ */
+static u32 qs_proto_mode_prep(const struct qs_mode *mode, u32 pccr, u32 cfg)
+{
+	u32 shift = qs_proto_mode_shift(mode);
+
+	pccr &= ~(qs_proto_mode_mask(mode) << shift);
+	return pccr | cfg << shift;
+}
+
+#define abs_diff(a, b) ({ \
+	typeof(a) _a = (a); \
+	typeof(b) _b = (b); \
+	_a > _b ? _a - _b : _b - _a; \
+})
+
+static int qs_set_mode(struct phy *phy, enum phy_mode phy_mode, int submode)
+{
+	enum qs_protocol proto;
+	const struct qs_proto_params *params;
+	const struct qs_mode *old_mode = NULL, *new_mode;
+	int i, pll, ret;
+	struct qs_group *group = phy_get_drvdata(phy);
+	struct qs_priv *serdes = group->serdes;
+	u32 mask, tmp;
+	u32 gcr0 = 0, gcr1 = 0, recr0 = 0, tecr0 = 0;
+	u32 gcr0_mask = 0, gcr1_mask = 0, recr0_mask = 0, tecr0_mask = 0;
+
+	proto = qs_lookup_proto(phy_mode, submode);
+	if (proto == QS_PROTO_UNKNOWN) {
+		dev_dbg(&phy->dev, "unknown mode/submode %d/%d\n",
+			phy_mode, submode);
+		return -EINVAL;
+	}
+
+	/* Nothing to do */
+	if (proto == group->proto)
+		return 0;
+
+	new_mode = qs_lookup_mode(group, proto);
+	if (!new_mode) {
+		dev_dbg(&phy->dev, "could not find mode for %s on lanes %u to %u\n",
+			qs_proto_str[proto], group->first_lane,
+			group->last_lane);
+		return -EINVAL;
+	}
+
+	if (group->proto != QS_PROTO_UNKNOWN) {
+		old_mode = qs_lookup_mode(group, group->proto);
+		if (!old_mode) {
+			dev_err(&phy->dev, "could not find mode for %s\n",
+				qs_proto_str[group->proto]);
+			return -EBUSY;
+		}
+	}
+
+	clk_disable_unprepare(group->pll);
+	clk_rate_exclusive_put(group->pll);
+	group->pll = NULL;
+
+	/* First, try to use a PLL which already has the correct rate */
+	params = &qs_proto_params[proto];
+	for (pll = 0; pll < ARRAY_SIZE(serdes->pll); pll++) {
+		struct clk *clk = serdes->pll[pll].hw.clk;
+		unsigned long rate = clk_get_rate(clk);
+		unsigned long error = abs_diff(rate, params->frate_khz);
+
+		dev_dbg(&phy->dev, "pll%d has rate %lu\n", pll, rate);
+		/* Accept up to 100ppm deviation */
+		if ((!error || params->frate_khz / error > 10000) &&
+		    !clk_set_rate_exclusive(clk, rate))
+			goto got_pll;
+		/* Someone else got a different rate first */
+	}
+
+	/* If neither PLL has the right rate, try setting it */
+	for (pll = 0; pll < 2; pll++) {
+		ret = clk_set_rate_exclusive(serdes->pll[pll].hw.clk,
+					     params->frate_khz);
+		if (!ret)
+			goto got_pll;
+	}
+
+	dev_dbg(&phy->dev, "could not get a pll at %ukHz\n",
+		params->frate_khz);
+	return ret;
+
+got_pll:
+	group->pll = serdes->pll[pll].hw.clk;
+	clk_prepare_enable(group->pll);
+
+	gcr0_mask |= LNmGCR0_RRAT_SEL | LNmGCR0_TRAT_SEL;
+	gcr0_mask |= LNmGCR0_RPLL_LES | LNmGCR0_TPLL_LES;
+	gcr0_mask |= LNmGCR0_RRST_B | LNmGCR0_TRST_B;
+	gcr0_mask |= LNmGCR0_RX_PD | LNmGCR0_TX_PD;
+	gcr0_mask |= LNmGCR0_IF20BIT_EN | LNmGCR0_PROTS;
+	gcr0 |= FIELD_PREP(LNmGCR0_RPLL_LES, !pll);
+	gcr0 |= FIELD_PREP(LNmGCR0_TPLL_LES, !pll);
+	gcr0 |= FIELD_PREP(LNmGCR0_RRAT_SEL, params->rat_sel);
+	gcr0 |= FIELD_PREP(LNmGCR0_TRAT_SEL, params->rat_sel);
+	gcr0 |= FIELD_PREP(LNmGCR0_IF20BIT_EN, params->if20bit);
+	gcr0 |= FIELD_PREP(LNmGCR0_PROTS, params->prots);
+
+	gcr1_mask |= LNmGCR1_RDAT_INV | LNmGCR1_TDAT_INV;
+	gcr1_mask |= LNmGCR1_OPAD_CTL | LNmGCR1_REIDL_TH;
+	gcr1_mask |= LNmGCR1_REIDL_EX_SEL | LNmGCR1_REIDL_ET_SEL;
+	gcr1_mask |= LNmGCR1_REIDL_EX_MSB | LNmGCR1_REIDL_ET_MSB;
+	gcr1_mask |= LNmGCR1_REQ_CTL_SNP | LNmGCR1_REQ_CDR_SNP;
+	gcr1_mask |= LNmGCR1_TRSTDIR | LNmGCR1_REQ_BIN_SNP;
+	gcr1_mask |= LNmGCR1_ISLEW_RCTL | LNmGCR1_OSLEW_RCTL;
+	gcr1 |= FIELD_PREP(LNmGCR1_REIDL_TH, params->reidl_th);
+	gcr1 |= FIELD_PREP(LNmGCR1_REIDL_EX_SEL, params->reidl_ex & 3);
+	gcr1 |= FIELD_PREP(LNmGCR1_REIDL_ET_SEL, params->reidl_et & 3);
+	gcr1 |= FIELD_PREP(LNmGCR1_REIDL_EX_MSB, params->reidl_ex >> 2);
+	gcr1 |= FIELD_PREP(LNmGCR1_REIDL_ET_MSB, params->reidl_et >> 2);
+	gcr1 |= FIELD_PREP(LNmGCR1_TRSTDIR,
+			   group->first_lane > group->last_lane);
+	gcr1 |= FIELD_PREP(LNmGCR1_ISLEW_RCTL, params->slew);
+	gcr1 |= FIELD_PREP(LNmGCR1_OSLEW_RCTL, params->slew);
+
+	recr0_mask |= LNmRECR0_GK2OVD | LNmRECR0_GK3OVD;
+	recr0_mask |= LNmRECR0_GK2OVD_EN | LNmRECR0_GK3OVD_EN;
+	recr0_mask |= LNmRECR0_BASE_WAND | LNmRECR0_OSETOVD;
+	if (params->gain) {
+		recr0 |= FIELD_PREP(LNmRECR0_GK2OVD, params->gain);
+		recr0 |= FIELD_PREP(LNmRECR0_GK3OVD, params->gain);
+		recr0 |= LNmRECR0_GK2OVD_EN | LNmRECR0_GK3OVD_EN;
+	}
+	recr0 |= FIELD_PREP(LNmRECR0_BASE_WAND, params->baseline_wander);
+	recr0 |= FIELD_PREP(LNmRECR0_OSETOVD, params->offset_override);
+
+	tecr0_mask |= LNmTECR0_TEQ_TYPE;
+	tecr0_mask |= LNmTECR0_SGN_PREQ | LNmTECR0_RATIO_PREQ;
+	tecr0_mask |= LNmTECR0_SGN_POST1Q | LNmTECR0_RATIO_PST1Q;
+	tecr0_mask |= LNmTECR0_ADPT_EQ | LNmTECR0_AMP_RED;
+	tecr0 |= FIELD_PREP(LNmTECR0_TEQ_TYPE, params->teq);
+	if (params->preq_ratio) {
+		tecr0 |= FIELD_PREP(LNmTECR0_SGN_PREQ, 1);
+		tecr0 |= FIELD_PREP(LNmTECR0_RATIO_PREQ, params->preq_ratio);
+	}
+	if (params->postq_ratio) {
+		tecr0 |= FIELD_PREP(LNmTECR0_SGN_POST1Q, 1);
+		tecr0 |= FIELD_PREP(LNmTECR0_RATIO_PST1Q, params->postq_ratio);
+	}
+	tecr0 |= FIELD_PREP(LNmTECR0_ADPT_EQ, params->adpt_eq);
+	tecr0 |= FIELD_PREP(LNmTECR0_AMP_RED, params->amp_red);
+
+	mutex_lock(&serdes->lock);
+
+	/* Disable the old controller */
+	if (old_mode) {
+		tmp = qs_read(serdes, PCCRn(old_mode->pccr));
+		tmp = qs_proto_mode_prep(old_mode, tmp, 0);
+		qs_write(serdes, tmp, PCCRn(old_mode->pccr));
+
+		if (old_mode->protos & PROTO_MASK(SGMII)) {
+			tmp = qs_read(serdes, SGMIIaCR1(old_mode->idx));
+			tmp &= SGMIIaCR1_SGPCS_EN;
+			qs_write(serdes, tmp, SGMIIaCR1(old_mode->idx));
+		}
+	}
+
+	for_each_lane_reverse(i, group) {
+		tmp = qs_read(serdes, LNmGCR0(i));
+		tmp &= ~(LNmGCR0_RRST_B | LNmGCR0_TRST_B);
+		qs_write(serdes, tmp, LNmGCR0(i));
+		ndelay(50);
+
+		tmp &= ~gcr0_mask;
+		tmp |= gcr0;
+		tmp |= FIELD_PREP(LNmGCR0_FIRST_LANE, i == group->first_lane);
+		qs_write(serdes, tmp, LNmGCR0(i));
+
+		tmp = qs_read(serdes, LNmGCR1(i));
+		tmp &= ~gcr1_mask;
+		tmp |= gcr1;
+		qs_write(serdes, tmp, LNmGCR1(i));
+
+		tmp = qs_read(serdes, LNmRECR0(i));
+		tmp &= ~recr0_mask;
+		tmp |= recr0;
+		qs_write(serdes, tmp, LNmRECR0(i));
+
+		tmp = qs_read(serdes, LNmTECR0(i));
+		tmp &= ~tecr0_mask;
+		tmp |= tecr0;
+		qs_write(serdes, tmp, LNmTECR0(i));
+
+		tmp = qs_read(serdes, LNmTTLCR0(i));
+		tmp &= ~LNmTTLCR0_FLT_SEL;
+		tmp |= FIELD_PREP(LNmTTLCR0_FLT_SEL, params->flt_sel);
+		qs_write(serdes, tmp, LNmTTLCR0(i));
+
+		ndelay(120);
+		tmp = qs_read(serdes, LNmGCR0(i));
+		tmp |= LNmGCR0_RRST_B | LNmGCR0_TRST_B;
+		qs_write(serdes, tmp, LNmGCR0(i));
+	}
+
+	if (proto == QS_PROTO_1000BASEKX) {
+		/* FIXME: this races with clock updates */
+		tmp = qs_read(serdes, PLLaCR0(pll));
+		tmp &= ~PLLaCR0_DLYDIV_SEL;
+		tmp |= FIELD_PREP(PLLaCR0_DLYDIV_SEL, 1);
+		qs_write(serdes, tmp, PLLaCR0(pll));
+	}
+
+	/* Enable the new controller */
+	tmp = qs_read(serdes, PCCRn(new_mode->pccr));
+	tmp = qs_proto_mode_prep(new_mode, tmp, new_mode->cfg);
+	if (new_mode->protos & PROTO_MASK(1000BASEKX)) {
+		if (new_mode->pccr == 8) {
+			mask = PCCR8_SGMIIa_KX(new_mode->idx);
+		} else {
+			dev_err(&phy->dev, "PCCR%X doesn't have a KX bit\n",
+				new_mode->pccr);
+			mask = 0;
+		}
+
+		if (proto == QS_PROTO_1000BASEKX)
+			tmp |= mask;
+		else
+			tmp &= ~mask;
+	}
+	qs_write(serdes, tmp, PCCRn(new_mode->pccr));
+
+	if (new_mode->protos & PROTO_MASK(SGMII)) {
+		tmp = qs_read(serdes, SGMIIaCR1(new_mode->idx));
+		tmp |= SGMIIaCR1_SGPCS_EN;
+		qs_write(serdes, tmp, SGMIIaCR1(new_mode->idx));
+	}
+
+	mutex_unlock(&serdes->lock);
+
+	group->proto = proto;
+	dev_dbg(&phy->dev, "set mode to %s on lanes %u to %u\n",
+		qs_proto_str[proto], group->first_lane, group->last_lane);
+	return 0;
+}
+
+static void qs_release(struct phy *phy)
+{
+	struct qs_group *group = phy_get_drvdata(phy);
+	struct qs_priv *serdes = group->serdes;
+
+	mutex_lock(&serdes->lock);
+	if (--group->users) {
+		mutex_unlock(&serdes->lock);
+		return;
+	}
+	list_del(&group->groups);
+	mutex_unlock(&serdes->lock);
+
+	phy_destroy(phy);
+	kfree(group);
+}
+
+static const struct phy_ops qs_phy_ops = {
+	.init = qs_init,
+	.exit = qs_exit,
+	.power_on = qs_power_on,
+	.power_off = qs_power_off,
+	.set_mode = qs_set_mode,
+	.validate = qs_validate,
+	.release = qs_release,
+	.owner = THIS_MODULE,
+};
+
+static struct phy *qs_xlate(struct device *dev, struct of_phandle_args *args)
+{
+	struct phy *phy;
+	struct list_head *head;
+	struct qs_group *group;
+	struct qs_priv *serdes = dev_get_drvdata(dev);
+
+	if (args->args_count != 2)
+		return ERR_PTR(-EINVAL);
+
+	mutex_lock(&serdes->lock);
+
+	/* Look for an existing group */
+	list_for_each(head, &serdes->groups) {
+		group = container_of(head, struct qs_group, groups);
+		if (group->first_lane == args->args[0] &&
+		    group->last_lane == args->args[1]) {
+			group->users++;
+			return group->phy;
+		}
+	}
+
+	/* None found, create our own */
+	group = kzalloc(sizeof(*group), GFP_KERNEL);
+	if (!group) {
+		mutex_unlock(&serdes->lock);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	group->serdes = serdes;
+	group->first_lane = args->args[0];
+	group->last_lane = args->args[1];
+	group->users = 1;
+	phy = phy_create(dev, NULL, &qs_phy_ops);
+	if (IS_ERR(phy)) {
+		kfree(group);
+	} else {
+		group->phy = phy;
+		phy_set_drvdata(phy, group);
+		list_add(&group->groups, &serdes->groups);
+	}
+
+	mutex_unlock(&serdes->lock);
+	return phy;
+}
+
+static int qs_probe(struct platform_device *pdev)
+{
+	bool grabbed_clocks = false;
+	int i, ret;
+	struct device *dev = &pdev->dev;
+	struct qs_priv *serdes;
+	struct regmap_config regmap_config = {};
+	const struct qs_conf *conf;
+	struct resource *res;
+	void __iomem *base;
+
+	serdes = devm_kzalloc(dev, sizeof(*serdes), GFP_KERNEL);
+	if (!serdes)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, serdes);
+	mutex_init(&serdes->lock);
+	INIT_LIST_HEAD(&serdes->groups);
+	serdes->dev = dev;
+
+	base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
+		dev_err_probe(dev, ret, "could not get/map registers\n");
+		return ret;
+	}
+
+	conf = device_get_match_data(dev);
+	serdes->conf = conf;
+	regmap_config.reg_bits = 32;
+	regmap_config.reg_stride = 4;
+	regmap_config.val_bits = 32;
+	regmap_config.val_format_endian = conf->endian;
+	regmap_config.max_register = res->end - res->start;
+	regmap_config.disable_locking = true;
+	serdes->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+	if (IS_ERR(serdes->regmap)) {
+		ret = PTR_ERR(serdes->regmap);
+		dev_err_probe(dev, ret, "could not create regmap\n");
+		return ret;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(serdes->ref); i++) {
+		static const char fmt[] = "ref%d";
+		char name[sizeof(fmt)];
+
+		snprintf(name, sizeof(name), fmt, i);
+		serdes->ref[i] = devm_clk_get(dev, name);
+		if (IS_ERR(serdes->ref[i])) {
+			ret = PTR_ERR(serdes->ref[i]);
+			dev_err_probe(dev, ret, "could not get %s\n", name);
+			return ret;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(serdes->pll); i++) {
+		static const char fmt[] = "%s.pll%d";
+		char *name;
+		const struct clk_hw *ref_hw[] = {
+			__clk_get_hw(serdes->ref[i]),
+		};
+		size_t len;
+		struct clk_init_data init = {};
+
+		len = snprintf(NULL, 0, fmt, pdev->name, i);
+		name = devm_kzalloc(dev, len + 1, GFP_KERNEL);
+		if (!name)
+			return -ENOMEM;
+
+		snprintf(name, len + 1, fmt, pdev->name, i);
+		init.name = name;
+		init.ops = &qs_pll_clk_ops;
+		init.parent_hws = ref_hw;
+		init.num_parents = 1;
+		init.flags = CLK_SET_RATE_GATE | CLK_GET_RATE_NOCACHE;
+		init.flags |= CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE;
+
+		serdes->pll[i].hw.init = &init;
+		serdes->pll[i].serdes = serdes;
+		serdes->pll[i].idx = i;
+		ret = devm_clk_hw_register(dev, &serdes->pll[i].hw);
+		if (ret) {
+			dev_err_probe(dev, ret, "could not register %s\n",
+				      name);
+			return ret;
+		}
+	}
+
+	/* Deselect anything configured by the RCW/bootloader */
+	for (i = 0; i < conf->mode_count; i++) {
+		const struct qs_mode *mode = &conf->modes[i];
+		u32 pccr = qs_read(serdes, PCCRn(mode->pccr));
+
+		if (qs_proto_mode_get(mode, pccr) == mode->cfg) {
+			if (mode->protos & UNSUPPORTED_PROTOS) {
+				/* Don't mess with modes we don't support */
+				serdes->used_lanes |= mode->lanes;
+				if (grabbed_clocks)
+					continue;
+
+				grabbed_clocks = true;
+				clk_prepare_enable(serdes->pll[0].hw.clk);
+				clk_prepare_enable(serdes->pll[1].hw.clk);
+				clk_rate_exclusive_get(serdes->pll[0].hw.clk);
+				clk_rate_exclusive_get(serdes->pll[1].hw.clk);
+			} else {
+				/* Otherwise, clear out the existing config */
+				pccr = qs_proto_mode_prep(mode, pccr, 0);
+				qs_write(serdes, pccr, PCCRn(mode->pccr));
+			}
+		}
+	}
+
+	/* TODO: clear SGMIIaCR1 */
+
+	/* TODO: power off unused lanes */
+
+	ret = PTR_ERR_OR_ZERO(devm_of_phy_provider_register(dev, qs_xlate));
+	if (ret)
+		dev_err_probe(dev, ret, "could not register phy provider\n");
+	else
+		dev_info(dev, "probed with %d lanes\n", conf->lanes);
+	return ret;
+}
+
+/*
+ * XXX: For SerDes1, lane A uses pins SD1_RX3_P/N! That is, the lane numbers
+ * and pin numbers are _reversed_. In addition, the PCCR documentation is
+ * _inconsistent_ in its usage of these terms!
+ *
+ * PCCR "Lane 0" refers to...
+ * ==== =====================
+ *    0 Lane A
+ *    2 Lane A
+ *    8 Lane A
+ *    9 Lane A
+ *    B Lane D!
+ */
+static const struct qs_mode ls1046a_modes1[] = {
+	CONF_SINGLE(1, PCIE, 0x0, 1, 0b001), /* PCIe.1 */
+	CONF_1000BASEKX(0, 0x8, 0, 0b001), /* SGMII.6 */
+	CONF_SGMII25KX(1, 0x8, 1, 0b001), /* SGMII.5 */
+	CONF_SGMII25KX(2, 0x8, 2, 0b001), /* SGMII.10 */
+	CONF_SGMII25KX(3, 0x8, 3, 0b001), /* SGMII.9 */
+	CONF_SINGLE(1, QSGMII, 0x9, 2, 0b001), /* QSGMII.6,5,10,1 */
+	CONF_XFI(2, 0xB, 0, 0b010), /* XFI.10 */
+	CONF_XFI(3, 0xB, 1, 0b001), /* XFI.9 */
+};
+
+static const struct qs_conf ls1046a_conf1 = {
+	.modes = ls1046a_modes1,
+	.mode_count = ARRAY_SIZE(ls1046a_modes1),
+	.lanes = 4,
+	.endian = REGMAP_ENDIAN_BIG,
+};
+
+static const struct qs_mode ls1046a_modes2[] = {
+	CONF_SINGLE(0, PCIE, 0x0, 0, 0b001), /* PCIe.1 x1 */
+	CONF(GENMASK(3, 0), PROTO_MASK(PCIE), 0x0, 0, 0b011), /* PCIe.1 x4 */
+	CONF_SINGLE(2, PCIE, 0x0, 2, 0b001), /* PCIe.2 x1 */
+	CONF(GENMASK(3, 2), PROTO_MASK(PCIE), 0x0, 2, 0b010), /* PCIe.3 x2 */
+	CONF_SINGLE(3, PCIE, 0x0, 2, 0b011), /* PCIe.3 x1 */
+	CONF_SINGLE(3, SATA, 0x2, 0, 0b001), /* SATA */
+	CONF_1000BASEKX(1, 0x8, 1, 0b001), /* SGMII.2 */
+};
+
+static const struct qs_conf ls1046a_conf2 = {
+	.modes = ls1046a_modes2,
+	.mode_count = ARRAY_SIZE(ls1046a_modes2),
+	.lanes = 4,
+	.endian = REGMAP_ENDIAN_BIG,
+};
+
+static const struct of_device_id qs_of_match[] = {
+	{ .compatible = "fsl,ls1046a-serdes-1", .data = &ls1046a_conf1 },
+	{ .compatible = "fsl,ls1046a-serdes-2", .data = &ls1046a_conf2 },
+};
+MODULE_DEVICE_TABLE(of, qs_of_match);
+
+static struct platform_driver qs_driver = {
+	.probe = qs_probe,
+	.driver = {
+		.name = "qoriq_serdes",
+		.of_match_table = qs_of_match,
+	},
+};
+module_platform_driver(qs_driver);
+
+MODULE_AUTHOR("Sean Anderson <sean.anderson@seco.com>");
+MODULE_DESCRIPTION("QorIQ SerDes driver");
+MODULE_LICENSE("GPL");
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 04/28] net: fman: Convert to SPDX identifiers
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (2 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 05/28] net: fman: Don't pass comm_mode to enable/disable Sean Anderson
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Camelia Groza

This converts the license text of files in the fman directory to use
SPDX license identifiers instead.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Acked-by: Camelia Groza <camelia.groza@nxp.com>
Tested-by: Camelia Groza <camelia.groza@nxp.com>
---

 drivers/net/ethernet/freescale/fman/fman.c    | 31 ++----------------
 drivers/net/ethernet/freescale/fman/fman.h    | 31 ++----------------
 .../net/ethernet/freescale/fman/fman_dtsec.c  | 31 ++----------------
 .../net/ethernet/freescale/fman/fman_dtsec.h  | 31 ++----------------
 .../net/ethernet/freescale/fman/fman_keygen.c | 29 +----------------
 .../net/ethernet/freescale/fman/fman_keygen.h | 29 +----------------
 .../net/ethernet/freescale/fman/fman_memac.c  | 31 ++----------------
 .../net/ethernet/freescale/fman/fman_memac.h  | 31 ++----------------
 .../net/ethernet/freescale/fman/fman_muram.c  | 31 ++----------------
 .../net/ethernet/freescale/fman/fman_muram.h  | 32 ++-----------------
 .../net/ethernet/freescale/fman/fman_port.c   | 29 +----------------
 .../net/ethernet/freescale/fman/fman_port.h   | 29 +----------------
 drivers/net/ethernet/freescale/fman/fman_sp.c | 29 +----------------
 drivers/net/ethernet/freescale/fman/fman_sp.h | 28 +---------------
 .../net/ethernet/freescale/fman/fman_tgec.c   | 31 ++----------------
 .../net/ethernet/freescale/fman/fman_tgec.h   | 31 ++----------------
 drivers/net/ethernet/freescale/fman/mac.c     | 32 ++-----------------
 drivers/net/ethernet/freescale/fman/mac.h     | 32 ++-----------------
 18 files changed, 33 insertions(+), 515 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c
index 8f0db61cb1f6..9d85fb136e34 100644
--- a/drivers/net/ethernet/freescale/fman/fman.c
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -1,34 +1,7 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  * Copyright 2020 NXP
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/net/ethernet/freescale/fman/fman.h b/drivers/net/ethernet/freescale/fman/fman.h
index f2ede1360f03..2ea575a46675 100644
--- a/drivers/net/ethernet/freescale/fman/fman.h
+++ b/drivers/net/ethernet/freescale/fman/fman.h
@@ -1,34 +1,7 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  * Copyright 2020 NXP
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef __FM_H
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 1950a8936bc0..a39d57347d59 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.h b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
index 68512c3bd6e5..3c26b97f8ced 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #ifndef __DTSEC_H
diff --git a/drivers/net/ethernet/freescale/fman/fman_keygen.c b/drivers/net/ethernet/freescale/fman/fman_keygen.c
index e1bdfed16134..e73f6ef3c6ee 100644
--- a/drivers/net/ethernet/freescale/fman/fman_keygen.c
+++ b/drivers/net/ethernet/freescale/fman/fman_keygen.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
  * Copyright 2017 NXP
- *
- * 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 NXP 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 NXP ``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 NXP BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/net/ethernet/freescale/fman/fman_keygen.h b/drivers/net/ethernet/freescale/fman/fman_keygen.h
index c4640de3f4cb..2cb0df453074 100644
--- a/drivers/net/ethernet/freescale/fman/fman_keygen.h
+++ b/drivers/net/ethernet/freescale/fman/fman_keygen.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
  * Copyright 2017 NXP
- *
- * 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 NXP 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 NXP ``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 NXP 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 __KEYGEN_H
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 2216b7f51d26..d47e5d282143 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.h b/drivers/net/ethernet/freescale/fman/fman_memac.h
index 3820f7a22983..702df2aa43f9 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #ifndef __MEMAC_H
diff --git a/drivers/net/ethernet/freescale/fman/fman_muram.c b/drivers/net/ethernet/freescale/fman/fman_muram.c
index 7ad317e622bc..f557d68e5b76 100644
--- a/drivers/net/ethernet/freescale/fman/fman_muram.c
+++ b/drivers/net/ethernet/freescale/fman/fman_muram.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #include "fman_muram.h"
diff --git a/drivers/net/ethernet/freescale/fman/fman_muram.h b/drivers/net/ethernet/freescale/fman/fman_muram.h
index 453bf849eee1..3643af61bae2 100644
--- a/drivers/net/ethernet/freescale/fman/fman_muram.h
+++ b/drivers/net/ethernet/freescale/fman/fman_muram.h
@@ -1,34 +1,8 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
+
 #ifndef __FM_MURAM_EXT
 #define __FM_MURAM_EXT
 
diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c
index 4c9d05c45c03..ab90fe2bee5e 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.c
+++ b/drivers/net/ethernet/freescale/fman/fman_port.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
  * Copyright 2008 - 2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/net/ethernet/freescale/fman/fman_port.h b/drivers/net/ethernet/freescale/fman/fman_port.h
index 82f12661a46d..4917fe8f0617 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.h
+++ b/drivers/net/ethernet/freescale/fman/fman_port.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
  * Copyright 2008 - 2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef __FMAN_PORT_H
diff --git a/drivers/net/ethernet/freescale/fman/fman_sp.c b/drivers/net/ethernet/freescale/fman/fman_sp.c
index 248f5bcca468..0fac60aa5283 100644
--- a/drivers/net/ethernet/freescale/fman/fman_sp.c
+++ b/drivers/net/ethernet/freescale/fman/fman_sp.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
  * Copyright 2008 - 2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "fman_sp.h"
diff --git a/drivers/net/ethernet/freescale/fman/fman_sp.h b/drivers/net/ethernet/freescale/fman/fman_sp.h
index 820b7f63088f..a62dd21c81f1 100644
--- a/drivers/net/ethernet/freescale/fman/fman_sp.h
+++ b/drivers/net/ethernet/freescale/fman/fman_sp.h
@@ -1,32 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
  * Copyright 2008 - 2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *	 notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *	 notice, this list of conditions and the following disclaimer in the
- *	 documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *	 names of its contributors may be used to endorse or promote products
- *	 derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef __FM_SP_H
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index 311c1906e044..a3c6576dd99d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.h b/drivers/net/ethernet/freescale/fman/fman_tgec.h
index b28b20b26148..8df90054495c 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #ifndef __TGEC_H
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 39ae965cd4f6..2b3c6cbefef6 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -1,32 +1,6 @@
-/* Copyright 2008-2015 Freescale Semiconductor, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *	 notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *	 notice, this list of conditions and the following disclaimer in the
- *	 documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *	 names of its contributors may be used to endorse or promote products
- *	 derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index daa285a9b8b2..909faf5fa2fe 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -1,32 +1,6 @@
-/* Copyright 2008-2015 Freescale Semiconductor, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *	 notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *	 notice, this list of conditions and the following disclaimer in the
- *	 documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *	 names of its contributors may be used to endorse or promote products
- *	 derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #ifndef __MAC_H
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 05/28] net: fman: Don't pass comm_mode to enable/disable
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (3 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 04/28] net: fman: Convert to SPDX identifiers Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 06/28] net: fman: Store en/disable in mac_device instead of mac_priv_s Sean Anderson
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Camelia Groza

mac_priv_s->enable() and ->disable() are always called with
a comm_mode of COMM_MODE_RX_AND_TX. Remove this parameter, and refactor
the macs appropriately.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Acked-by: Camelia Groza <camelia.groza@nxp.com>
Tested-by: Camelia Groza <camelia.groza@nxp.com>
---

 .../net/ethernet/freescale/fman/fman_dtsec.c  | 20 ++++++-------------
 .../net/ethernet/freescale/fman/fman_dtsec.h  |  4 ++--
 .../net/ethernet/freescale/fman/fman_memac.c  | 16 ++++-----------
 .../net/ethernet/freescale/fman/fman_memac.h  |  4 ++--
 .../net/ethernet/freescale/fman/fman_tgec.c   | 14 ++++---------
 .../net/ethernet/freescale/fman/fman_tgec.h   |  4 ++--
 drivers/net/ethernet/freescale/fman/mac.c     |  8 ++++----
 7 files changed, 24 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index a39d57347d59..167843941fa4 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -879,7 +879,7 @@ static void graceful_stop(struct fman_mac *dtsec, enum comm_mode mode)
 	}
 }
 
-int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode)
+int dtsec_enable(struct fman_mac *dtsec)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 tmp;
@@ -889,20 +889,16 @@ int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode)
 
 	/* Enable */
 	tmp = ioread32be(&regs->maccfg1);
-	if (mode & COMM_MODE_RX)
-		tmp |= MACCFG1_RX_EN;
-	if (mode & COMM_MODE_TX)
-		tmp |= MACCFG1_TX_EN;
-
+	tmp |= MACCFG1_RX_EN | MACCFG1_TX_EN;
 	iowrite32be(tmp, &regs->maccfg1);
 
 	/* Graceful start - clear the graceful Rx/Tx stop bit */
-	graceful_start(dtsec, mode);
+	graceful_start(dtsec, COMM_MODE_RX_AND_TX);
 
 	return 0;
 }
 
-int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode)
+int dtsec_disable(struct fman_mac *dtsec)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 tmp;
@@ -911,14 +907,10 @@ int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode)
 		return -EINVAL;
 
 	/* Graceful stop - Assert the graceful Rx/Tx stop bit */
-	graceful_stop(dtsec, mode);
+	graceful_stop(dtsec, COMM_MODE_RX_AND_TX);
 
 	tmp = ioread32be(&regs->maccfg1);
-	if (mode & COMM_MODE_RX)
-		tmp &= ~MACCFG1_RX_EN;
-	if (mode & COMM_MODE_TX)
-		tmp &= ~MACCFG1_TX_EN;
-
+	tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
 	iowrite32be(tmp, &regs->maccfg1);
 
 	return 0;
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.h b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
index 3c26b97f8ced..f072cdc560ba 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
@@ -16,8 +16,8 @@ int dtsec_adjust_link(struct fman_mac *dtsec,
 int dtsec_restart_autoneg(struct fman_mac *dtsec);
 int dtsec_cfg_max_frame_len(struct fman_mac *dtsec, u16 new_val);
 int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val);
-int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode);
-int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode);
+int dtsec_enable(struct fman_mac *dtsec);
+int dtsec_disable(struct fman_mac *dtsec);
 int dtsec_init(struct fman_mac *dtsec);
 int dtsec_free(struct fman_mac *dtsec);
 int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en);
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index d47e5d282143..c34da49aed31 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -685,7 +685,7 @@ static bool is_init_done(struct memac_cfg *memac_drv_params)
 	return false;
 }
 
-int memac_enable(struct fman_mac *memac, enum comm_mode mode)
+int memac_enable(struct fman_mac *memac)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
@@ -694,17 +694,13 @@ int memac_enable(struct fman_mac *memac, enum comm_mode mode)
 		return -EINVAL;
 
 	tmp = ioread32be(&regs->command_config);
-	if (mode & COMM_MODE_RX)
-		tmp |= CMD_CFG_RX_EN;
-	if (mode & COMM_MODE_TX)
-		tmp |= CMD_CFG_TX_EN;
-
+	tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN;
 	iowrite32be(tmp, &regs->command_config);
 
 	return 0;
 }
 
-int memac_disable(struct fman_mac *memac, enum comm_mode mode)
+int memac_disable(struct fman_mac *memac)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
@@ -713,11 +709,7 @@ int memac_disable(struct fman_mac *memac, enum comm_mode mode)
 		return -EINVAL;
 
 	tmp = ioread32be(&regs->command_config);
-	if (mode & COMM_MODE_RX)
-		tmp &= ~CMD_CFG_RX_EN;
-	if (mode & COMM_MODE_TX)
-		tmp &= ~CMD_CFG_TX_EN;
-
+	tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN);
 	iowrite32be(tmp, &regs->command_config);
 
 	return 0;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.h b/drivers/net/ethernet/freescale/fman/fman_memac.h
index 702df2aa43f9..535ecd2b2ab4 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.h
@@ -19,8 +19,8 @@ int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val);
 int memac_cfg_reset_on_init(struct fman_mac *memac, bool enable);
 int memac_cfg_fixed_link(struct fman_mac *memac,
 			 struct fixed_phy_status *fixed_link);
-int memac_enable(struct fman_mac *memac, enum comm_mode mode);
-int memac_disable(struct fman_mac *memac, enum comm_mode mode);
+int memac_enable(struct fman_mac *memac);
+int memac_disable(struct fman_mac *memac);
 int memac_init(struct fman_mac *memac);
 int memac_free(struct fman_mac *memac);
 int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en);
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index a3c6576dd99d..2b38d22c863d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -392,7 +392,7 @@ static bool is_init_done(struct tgec_cfg *cfg)
 	return false;
 }
 
-int tgec_enable(struct fman_mac *tgec, enum comm_mode mode)
+int tgec_enable(struct fman_mac *tgec)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 	u32 tmp;
@@ -401,16 +401,13 @@ int tgec_enable(struct fman_mac *tgec, enum comm_mode mode)
 		return -EINVAL;
 
 	tmp = ioread32be(&regs->command_config);
-	if (mode & COMM_MODE_RX)
-		tmp |= CMD_CFG_RX_EN;
-	if (mode & COMM_MODE_TX)
-		tmp |= CMD_CFG_TX_EN;
+	tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN;
 	iowrite32be(tmp, &regs->command_config);
 
 	return 0;
 }
 
-int tgec_disable(struct fman_mac *tgec, enum comm_mode mode)
+int tgec_disable(struct fman_mac *tgec)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 	u32 tmp;
@@ -419,10 +416,7 @@ int tgec_disable(struct fman_mac *tgec, enum comm_mode mode)
 		return -EINVAL;
 
 	tmp = ioread32be(&regs->command_config);
-	if (mode & COMM_MODE_RX)
-		tmp &= ~CMD_CFG_RX_EN;
-	if (mode & COMM_MODE_TX)
-		tmp &= ~CMD_CFG_TX_EN;
+	tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN);
 	iowrite32be(tmp, &regs->command_config);
 
 	return 0;
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.h b/drivers/net/ethernet/freescale/fman/fman_tgec.h
index 8df90054495c..5b256758cbec 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.h
@@ -12,8 +12,8 @@ struct fman_mac *tgec_config(struct fman_mac_params *params);
 int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val);
 int tgec_modify_mac_address(struct fman_mac *tgec, const enet_addr_t *enet_addr);
 int tgec_cfg_max_frame_len(struct fman_mac *tgec, u16 new_val);
-int tgec_enable(struct fman_mac *tgec, enum comm_mode mode);
-int tgec_disable(struct fman_mac *tgec, enum comm_mode mode);
+int tgec_enable(struct fman_mac *tgec);
+int tgec_disable(struct fman_mac *tgec);
 int tgec_init(struct fman_mac *tgec);
 int tgec_free(struct fman_mac *tgec);
 int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en);
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 2b3c6cbefef6..a8d521760ffc 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -40,8 +40,8 @@ struct mac_priv_s {
 	u16				speed;
 	u16				max_speed;
 
-	int (*enable)(struct fman_mac *mac_dev, enum comm_mode mode);
-	int (*disable)(struct fman_mac *mac_dev, enum comm_mode mode);
+	int (*enable)(struct fman_mac *mac_dev);
+	int (*disable)(struct fman_mac *mac_dev);
 };
 
 struct mac_address {
@@ -247,7 +247,7 @@ static int start(struct mac_device *mac_dev)
 	struct phy_device *phy_dev = mac_dev->phy_dev;
 	struct mac_priv_s *priv = mac_dev->priv;
 
-	err = priv->enable(mac_dev->fman_mac, COMM_MODE_RX_AND_TX);
+	err = priv->enable(mac_dev->fman_mac);
 	if (!err && phy_dev)
 		phy_start(phy_dev);
 
@@ -261,7 +261,7 @@ static int stop(struct mac_device *mac_dev)
 	if (mac_dev->phy_dev)
 		phy_stop(mac_dev->phy_dev);
 
-	return priv->disable(mac_dev->fman_mac, COMM_MODE_RX_AND_TX);
+	return priv->disable(mac_dev->fman_mac);
 }
 
 static int set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 06/28] net: fman: Store en/disable in mac_device instead of mac_priv_s
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (4 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 05/28] net: fman: Don't pass comm_mode to enable/disable Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 07/28] net: fman: dtsec: Always gracefully stop/start Sean Anderson
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Camelia Groza

All macs use the same start/stop functions. The actual mac-specific code
lives in enable/disable. Move these functions to an appropriate struct,
and inline the phy enable/disable calls to the caller of start/stop.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Acked-by: Camelia Groza <camelia.groza@nxp.com>
Tested-by: Camelia Groza <camelia.groza@nxp.com>
---

 .../net/ethernet/freescale/dpaa/dpaa_eth.c    | 11 +++--
 drivers/net/ethernet/freescale/fman/mac.c     | 44 +++----------------
 drivers/net/ethernet/freescale/fman/mac.h     |  4 +-
 3 files changed, 15 insertions(+), 44 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 45634579adb6..a548598b2e2d 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -288,9 +288,11 @@ static int dpaa_stop(struct net_device *net_dev)
 	 */
 	msleep(200);
 
-	err = mac_dev->stop(mac_dev);
+	if (mac_dev->phy_dev)
+		phy_stop(mac_dev->phy_dev);
+	err = mac_dev->disable(mac_dev->fman_mac);
 	if (err < 0)
-		netif_err(priv, ifdown, net_dev, "mac_dev->stop() = %d\n",
+		netif_err(priv, ifdown, net_dev, "mac_dev->disable() = %d\n",
 			  err);
 
 	for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
@@ -2942,11 +2944,12 @@ static int dpaa_open(struct net_device *net_dev)
 			goto mac_start_failed;
 	}
 
-	err = priv->mac_dev->start(mac_dev);
+	err = priv->mac_dev->enable(mac_dev->fman_mac);
 	if (err < 0) {
-		netif_err(priv, ifup, net_dev, "mac_dev->start() = %d\n", err);
+		netif_err(priv, ifup, net_dev, "mac_dev->enable() = %d\n", err);
 		goto mac_start_failed;
 	}
+	phy_start(priv->mac_dev->phy_dev);
 
 	netif_tx_start_all_queues(net_dev);
 
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index a8d521760ffc..6a4eaca83700 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -39,9 +39,6 @@ struct mac_priv_s {
 	struct fixed_phy_status		*fixed_link;
 	u16				speed;
 	u16				max_speed;
-
-	int (*enable)(struct fman_mac *mac_dev);
-	int (*disable)(struct fman_mac *mac_dev);
 };
 
 struct mac_address {
@@ -241,29 +238,6 @@ static int memac_initialization(struct mac_device *mac_dev)
 	return err;
 }
 
-static int start(struct mac_device *mac_dev)
-{
-	int	 err;
-	struct phy_device *phy_dev = mac_dev->phy_dev;
-	struct mac_priv_s *priv = mac_dev->priv;
-
-	err = priv->enable(mac_dev->fman_mac);
-	if (!err && phy_dev)
-		phy_start(phy_dev);
-
-	return err;
-}
-
-static int stop(struct mac_device *mac_dev)
-{
-	struct mac_priv_s *priv = mac_dev->priv;
-
-	if (mac_dev->phy_dev)
-		phy_stop(mac_dev->phy_dev);
-
-	return priv->disable(mac_dev->fman_mac);
-}
-
 static int set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
 {
 	struct mac_priv_s	*priv;
@@ -454,11 +428,9 @@ static void setup_dtsec(struct mac_device *mac_dev)
 	mac_dev->set_allmulti		= dtsec_set_allmulti;
 	mac_dev->set_tstamp		= dtsec_set_tstamp;
 	mac_dev->set_multi		= set_multi;
-	mac_dev->start			= start;
-	mac_dev->stop			= stop;
 	mac_dev->adjust_link            = adjust_link_dtsec;
-	mac_dev->priv->enable		= dtsec_enable;
-	mac_dev->priv->disable		= dtsec_disable;
+	mac_dev->enable			= dtsec_enable;
+	mac_dev->disable		= dtsec_disable;
 }
 
 static void setup_tgec(struct mac_device *mac_dev)
@@ -474,11 +446,9 @@ static void setup_tgec(struct mac_device *mac_dev)
 	mac_dev->set_allmulti		= tgec_set_allmulti;
 	mac_dev->set_tstamp		= tgec_set_tstamp;
 	mac_dev->set_multi		= set_multi;
-	mac_dev->start			= start;
-	mac_dev->stop			= stop;
 	mac_dev->adjust_link            = adjust_link_void;
-	mac_dev->priv->enable		= tgec_enable;
-	mac_dev->priv->disable		= tgec_disable;
+	mac_dev->enable			= tgec_enable;
+	mac_dev->disable		= tgec_disable;
 }
 
 static void setup_memac(struct mac_device *mac_dev)
@@ -494,11 +464,9 @@ static void setup_memac(struct mac_device *mac_dev)
 	mac_dev->set_allmulti		= memac_set_allmulti;
 	mac_dev->set_tstamp		= memac_set_tstamp;
 	mac_dev->set_multi		= set_multi;
-	mac_dev->start			= start;
-	mac_dev->stop			= stop;
 	mac_dev->adjust_link            = adjust_link_memac;
-	mac_dev->priv->enable		= memac_enable;
-	mac_dev->priv->disable		= memac_disable;
+	mac_dev->enable			= memac_enable;
+	mac_dev->disable		= memac_disable;
 }
 
 #define DTSEC_SUPPORTED \
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index 909faf5fa2fe..95f67b4efb61 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -36,8 +36,8 @@ struct mac_device {
 	bool allmulti;
 
 	int (*init)(struct mac_device *mac_dev);
-	int (*start)(struct mac_device *mac_dev);
-	int (*stop)(struct mac_device *mac_dev);
+	int (*enable)(struct fman_mac *mac_dev);
+	int (*disable)(struct fman_mac *mac_dev);
 	void (*adjust_link)(struct mac_device *mac_dev);
 	int (*set_promisc)(struct fman_mac *mac_dev, bool enable);
 	int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr);
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 07/28] net: fman: dtsec: Always gracefully stop/start
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (5 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 06/28] net: fman: Store en/disable in mac_device instead of mac_priv_s Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 08/28] net: fman: Get PCS node in per-mac init Sean Anderson
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Camelia Groza

There are two ways that GRS can be set: graceful_stop and dtsec_isr. It
is cleared by graceful_start. If it is already set before calling
graceful_stop, then that means that dtsec_isr set it. In that case, we
will not set GRS nor will we clear it (which seems like a bug?). For GTS
the logic is similar, except that there is no one else messing with this
bit (so we will always set and clear it). Simplify the logic by always
setting/clearing GRS/GTS. This is less racy that the previous behavior,
and ensures that we always end up clearing the bits. This can of course
clear GRS while dtsec_isr is waiting, but because we have already done
our own waiting it should be fine.

This is the last user of enum comm_mode, so remove it.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Acked-by: Camelia Groza <camelia.groza@nxp.com>
Tested-by: Camelia Groza <camelia.groza@nxp.com>
---
Changes since previous series:
- Fix unused variable warning in dtsec_modify_mac_address

 .../net/ethernet/freescale/fman/fman_dtsec.c  | 94 ++++++-------------
 .../net/ethernet/freescale/fman/fman_mac.h    | 10 --
 2 files changed, 30 insertions(+), 74 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 167843941fa4..7f4f3d797a8d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -833,49 +833,41 @@ int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val)
 	return 0;
 }
 
-static void graceful_start(struct fman_mac *dtsec, enum comm_mode mode)
+static void graceful_start(struct fman_mac *dtsec)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 
-	if (mode & COMM_MODE_TX)
-		iowrite32be(ioread32be(&regs->tctrl) &
-				~TCTRL_GTS, &regs->tctrl);
-	if (mode & COMM_MODE_RX)
-		iowrite32be(ioread32be(&regs->rctrl) &
-				~RCTRL_GRS, &regs->rctrl);
+	iowrite32be(ioread32be(&regs->tctrl) & ~TCTRL_GTS, &regs->tctrl);
+	iowrite32be(ioread32be(&regs->rctrl) & ~RCTRL_GRS, &regs->rctrl);
 }
 
-static void graceful_stop(struct fman_mac *dtsec, enum comm_mode mode)
+static void graceful_stop(struct fman_mac *dtsec)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 tmp;
 
 	/* Graceful stop - Assert the graceful Rx stop bit */
-	if (mode & COMM_MODE_RX) {
-		tmp = ioread32be(&regs->rctrl) | RCTRL_GRS;
-		iowrite32be(tmp, &regs->rctrl);
+	tmp = ioread32be(&regs->rctrl) | RCTRL_GRS;
+	iowrite32be(tmp, &regs->rctrl);
 
-		if (dtsec->fm_rev_info.major == 2) {
-			/* Workaround for dTSEC Errata A002 */
-			usleep_range(100, 200);
-		} else {
-			/* Workaround for dTSEC Errata A004839 */
-			usleep_range(10, 50);
-		}
+	if (dtsec->fm_rev_info.major == 2) {
+		/* Workaround for dTSEC Errata A002 */
+		usleep_range(100, 200);
+	} else {
+		/* Workaround for dTSEC Errata A004839 */
+		usleep_range(10, 50);
 	}
 
 	/* Graceful stop - Assert the graceful Tx stop bit */
-	if (mode & COMM_MODE_TX) {
-		if (dtsec->fm_rev_info.major == 2) {
-			/* dTSEC Errata A004: Do not use TCTRL[GTS]=1 */
-			pr_debug("GTS not supported due to DTSEC_A004 Errata.\n");
-		} else {
-			tmp = ioread32be(&regs->tctrl) | TCTRL_GTS;
-			iowrite32be(tmp, &regs->tctrl);
+	if (dtsec->fm_rev_info.major == 2) {
+		/* dTSEC Errata A004: Do not use TCTRL[GTS]=1 */
+		pr_debug("GTS not supported due to DTSEC_A004 Errata.\n");
+	} else {
+		tmp = ioread32be(&regs->tctrl) | TCTRL_GTS;
+		iowrite32be(tmp, &regs->tctrl);
 
-			/* Workaround for dTSEC Errata A0012, A0014 */
-			usleep_range(10, 50);
-		}
+		/* Workaround for dTSEC Errata A0012, A0014 */
+		usleep_range(10, 50);
 	}
 }
 
@@ -893,7 +885,7 @@ int dtsec_enable(struct fman_mac *dtsec)
 	iowrite32be(tmp, &regs->maccfg1);
 
 	/* Graceful start - clear the graceful Rx/Tx stop bit */
-	graceful_start(dtsec, COMM_MODE_RX_AND_TX);
+	graceful_start(dtsec);
 
 	return 0;
 }
@@ -907,7 +899,7 @@ int dtsec_disable(struct fman_mac *dtsec)
 		return -EINVAL;
 
 	/* Graceful stop - Assert the graceful Rx/Tx stop bit */
-	graceful_stop(dtsec, COMM_MODE_RX_AND_TX);
+	graceful_stop(dtsec);
 
 	tmp = ioread32be(&regs->maccfg1);
 	tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
@@ -921,18 +913,12 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
 			      u16 pause_time, u16 __maybe_unused thresh_time)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
-	enum comm_mode mode = COMM_MODE_NONE;
 	u32 ptv = 0;
 
 	if (!is_init_done(dtsec->dtsec_drv_param))
 		return -EINVAL;
 
-	if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
-		mode |= COMM_MODE_RX;
-	if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
-		mode |= COMM_MODE_TX;
-
-	graceful_stop(dtsec, mode);
+	graceful_stop(dtsec);
 
 	if (pause_time) {
 		/* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */
@@ -954,7 +940,7 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
 		iowrite32be(ioread32be(&regs->maccfg1) & ~MACCFG1_TX_FLOW,
 			    &regs->maccfg1);
 
-	graceful_start(dtsec, mode);
+	graceful_start(dtsec);
 
 	return 0;
 }
@@ -962,18 +948,12 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
 int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
-	enum comm_mode mode = COMM_MODE_NONE;
 	u32 tmp;
 
 	if (!is_init_done(dtsec->dtsec_drv_param))
 		return -EINVAL;
 
-	if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
-		mode |= COMM_MODE_RX;
-	if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
-		mode |= COMM_MODE_TX;
-
-	graceful_stop(dtsec, mode);
+	graceful_stop(dtsec);
 
 	tmp = ioread32be(&regs->maccfg1);
 	if (en)
@@ -982,25 +962,17 @@ int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
 		tmp &= ~MACCFG1_RX_FLOW;
 	iowrite32be(tmp, &regs->maccfg1);
 
-	graceful_start(dtsec, mode);
+	graceful_start(dtsec);
 
 	return 0;
 }
 
 int dtsec_modify_mac_address(struct fman_mac *dtsec, const enet_addr_t *enet_addr)
 {
-	struct dtsec_regs __iomem *regs = dtsec->regs;
-	enum comm_mode mode = COMM_MODE_NONE;
-
 	if (!is_init_done(dtsec->dtsec_drv_param))
 		return -EINVAL;
 
-	if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
-		mode |= COMM_MODE_RX;
-	if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
-		mode |= COMM_MODE_TX;
-
-	graceful_stop(dtsec, mode);
+	graceful_stop(dtsec);
 
 	/* Initialize MAC Station Address registers (1 & 2)
 	 * Station address have to be swapped (big endian to little endian
@@ -1008,7 +980,7 @@ int dtsec_modify_mac_address(struct fman_mac *dtsec, const enet_addr_t *enet_add
 	dtsec->addr = ENET_ADDR_TO_UINT64(*enet_addr);
 	set_mac_address(dtsec->regs, (const u8 *)(*enet_addr));
 
-	graceful_start(dtsec, mode);
+	graceful_start(dtsec);
 
 	return 0;
 }
@@ -1226,18 +1198,12 @@ int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val)
 int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
-	enum comm_mode mode = COMM_MODE_NONE;
 	u32 tmp;
 
 	if (!is_init_done(dtsec->dtsec_drv_param))
 		return -EINVAL;
 
-	if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
-		mode |= COMM_MODE_RX;
-	if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
-		mode |= COMM_MODE_TX;
-
-	graceful_stop(dtsec, mode);
+	graceful_stop(dtsec);
 
 	tmp = ioread32be(&regs->maccfg2);
 
@@ -1258,7 +1224,7 @@ int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
 		tmp &= ~DTSEC_ECNTRL_R100M;
 	iowrite32be(tmp, &regs->ecntrl);
 
-	graceful_start(dtsec, mode);
+	graceful_start(dtsec);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/freescale/fman/fman_mac.h b/drivers/net/ethernet/freescale/fman/fman_mac.h
index 19f327efdaff..418d1de85702 100644
--- a/drivers/net/ethernet/freescale/fman/fman_mac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_mac.h
@@ -75,16 +75,6 @@ typedef u8 enet_addr_t[ETH_ALEN];
 #define ETH_HASH_ENTRY_OBJ(ptr)	\
 	hlist_entry_safe(ptr, struct eth_hash_entry, node)
 
-/* Enumeration (bit flags) of communication modes (Transmit,
- * receive or both).
- */
-enum comm_mode {
-	COMM_MODE_NONE = 0,	/* No transmit/receive communication */
-	COMM_MODE_RX = 1,	/* Only receive communication */
-	COMM_MODE_TX = 2,	/* Only transmit communication */
-	COMM_MODE_RX_AND_TX = 3	/* Both transmit and receive communication */
-};
-
 /* FM MAC Exceptions */
 enum fman_mac_exceptions {
 	FM_MAC_EX_10G_MDIO_SCAN_EVENT = 0
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 08/28] net: fman: Get PCS node in per-mac init
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (6 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 07/28] net: fman: dtsec: Always gracefully stop/start Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 09/28] net: fman: Store initialization function in match data Sean Anderson
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

This moves the reading of the PCS property out of the generic probe and
into the mac-specific initialization function. This reduces the
mac-specific jobs done in the top-level probe function.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/net/ethernet/freescale/fman/mac.c | 19 +++++++++----------
 drivers/net/ethernet/freescale/fman/mac.h |  2 +-
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 6a4eaca83700..0af6f6c49284 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -32,7 +32,6 @@ struct mac_priv_s {
 	void __iomem			*vaddr;
 	u8				cell_index;
 	struct fman			*fman;
-	struct device_node		*internal_phy_node;
 	/* List of multicast addresses */
 	struct list_head		mc_addr_list;
 	struct platform_device		*eth_dev;
@@ -85,12 +84,12 @@ static int set_fman_mac_params(struct mac_device *mac_dev,
 	params->exception_cb	= mac_exception;
 	params->event_cb	= mac_exception;
 	params->dev_id		= mac_dev;
-	params->internal_phy_node = priv->internal_phy_node;
 
 	return 0;
 }
 
-static int tgec_initialization(struct mac_device *mac_dev)
+static int tgec_initialization(struct mac_device *mac_dev,
+			       struct device_node *mac_node)
 {
 	int err;
 	struct mac_priv_s	*priv;
@@ -138,7 +137,8 @@ static int tgec_initialization(struct mac_device *mac_dev)
 	return err;
 }
 
-static int dtsec_initialization(struct mac_device *mac_dev)
+static int dtsec_initialization(struct mac_device *mac_dev,
+				struct device_node *mac_node)
 {
 	int			err;
 	struct mac_priv_s	*priv;
@@ -150,6 +150,7 @@ static int dtsec_initialization(struct mac_device *mac_dev)
 	err = set_fman_mac_params(mac_dev, &params);
 	if (err)
 		goto _return;
+	params.internal_phy_node = of_parse_phandle(mac_node, "tbi-handle", 0);
 
 	mac_dev->fman_mac = dtsec_config(&params);
 	if (!mac_dev->fman_mac) {
@@ -190,7 +191,8 @@ static int dtsec_initialization(struct mac_device *mac_dev)
 	return err;
 }
 
-static int memac_initialization(struct mac_device *mac_dev)
+static int memac_initialization(struct mac_device *mac_dev,
+				struct device_node *mac_node)
 {
 	int			 err;
 	struct mac_priv_s	*priv;
@@ -201,6 +203,7 @@ static int memac_initialization(struct mac_device *mac_dev)
 	err = set_fman_mac_params(mac_dev, &params);
 	if (err)
 		goto _return;
+	params.internal_phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0);
 
 	if (priv->max_speed == SPEED_10000)
 		params.phy_if = PHY_INTERFACE_MODE_XGMII;
@@ -583,14 +586,10 @@ static int mac_probe(struct platform_device *_of_dev)
 
 	if (of_device_is_compatible(mac_node, "fsl,fman-dtsec")) {
 		setup_dtsec(mac_dev);
-		priv->internal_phy_node = of_parse_phandle(mac_node,
-							  "tbi-handle", 0);
 	} else if (of_device_is_compatible(mac_node, "fsl,fman-xgec")) {
 		setup_tgec(mac_dev);
 	} else if (of_device_is_compatible(mac_node, "fsl,fman-memac")) {
 		setup_memac(mac_dev);
-		priv->internal_phy_node = of_parse_phandle(mac_node,
-							  "pcsphy-handle", 0);
 	} else {
 		dev_err(dev, "MAC node (%pOF) contains unsupported MAC\n",
 			mac_node);
@@ -783,7 +782,7 @@ static int mac_probe(struct platform_device *_of_dev)
 		put_device(&phy->mdio.dev);
 	}
 
-	err = mac_dev->init(mac_dev);
+	err = mac_dev->init(mac_dev, mac_node);
 	if (err < 0) {
 		dev_err(dev, "mac_dev->init() = %d\n", err);
 		of_node_put(mac_dev->phy_node);
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index 95f67b4efb61..e4329c7d5001 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -35,7 +35,7 @@ struct mac_device {
 	bool promisc;
 	bool allmulti;
 
-	int (*init)(struct mac_device *mac_dev);
+	int (*init)(struct mac_device *mac_dev, struct device_node *mac_node);
 	int (*enable)(struct fman_mac *mac_dev);
 	int (*disable)(struct fman_mac *mac_dev);
 	void (*adjust_link)(struct mac_device *mac_dev);
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 09/28] net: fman: Store initialization function in match data
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (7 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 08/28] net: fman: Get PCS node in per-mac init Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 10/28] net: fman: Move struct dev to mac_device Sean Anderson
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

Instead of re-matching the compatible string in order to determine the
init function, just store it in the match data. This also move the setting
of the rest of the functions into init as well. To ensure everything
compiles correctly, we move them to the bottom of the file.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/net/ethernet/freescale/fman/mac.c | 356 ++++++++++------------
 drivers/net/ethernet/freescale/fman/mac.h |   1 -
 2 files changed, 165 insertions(+), 192 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 0af6f6c49284..8dd6a5b12922 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -88,159 +88,6 @@ static int set_fman_mac_params(struct mac_device *mac_dev,
 	return 0;
 }
 
-static int tgec_initialization(struct mac_device *mac_dev,
-			       struct device_node *mac_node)
-{
-	int err;
-	struct mac_priv_s	*priv;
-	struct fman_mac_params	params;
-	u32			version;
-
-	priv = mac_dev->priv;
-
-	err = set_fman_mac_params(mac_dev, &params);
-	if (err)
-		goto _return;
-
-	mac_dev->fman_mac = tgec_config(&params);
-	if (!mac_dev->fman_mac) {
-		err = -EINVAL;
-		goto _return;
-	}
-
-	err = tgec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = tgec_init(mac_dev->fman_mac);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	/* For 10G MAC, disable Tx ECC exception */
-	err = mac_dev->set_exception(mac_dev->fman_mac,
-				     FM_MAC_EX_10G_TX_ECC_ER, false);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = tgec_get_version(mac_dev->fman_mac, &version);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	dev_info(priv->dev, "FMan XGEC version: 0x%08x\n", version);
-
-	goto _return;
-
-_return_fm_mac_free:
-	tgec_free(mac_dev->fman_mac);
-
-_return:
-	return err;
-}
-
-static int dtsec_initialization(struct mac_device *mac_dev,
-				struct device_node *mac_node)
-{
-	int			err;
-	struct mac_priv_s	*priv;
-	struct fman_mac_params	params;
-	u32			version;
-
-	priv = mac_dev->priv;
-
-	err = set_fman_mac_params(mac_dev, &params);
-	if (err)
-		goto _return;
-	params.internal_phy_node = of_parse_phandle(mac_node, "tbi-handle", 0);
-
-	mac_dev->fman_mac = dtsec_config(&params);
-	if (!mac_dev->fman_mac) {
-		err = -EINVAL;
-		goto _return;
-	}
-
-	err = dtsec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = dtsec_cfg_pad_and_crc(mac_dev->fman_mac, true);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = dtsec_init(mac_dev->fman_mac);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	/* For 1G MAC, disable by default the MIB counters overflow interrupt */
-	err = mac_dev->set_exception(mac_dev->fman_mac,
-				     FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = dtsec_get_version(mac_dev->fman_mac, &version);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	dev_info(priv->dev, "FMan dTSEC version: 0x%08x\n", version);
-
-	goto _return;
-
-_return_fm_mac_free:
-	dtsec_free(mac_dev->fman_mac);
-
-_return:
-	return err;
-}
-
-static int memac_initialization(struct mac_device *mac_dev,
-				struct device_node *mac_node)
-{
-	int			 err;
-	struct mac_priv_s	*priv;
-	struct fman_mac_params	 params;
-
-	priv = mac_dev->priv;
-
-	err = set_fman_mac_params(mac_dev, &params);
-	if (err)
-		goto _return;
-	params.internal_phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0);
-
-	if (priv->max_speed == SPEED_10000)
-		params.phy_if = PHY_INTERFACE_MODE_XGMII;
-
-	mac_dev->fman_mac = memac_config(&params);
-	if (!mac_dev->fman_mac) {
-		err = -EINVAL;
-		goto _return;
-	}
-
-	err = memac_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = memac_cfg_reset_on_init(mac_dev->fman_mac, true);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = memac_cfg_fixed_link(mac_dev->fman_mac, priv->fixed_link);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = memac_init(mac_dev->fman_mac);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	dev_info(priv->dev, "FMan MEMAC\n");
-
-	goto _return;
-
-_return_fm_mac_free:
-	memac_free(mac_dev->fman_mac);
-
-_return:
-	return err;
-}
-
 static int set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
 {
 	struct mac_priv_s	*priv;
@@ -418,27 +265,15 @@ static void adjust_link_memac(struct mac_device *mac_dev)
 			err);
 }
 
-static void setup_dtsec(struct mac_device *mac_dev)
+static int tgec_initialization(struct mac_device *mac_dev,
+			       struct device_node *mac_node)
 {
-	mac_dev->init			= dtsec_initialization;
-	mac_dev->set_promisc		= dtsec_set_promiscuous;
-	mac_dev->change_addr		= dtsec_modify_mac_address;
-	mac_dev->add_hash_mac_addr	= dtsec_add_hash_mac_address;
-	mac_dev->remove_hash_mac_addr	= dtsec_del_hash_mac_address;
-	mac_dev->set_tx_pause		= dtsec_set_tx_pause_frames;
-	mac_dev->set_rx_pause		= dtsec_accept_rx_pause_frames;
-	mac_dev->set_exception		= dtsec_set_exception;
-	mac_dev->set_allmulti		= dtsec_set_allmulti;
-	mac_dev->set_tstamp		= dtsec_set_tstamp;
-	mac_dev->set_multi		= set_multi;
-	mac_dev->adjust_link            = adjust_link_dtsec;
-	mac_dev->enable			= dtsec_enable;
-	mac_dev->disable		= dtsec_disable;
-}
+	int err;
+	struct mac_priv_s	*priv;
+	struct fman_mac_params	params;
+	u32			version;
 
-static void setup_tgec(struct mac_device *mac_dev)
-{
-	mac_dev->init			= tgec_initialization;
+	priv = mac_dev->priv;
 	mac_dev->set_promisc		= tgec_set_promiscuous;
 	mac_dev->change_addr		= tgec_modify_mac_address;
 	mac_dev->add_hash_mac_addr	= tgec_add_hash_mac_address;
@@ -452,11 +287,121 @@ static void setup_tgec(struct mac_device *mac_dev)
 	mac_dev->adjust_link            = adjust_link_void;
 	mac_dev->enable			= tgec_enable;
 	mac_dev->disable		= tgec_disable;
+
+	err = set_fman_mac_params(mac_dev, &params);
+	if (err)
+		goto _return;
+
+	mac_dev->fman_mac = tgec_config(&params);
+	if (!mac_dev->fman_mac) {
+		err = -EINVAL;
+		goto _return;
+	}
+
+	err = tgec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = tgec_init(mac_dev->fman_mac);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	/* For 10G MAC, disable Tx ECC exception */
+	err = mac_dev->set_exception(mac_dev->fman_mac,
+				     FM_MAC_EX_10G_TX_ECC_ER, false);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = tgec_get_version(mac_dev->fman_mac, &version);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	dev_info(priv->dev, "FMan XGEC version: 0x%08x\n", version);
+
+	goto _return;
+
+_return_fm_mac_free:
+	tgec_free(mac_dev->fman_mac);
+
+_return:
+	return err;
+}
+
+static int dtsec_initialization(struct mac_device *mac_dev,
+				struct device_node *mac_node)
+{
+	int			err;
+	struct mac_priv_s	*priv;
+	struct fman_mac_params	params;
+	u32			version;
+
+	priv = mac_dev->priv;
+	mac_dev->set_promisc		= dtsec_set_promiscuous;
+	mac_dev->change_addr		= dtsec_modify_mac_address;
+	mac_dev->add_hash_mac_addr	= dtsec_add_hash_mac_address;
+	mac_dev->remove_hash_mac_addr	= dtsec_del_hash_mac_address;
+	mac_dev->set_tx_pause		= dtsec_set_tx_pause_frames;
+	mac_dev->set_rx_pause		= dtsec_accept_rx_pause_frames;
+	mac_dev->set_exception		= dtsec_set_exception;
+	mac_dev->set_allmulti		= dtsec_set_allmulti;
+	mac_dev->set_tstamp		= dtsec_set_tstamp;
+	mac_dev->set_multi		= set_multi;
+	mac_dev->adjust_link            = adjust_link_dtsec;
+	mac_dev->enable			= dtsec_enable;
+	mac_dev->disable		= dtsec_disable;
+
+	err = set_fman_mac_params(mac_dev, &params);
+	if (err)
+		goto _return;
+	params.internal_phy_node = of_parse_phandle(mac_node, "tbi-handle", 0);
+
+	mac_dev->fman_mac = dtsec_config(&params);
+	if (!mac_dev->fman_mac) {
+		err = -EINVAL;
+		goto _return;
+	}
+
+	err = dtsec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = dtsec_cfg_pad_and_crc(mac_dev->fman_mac, true);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = dtsec_init(mac_dev->fman_mac);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	/* For 1G MAC, disable by default the MIB counters overflow interrupt */
+	err = mac_dev->set_exception(mac_dev->fman_mac,
+				     FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = dtsec_get_version(mac_dev->fman_mac, &version);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	dev_info(priv->dev, "FMan dTSEC version: 0x%08x\n", version);
+
+	goto _return;
+
+_return_fm_mac_free:
+	dtsec_free(mac_dev->fman_mac);
+
+_return:
+	return err;
 }
 
-static void setup_memac(struct mac_device *mac_dev)
+static int memac_initialization(struct mac_device *mac_dev,
+				struct device_node *mac_node)
 {
-	mac_dev->init			= memac_initialization;
+	int			 err;
+	struct mac_priv_s	*priv;
+	struct fman_mac_params	 params;
+
+	priv = mac_dev->priv;
 	mac_dev->set_promisc		= memac_set_promiscuous;
 	mac_dev->change_addr		= memac_modify_mac_address;
 	mac_dev->add_hash_mac_addr	= memac_add_hash_mac_address;
@@ -470,6 +415,46 @@ static void setup_memac(struct mac_device *mac_dev)
 	mac_dev->adjust_link            = adjust_link_memac;
 	mac_dev->enable			= memac_enable;
 	mac_dev->disable		= memac_disable;
+
+	err = set_fman_mac_params(mac_dev, &params);
+	if (err)
+		goto _return;
+	params.internal_phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0);
+
+	if (priv->max_speed == SPEED_10000)
+		params.phy_if = PHY_INTERFACE_MODE_XGMII;
+
+	mac_dev->fman_mac = memac_config(&params);
+	if (!mac_dev->fman_mac) {
+		err = -EINVAL;
+		goto _return;
+	}
+
+	err = memac_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = memac_cfg_reset_on_init(mac_dev->fman_mac, true);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = memac_cfg_fixed_link(mac_dev->fman_mac, priv->fixed_link);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = memac_init(mac_dev->fman_mac);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	dev_info(priv->dev, "FMan MEMAC\n");
+
+	goto _return;
+
+_return_fm_mac_free:
+	memac_free(mac_dev->fman_mac);
+
+_return:
+	return err;
 }
 
 #define DTSEC_SUPPORTED \
@@ -546,9 +531,9 @@ static struct platform_device *dpaa_eth_add_device(int fman_id,
 }
 
 static const struct of_device_id mac_match[] = {
-	{ .compatible	= "fsl,fman-dtsec" },
-	{ .compatible	= "fsl,fman-xgec" },
-	{ .compatible	= "fsl,fman-memac" },
+	{ .compatible	= "fsl,fman-dtsec", .data = dtsec_initialization },
+	{ .compatible	= "fsl,fman-xgec", .data = tgec_initialization },
+	{ .compatible	= "fsl,fman-memac", .data = memac_initialization },
 	{}
 };
 MODULE_DEVICE_TABLE(of, mac_match);
@@ -556,6 +541,7 @@ MODULE_DEVICE_TABLE(of, mac_match);
 static int mac_probe(struct platform_device *_of_dev)
 {
 	int			 err, i, nph;
+	int (*init)(struct mac_device *mac_dev, struct device_node *mac_node);
 	struct device		*dev;
 	struct device_node	*mac_node, *dev_node;
 	struct mac_device	*mac_dev;
@@ -568,6 +554,7 @@ static int mac_probe(struct platform_device *_of_dev)
 
 	dev = &_of_dev->dev;
 	mac_node = dev->of_node;
+	init = of_device_get_match_data(dev);
 
 	mac_dev = devm_kzalloc(dev, sizeof(*mac_dev), GFP_KERNEL);
 	if (!mac_dev) {
@@ -584,19 +571,6 @@ static int mac_probe(struct platform_device *_of_dev)
 	mac_dev->priv = priv;
 	priv->dev = dev;
 
-	if (of_device_is_compatible(mac_node, "fsl,fman-dtsec")) {
-		setup_dtsec(mac_dev);
-	} else if (of_device_is_compatible(mac_node, "fsl,fman-xgec")) {
-		setup_tgec(mac_dev);
-	} else if (of_device_is_compatible(mac_node, "fsl,fman-memac")) {
-		setup_memac(mac_dev);
-	} else {
-		dev_err(dev, "MAC node (%pOF) contains unsupported MAC\n",
-			mac_node);
-		err = -EINVAL;
-		goto _return;
-	}
-
 	INIT_LIST_HEAD(&priv->mc_addr_list);
 
 	/* Get the FM node */
@@ -782,7 +756,7 @@ static int mac_probe(struct platform_device *_of_dev)
 		put_device(&phy->mdio.dev);
 	}
 
-	err = mac_dev->init(mac_dev, mac_node);
+	err = init(mac_dev, mac_node);
 	if (err < 0) {
 		dev_err(dev, "mac_dev->init() = %d\n", err);
 		of_node_put(mac_dev->phy_node);
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index e4329c7d5001..fed3835a8473 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -35,7 +35,6 @@ struct mac_device {
 	bool promisc;
 	bool allmulti;
 
-	int (*init)(struct mac_device *mac_dev, struct device_node *mac_node);
 	int (*enable)(struct fman_mac *mac_dev);
 	int (*disable)(struct fman_mac *mac_dev);
 	void (*adjust_link)(struct mac_device *mac_dev);
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 10/28] net: fman: Move struct dev to mac_device
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (8 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 09/28] net: fman: Store initialization function in match data Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-18  3:57   ` kernel test robot
  2022-06-17 20:32 ` [PATCH net-next 11/28] net: fman: Configure fixed link in memac_initialization Sean Anderson
                   ` (17 subsequent siblings)
  27 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

Move the reference to our device to mac_device. This way, macs can use
it in their log messages.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/net/ethernet/freescale/fman/mac.c | 21 ++++++++++-----------
 drivers/net/ethernet/freescale/fman/mac.h |  1 +
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 8dd6a5b12922..5d6159c0e1f0 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -28,7 +28,6 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("FSL FMan MAC API based driver");
 
 struct mac_priv_s {
-	struct device			*dev;
 	void __iomem			*vaddr;
 	u8				cell_index;
 	struct fman			*fman;
@@ -57,10 +56,10 @@ static void mac_exception(void *handle, enum fman_mac_exceptions ex)
 		/* don't flag RX FIFO after the first */
 		mac_dev->set_exception(mac_dev->fman_mac,
 				       FM_MAC_EX_10G_RX_FIFO_OVFL, false);
-		dev_err(priv->dev, "10G MAC got RX FIFO Error = %x\n", ex);
+		dev_err(mac_dev->dev, "10G MAC got RX FIFO Error = %x\n", ex);
 	}
 
-	dev_dbg(priv->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c",
+	dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c",
 		__func__, ex);
 }
 
@@ -70,7 +69,7 @@ static int set_fman_mac_params(struct mac_device *mac_dev,
 	struct mac_priv_s *priv = mac_dev->priv;
 
 	params->base_addr = (typeof(params->base_addr))
-		devm_ioremap(priv->dev, mac_dev->res->start,
+		devm_ioremap(mac_dev->dev, mac_dev->res->start,
 			     resource_size(mac_dev->res));
 	if (!params->base_addr)
 		return -ENOMEM;
@@ -244,7 +243,7 @@ static void adjust_link_dtsec(struct mac_device *mac_dev)
 	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
 	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
 	if (err < 0)
-		dev_err(mac_dev->priv->dev, "fman_set_mac_active_pause() = %d\n",
+		dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n",
 			err);
 }
 
@@ -261,7 +260,7 @@ static void adjust_link_memac(struct mac_device *mac_dev)
 	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
 	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
 	if (err < 0)
-		dev_err(mac_dev->priv->dev, "fman_set_mac_active_pause() = %d\n",
+		dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n",
 			err);
 }
 
@@ -316,7 +315,7 @@ static int tgec_initialization(struct mac_device *mac_dev,
 	if (err < 0)
 		goto _return_fm_mac_free;
 
-	dev_info(priv->dev, "FMan XGEC version: 0x%08x\n", version);
+	dev_info(mac_dev->dev, "FMan XGEC version: 0x%08x\n", version);
 
 	goto _return;
 
@@ -383,7 +382,7 @@ static int dtsec_initialization(struct mac_device *mac_dev,
 	if (err < 0)
 		goto _return_fm_mac_free;
 
-	dev_info(priv->dev, "FMan dTSEC version: 0x%08x\n", version);
+	dev_info(mac_dev->dev, "FMan dTSEC version: 0x%08x\n", version);
 
 	goto _return;
 
@@ -446,7 +445,7 @@ static int memac_initialization(struct mac_device *mac_dev,
 	if (err < 0)
 		goto _return_fm_mac_free;
 
-	dev_info(priv->dev, "FMan MEMAC\n");
+	dev_info(mac_dev->dev, "FMan MEMAC\n");
 
 	goto _return;
 
@@ -507,7 +506,7 @@ static struct platform_device *dpaa_eth_add_device(int fman_id,
 		goto no_mem;
 	}
 
-	pdev->dev.parent = priv->dev;
+	pdev->dev.parent = mac_dev->dev;
 
 	ret = platform_device_add_data(pdev, &data, sizeof(data));
 	if (ret)
@@ -569,7 +568,7 @@ static int mac_probe(struct platform_device *_of_dev)
 
 	/* Save private information */
 	mac_dev->priv = priv;
-	priv->dev = dev;
+	mac_dev->dev = dev;
 
 	INIT_LIST_HEAD(&priv->mc_addr_list);
 
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index fed3835a8473..05dbb8b5a704 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -19,6 +19,7 @@ struct fman_mac;
 struct mac_priv_s;
 
 struct mac_device {
+	struct device		*dev;
 	struct resource		*res;
 	u8			 addr[ETH_ALEN];
 	struct fman_port	*port[2];
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 11/28] net: fman: Configure fixed link in memac_initialization
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (9 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 10/28] net: fman: Move struct dev to mac_device Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 12/28] net: fman: Export/rename some common functions Sean Anderson
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

memac is the only mac which parses fixed links. Move the
parsing/configuring to its initialization function.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/net/ethernet/freescale/fman/mac.c | 93 +++++++++++------------
 1 file changed, 46 insertions(+), 47 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 5d6159c0e1f0..248108b15cb0 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -34,7 +34,6 @@ struct mac_priv_s {
 	/* List of multicast addresses */
 	struct list_head		mc_addr_list;
 	struct platform_device		*eth_dev;
-	struct fixed_phy_status		*fixed_link;
 	u16				speed;
 	u16				max_speed;
 };
@@ -399,6 +398,7 @@ static int memac_initialization(struct mac_device *mac_dev,
 	int			 err;
 	struct mac_priv_s	*priv;
 	struct fman_mac_params	 params;
+	struct fixed_phy_status *fixed_link;
 
 	priv = mac_dev->priv;
 	mac_dev->set_promisc		= memac_set_promiscuous;
@@ -437,21 +437,52 @@ static int memac_initialization(struct mac_device *mac_dev,
 	if (err < 0)
 		goto _return_fm_mac_free;
 
-	err = memac_cfg_fixed_link(mac_dev->fman_mac, priv->fixed_link);
-	if (err < 0)
-		goto _return_fm_mac_free;
+	if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
+		struct phy_device *phy;
+
+		err = of_phy_register_fixed_link(mac_node);
+		if (err)
+			goto _return_fm_mac_free;
+
+		fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL);
+		if (!fixed_link) {
+			err = -ENOMEM;
+			goto _return_fm_mac_free;
+		}
+
+		mac_dev->phy_node = of_node_get(mac_node);
+		phy = of_phy_find_device(mac_dev->phy_node);
+		if (!phy) {
+			err = -EINVAL;
+			of_node_put(mac_dev->phy_node);
+			goto _return_fixed_link_free;
+		}
+
+		fixed_link->link = phy->link;
+		fixed_link->speed = phy->speed;
+		fixed_link->duplex = phy->duplex;
+		fixed_link->pause = phy->pause;
+		fixed_link->asym_pause = phy->asym_pause;
+
+		put_device(&phy->mdio.dev);
+
+		err = memac_cfg_fixed_link(mac_dev->fman_mac, fixed_link);
+		if (err < 0)
+			goto _return_fixed_link_free;
+	}
 
 	err = memac_init(mac_dev->fman_mac);
 	if (err < 0)
-		goto _return_fm_mac_free;
+		goto _return_fixed_link_free;
 
 	dev_info(mac_dev->dev, "FMan MEMAC\n");
 
 	goto _return;
 
+_return_fixed_link_free:
+	kfree(fixed_link);
 _return_fm_mac_free:
 	memac_free(mac_dev->fman_mac);
-
 _return:
 	return err;
 }
@@ -578,7 +609,7 @@ static int mac_probe(struct platform_device *_of_dev)
 		dev_err(dev, "of_get_parent(%pOF) failed\n",
 			mac_node);
 		err = -EINVAL;
-		goto _return_of_get_parent;
+		goto _return_of_node_put;
 	}
 
 	of_dev = of_find_device_by_node(dev_node);
@@ -612,7 +643,7 @@ static int mac_probe(struct platform_device *_of_dev)
 	if (err < 0) {
 		dev_err(dev, "of_address_to_resource(%pOF) = %d\n",
 			mac_node, err);
-		goto _return_of_get_parent;
+		goto _return_of_node_put;
 	}
 
 	mac_dev->res = __devm_request_region(dev,
@@ -622,7 +653,7 @@ static int mac_probe(struct platform_device *_of_dev)
 	if (!mac_dev->res) {
 		dev_err(dev, "__devm_request_mem_region(mac) failed\n");
 		err = -EBUSY;
-		goto _return_of_get_parent;
+		goto _return_of_node_put;
 	}
 
 	priv->vaddr = devm_ioremap(dev, mac_dev->res->start,
@@ -630,12 +661,12 @@ static int mac_probe(struct platform_device *_of_dev)
 	if (!priv->vaddr) {
 		dev_err(dev, "devm_ioremap() failed\n");
 		err = -EIO;
-		goto _return_of_get_parent;
+		goto _return_of_node_put;
 	}
 
 	if (!of_device_is_available(mac_node)) {
 		err = -ENODEV;
-		goto _return_of_get_parent;
+		goto _return_of_node_put;
 	}
 
 	/* Get the cell-index */
@@ -643,7 +674,7 @@ static int mac_probe(struct platform_device *_of_dev)
 	if (err) {
 		dev_err(dev, "failed to read cell-index for %pOF\n", mac_node);
 		err = -EINVAL;
-		goto _return_of_get_parent;
+		goto _return_of_node_put;
 	}
 	priv->cell_index = (u8)val;
 
@@ -658,14 +689,14 @@ static int mac_probe(struct platform_device *_of_dev)
 		dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n",
 			mac_node);
 		err = nph;
-		goto _return_of_get_parent;
+		goto _return_of_node_put;
 	}
 
 	if (nph != ARRAY_SIZE(mac_dev->port)) {
 		dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n",
 			mac_node);
 		err = -EINVAL;
-		goto _return_of_get_parent;
+		goto _return_of_node_put;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
@@ -724,42 +755,12 @@ static int mac_probe(struct platform_device *_of_dev)
 
 	/* Get the rest of the PHY information */
 	mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0);
-	if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
-		struct phy_device *phy;
-
-		err = of_phy_register_fixed_link(mac_node);
-		if (err)
-			goto _return_of_get_parent;
-
-		priv->fixed_link = kzalloc(sizeof(*priv->fixed_link),
-					   GFP_KERNEL);
-		if (!priv->fixed_link) {
-			err = -ENOMEM;
-			goto _return_of_get_parent;
-		}
-
-		mac_dev->phy_node = of_node_get(mac_node);
-		phy = of_phy_find_device(mac_dev->phy_node);
-		if (!phy) {
-			err = -EINVAL;
-			of_node_put(mac_dev->phy_node);
-			goto _return_of_get_parent;
-		}
-
-		priv->fixed_link->link = phy->link;
-		priv->fixed_link->speed = phy->speed;
-		priv->fixed_link->duplex = phy->duplex;
-		priv->fixed_link->pause = phy->pause;
-		priv->fixed_link->asym_pause = phy->asym_pause;
-
-		put_device(&phy->mdio.dev);
-	}
 
 	err = init(mac_dev, mac_node);
 	if (err < 0) {
 		dev_err(dev, "mac_dev->init() = %d\n", err);
 		of_node_put(mac_dev->phy_node);
-		goto _return_of_get_parent;
+		goto _return_of_node_put;
 	}
 
 	/* pause frame autonegotiation enabled */
@@ -790,8 +791,6 @@ static int mac_probe(struct platform_device *_of_dev)
 
 _return_of_node_put:
 	of_node_put(dev_node);
-_return_of_get_parent:
-	kfree(priv->fixed_link);
 _return:
 	return err;
 }
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 12/28] net: fman: Export/rename some common functions
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (10 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 11/28] net: fman: Configure fixed link in memac_initialization Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 13/28] net: fman: memac: Use params instead of priv for max_speed Sean Anderson
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

In preparation for moving each of the initialization functions to their
own file, export some common functions so they can be re-used. This adds
an fman prefix to set_multi to make it a bit less genericly-named.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/net/ethernet/freescale/fman/mac.c | 12 ++++++------
 drivers/net/ethernet/freescale/fman/mac.h |  3 +++
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 248108b15cb0..ac26861ea2e0 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -62,8 +62,8 @@ static void mac_exception(void *handle, enum fman_mac_exceptions ex)
 		__func__, ex);
 }
 
-static int set_fman_mac_params(struct mac_device *mac_dev,
-			       struct fman_mac_params *params)
+int set_fman_mac_params(struct mac_device *mac_dev,
+			struct fman_mac_params *params)
 {
 	struct mac_priv_s *priv = mac_dev->priv;
 
@@ -86,7 +86,7 @@ static int set_fman_mac_params(struct mac_device *mac_dev,
 	return 0;
 }
 
-static int set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
+int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
 {
 	struct mac_priv_s	*priv;
 	struct mac_address	*old_addr, *tmp;
@@ -281,7 +281,7 @@ static int tgec_initialization(struct mac_device *mac_dev,
 	mac_dev->set_exception		= tgec_set_exception;
 	mac_dev->set_allmulti		= tgec_set_allmulti;
 	mac_dev->set_tstamp		= tgec_set_tstamp;
-	mac_dev->set_multi		= set_multi;
+	mac_dev->set_multi		= fman_set_multi;
 	mac_dev->adjust_link            = adjust_link_void;
 	mac_dev->enable			= tgec_enable;
 	mac_dev->disable		= tgec_disable;
@@ -343,7 +343,7 @@ static int dtsec_initialization(struct mac_device *mac_dev,
 	mac_dev->set_exception		= dtsec_set_exception;
 	mac_dev->set_allmulti		= dtsec_set_allmulti;
 	mac_dev->set_tstamp		= dtsec_set_tstamp;
-	mac_dev->set_multi		= set_multi;
+	mac_dev->set_multi		= fman_set_multi;
 	mac_dev->adjust_link            = adjust_link_dtsec;
 	mac_dev->enable			= dtsec_enable;
 	mac_dev->disable		= dtsec_disable;
@@ -410,7 +410,7 @@ static int memac_initialization(struct mac_device *mac_dev,
 	mac_dev->set_exception		= memac_set_exception;
 	mac_dev->set_allmulti		= memac_set_allmulti;
 	mac_dev->set_tstamp		= memac_set_tstamp;
-	mac_dev->set_multi		= set_multi;
+	mac_dev->set_multi		= fman_set_multi;
 	mac_dev->adjust_link            = adjust_link_memac;
 	mac_dev->enable			= memac_enable;
 	mac_dev->disable		= memac_disable;
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index 05dbb8b5a704..da410a7d00c9 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -71,5 +71,8 @@ int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx);
 
 void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause,
 			bool *tx_pause);
+int set_fman_mac_params(struct mac_device *mac_dev,
+			struct fman_mac_params *params);
+int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev);
 
 #endif	/* __MAC_H */
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 13/28] net: fman: memac: Use params instead of priv for max_speed
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (11 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 12/28] net: fman: Export/rename some common functions Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 14/28] net: fman: Move initialization to mac-specific files Sean Anderson
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

This option is present in params, so use it instead of the fman private
version.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/net/ethernet/freescale/fman/mac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index ac26861ea2e0..b3f947f071ee 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -420,7 +420,7 @@ static int memac_initialization(struct mac_device *mac_dev,
 		goto _return;
 	params.internal_phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0);
 
-	if (priv->max_speed == SPEED_10000)
+	if (params.max_speed == SPEED_10000)
 		params.phy_if = PHY_INTERFACE_MODE_XGMII;
 
 	mac_dev->fman_mac = memac_config(&params);
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 14/28] net: fman: Move initialization to mac-specific files
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (12 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 13/28] net: fman: memac: Use params instead of priv for max_speed Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:32 ` [PATCH net-next 15/28] net: fman: Mark mac methods static Sean Anderson
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

This moves mac-specific initialization to mac-specific files. This will
make it easier to work with individual macs. It will also make it easier
to refactor the initialization to simplify the control flow. No
functional change intended.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../net/ethernet/freescale/fman/fman_dtsec.c  |  90 ++++++
 .../net/ethernet/freescale/fman/fman_dtsec.h  |  27 +-
 .../net/ethernet/freescale/fman/fman_memac.c  | 113 ++++++++
 .../net/ethernet/freescale/fman/fman_memac.h  |  25 +-
 .../net/ethernet/freescale/fman/fman_tgec.c   |  65 +++++
 .../net/ethernet/freescale/fman/fman_tgec.h   |  22 +-
 drivers/net/ethernet/freescale/fman/mac.c     | 267 ------------------
 7 files changed, 281 insertions(+), 328 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 7f4f3d797a8d..12ce079a356d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -7,6 +7,7 @@
 
 #include "fman_dtsec.h"
 #include "fman.h"
+#include "mac.h"
 
 #include <linux/slab.h>
 #include <linux/bitrev.h>
@@ -1247,6 +1248,28 @@ int dtsec_restart_autoneg(struct fman_mac *dtsec)
 	return 0;
 }
 
+static void adjust_link_dtsec(struct mac_device *mac_dev)
+{
+	struct phy_device *phy_dev = mac_dev->phy_dev;
+	struct fman_mac *fman_mac;
+	bool rx_pause, tx_pause;
+	int err;
+
+	fman_mac = mac_dev->fman_mac;
+	if (!phy_dev->link) {
+		dtsec_restart_autoneg(fman_mac);
+
+		return;
+	}
+
+	dtsec_adjust_link(fman_mac, phy_dev->speed);
+	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
+	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
+	if (err < 0)
+		dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n",
+			err);
+}
+
 int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
@@ -1492,3 +1515,70 @@ struct fman_mac *dtsec_config(struct fman_mac_params *params)
 	kfree(dtsec);
 	return NULL;
 }
+
+int dtsec_initialization(struct mac_device *mac_dev,
+			 struct device_node *mac_node)
+{
+	int			err;
+	struct mac_priv_s	*priv;
+	struct fman_mac_params	params;
+	u32			version;
+
+	priv = mac_dev->priv;
+	mac_dev->set_promisc		= dtsec_set_promiscuous;
+	mac_dev->change_addr		= dtsec_modify_mac_address;
+	mac_dev->add_hash_mac_addr	= dtsec_add_hash_mac_address;
+	mac_dev->remove_hash_mac_addr	= dtsec_del_hash_mac_address;
+	mac_dev->set_tx_pause		= dtsec_set_tx_pause_frames;
+	mac_dev->set_rx_pause		= dtsec_accept_rx_pause_frames;
+	mac_dev->set_exception		= dtsec_set_exception;
+	mac_dev->set_allmulti		= dtsec_set_allmulti;
+	mac_dev->set_tstamp		= dtsec_set_tstamp;
+	mac_dev->set_multi		= fman_set_multi;
+	mac_dev->adjust_link            = adjust_link_dtsec;
+	mac_dev->enable			= dtsec_enable;
+	mac_dev->disable		= dtsec_disable;
+
+	err = set_fman_mac_params(mac_dev, &params);
+	if (err)
+		goto _return;
+	params.internal_phy_node = of_parse_phandle(mac_node, "tbi-handle", 0);
+
+	mac_dev->fman_mac = dtsec_config(&params);
+	if (!mac_dev->fman_mac) {
+		err = -EINVAL;
+		goto _return;
+	}
+
+	err = dtsec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = dtsec_cfg_pad_and_crc(mac_dev->fman_mac, true);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = dtsec_init(mac_dev->fman_mac);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	/* For 1G MAC, disable by default the MIB counters overflow interrupt */
+	err = mac_dev->set_exception(mac_dev->fman_mac,
+				     FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = dtsec_get_version(mac_dev->fman_mac, &version);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	dev_info(mac_dev->dev, "FMan dTSEC version: 0x%08x\n", version);
+
+	goto _return;
+
+_return_fm_mac_free:
+	dtsec_free(mac_dev->fman_mac);
+
+_return:
+	return err;
+}
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.h b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
index f072cdc560ba..8c72d280c51a 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
@@ -8,27 +8,10 @@
 
 #include "fman_mac.h"
 
-struct fman_mac *dtsec_config(struct fman_mac_params *params);
-int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val);
-int dtsec_modify_mac_address(struct fman_mac *dtsec, const enet_addr_t *enet_addr);
-int dtsec_adjust_link(struct fman_mac *dtsec,
-		      u16 speed);
-int dtsec_restart_autoneg(struct fman_mac *dtsec);
-int dtsec_cfg_max_frame_len(struct fman_mac *dtsec, u16 new_val);
-int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val);
-int dtsec_enable(struct fman_mac *dtsec);
-int dtsec_disable(struct fman_mac *dtsec);
-int dtsec_init(struct fman_mac *dtsec);
-int dtsec_free(struct fman_mac *dtsec);
-int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en);
-int dtsec_set_tx_pause_frames(struct fman_mac *dtsec, u8 priority,
-			      u16 pause_time, u16 thresh_time);
-int dtsec_set_exception(struct fman_mac *dtsec,
-			enum fman_mac_exceptions exception, bool enable);
-int dtsec_add_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr);
-int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr);
-int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version);
-int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable);
-int dtsec_set_tstamp(struct fman_mac *dtsec, bool enable);
+struct mac_device;
+
+int dtsec_initialization(struct mac_device *mac_dev,
+			 struct device_node *mac_node,
+			 struct fman_mac_params *params);
 
 #endif /* __DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index c34da49aed31..4300a21a553b 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -7,6 +7,7 @@
 
 #include "fman_memac.h"
 #include "fman.h"
+#include "mac.h"
 
 #include <linux/slab.h>
 #include <linux/io.h>
@@ -774,6 +775,23 @@ int memac_adjust_link(struct fman_mac *memac, u16 speed)
 	return 0;
 }
 
+static void adjust_link_memac(struct mac_device *mac_dev)
+{
+	struct phy_device *phy_dev = mac_dev->phy_dev;
+	struct fman_mac *fman_mac;
+	bool rx_pause, tx_pause;
+	int err;
+
+	fman_mac = mac_dev->fman_mac;
+	memac_adjust_link(fman_mac, phy_dev->speed);
+
+	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
+	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
+	if (err < 0)
+		dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n",
+			err);
+}
+
 int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val)
 {
 	if (is_init_done(memac->memac_drv_param))
@@ -1178,3 +1196,98 @@ struct fman_mac *memac_config(struct fman_mac_params *params)
 
 	return memac;
 }
+
+int memac_initialization(struct mac_device *mac_dev,
+			 struct device_node *mac_node)
+{
+	int			 err;
+	struct mac_priv_s	*priv;
+	struct fman_mac_params	 params;
+	struct fixed_phy_status *fixed_link;
+
+	priv = mac_dev->priv;
+	mac_dev->set_promisc		= memac_set_promiscuous;
+	mac_dev->change_addr		= memac_modify_mac_address;
+	mac_dev->add_hash_mac_addr	= memac_add_hash_mac_address;
+	mac_dev->remove_hash_mac_addr	= memac_del_hash_mac_address;
+	mac_dev->set_tx_pause		= memac_set_tx_pause_frames;
+	mac_dev->set_rx_pause		= memac_accept_rx_pause_frames;
+	mac_dev->set_exception		= memac_set_exception;
+	mac_dev->set_allmulti		= memac_set_allmulti;
+	mac_dev->set_tstamp		= memac_set_tstamp;
+	mac_dev->set_multi		= fman_set_multi;
+	mac_dev->adjust_link            = adjust_link_memac;
+	mac_dev->enable			= memac_enable;
+	mac_dev->disable		= memac_disable;
+
+	err = set_fman_mac_params(mac_dev, &params);
+	if (err)
+		goto _return;
+	params.internal_phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0);
+
+	if (params.max_speed == SPEED_10000)
+		params.phy_if = PHY_INTERFACE_MODE_XGMII;
+
+	mac_dev->fman_mac = memac_config(&params);
+	if (!mac_dev->fman_mac) {
+		err = -EINVAL;
+		goto _return;
+	}
+
+	err = memac_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = memac_cfg_reset_on_init(mac_dev->fman_mac, true);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
+		struct phy_device *phy;
+
+		err = of_phy_register_fixed_link(mac_node);
+		if (err)
+			goto _return_fm_mac_free;
+
+		fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL);
+		if (!fixed_link) {
+			err = -ENOMEM;
+			goto _return_fm_mac_free;
+		}
+
+		mac_dev->phy_node = of_node_get(mac_node);
+		phy = of_phy_find_device(mac_dev->phy_node);
+		if (!phy) {
+			err = -EINVAL;
+			of_node_put(mac_dev->phy_node);
+			goto _return_fixed_link_free;
+		}
+
+		fixed_link->link = phy->link;
+		fixed_link->speed = phy->speed;
+		fixed_link->duplex = phy->duplex;
+		fixed_link->pause = phy->pause;
+		fixed_link->asym_pause = phy->asym_pause;
+
+		put_device(&phy->mdio.dev);
+
+		err = memac_cfg_fixed_link(mac_dev->fman_mac, fixed_link);
+		if (err < 0)
+			goto _return_fixed_link_free;
+	}
+
+	err = memac_init(mac_dev->fman_mac);
+	if (err < 0)
+		goto _return_fixed_link_free;
+
+	dev_info(mac_dev->dev, "FMan MEMAC\n");
+
+	goto _return;
+
+_return_fixed_link_free:
+	kfree(fixed_link);
+_return_fm_mac_free:
+	memac_free(mac_dev->fman_mac);
+_return:
+	return err;
+}
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.h b/drivers/net/ethernet/freescale/fman/fman_memac.h
index 535ecd2b2ab4..a58215a3b1d9 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.h
@@ -11,26 +11,9 @@
 #include <linux/netdevice.h>
 #include <linux/phy_fixed.h>
 
-struct fman_mac *memac_config(struct fman_mac_params *params);
-int memac_set_promiscuous(struct fman_mac *memac, bool new_val);
-int memac_modify_mac_address(struct fman_mac *memac, const enet_addr_t *enet_addr);
-int memac_adjust_link(struct fman_mac *memac, u16 speed);
-int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val);
-int memac_cfg_reset_on_init(struct fman_mac *memac, bool enable);
-int memac_cfg_fixed_link(struct fman_mac *memac,
-			 struct fixed_phy_status *fixed_link);
-int memac_enable(struct fman_mac *memac);
-int memac_disable(struct fman_mac *memac);
-int memac_init(struct fman_mac *memac);
-int memac_free(struct fman_mac *memac);
-int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en);
-int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority,
-			      u16 pause_time, u16 thresh_time);
-int memac_set_exception(struct fman_mac *memac,
-			enum fman_mac_exceptions exception, bool enable);
-int memac_add_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr);
-int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr);
-int memac_set_allmulti(struct fman_mac *memac, bool enable);
-int memac_set_tstamp(struct fman_mac *memac, bool enable);
+struct mac_device;
+
+int memac_initialization(struct mac_device *mac_dev,
+			 struct device_node *mac_node);
 
 #endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index 2b38d22c863d..2f2c4ef45f6f 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -7,6 +7,7 @@
 
 #include "fman_tgec.h"
 #include "fman.h"
+#include "mac.h"
 
 #include <linux/slab.h>
 #include <linux/bitrev.h>
@@ -609,6 +610,10 @@ int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr)
 	return 0;
 }
 
+static void adjust_link_void(struct mac_device *mac_dev)
+{
+}
+
 int tgec_get_version(struct fman_mac *tgec, u32 *mac_version)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
@@ -794,3 +799,63 @@ struct fman_mac *tgec_config(struct fman_mac_params *params)
 
 	return tgec;
 }
+
+int tgec_initialization(struct mac_device *mac_dev,
+			struct device_node *mac_node)
+{
+	int err;
+	struct fman_mac_params	params;
+	u32			version;
+
+	mac_dev->set_promisc		= tgec_set_promiscuous;
+	mac_dev->change_addr		= tgec_modify_mac_address;
+	mac_dev->add_hash_mac_addr	= tgec_add_hash_mac_address;
+	mac_dev->remove_hash_mac_addr	= tgec_del_hash_mac_address;
+	mac_dev->set_tx_pause		= tgec_set_tx_pause_frames;
+	mac_dev->set_rx_pause		= tgec_accept_rx_pause_frames;
+	mac_dev->set_exception		= tgec_set_exception;
+	mac_dev->set_allmulti		= tgec_set_allmulti;
+	mac_dev->set_tstamp		= tgec_set_tstamp;
+	mac_dev->set_multi		= fman_set_multi;
+	mac_dev->adjust_link            = adjust_link_void;
+	mac_dev->enable			= tgec_enable;
+	mac_dev->disable		= tgec_disable;
+
+	err = set_fman_mac_params(mac_dev, &params);
+	if (err)
+		goto _return;
+
+	mac_dev->fman_mac = tgec_config(&params);
+	if (!mac_dev->fman_mac) {
+		err = -EINVAL;
+		goto _return;
+	}
+
+	err = tgec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = tgec_init(mac_dev->fman_mac);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	/* For 10G MAC, disable Tx ECC exception */
+	err = mac_dev->set_exception(mac_dev->fman_mac,
+				     FM_MAC_EX_10G_TX_ECC_ER, false);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	err = tgec_get_version(mac_dev->fman_mac, &version);
+	if (err < 0)
+		goto _return_fm_mac_free;
+
+	pr_info("FMan XGEC version: 0x%08x\n", version);
+
+	goto _return;
+
+_return_fm_mac_free:
+	tgec_free(mac_dev->fman_mac);
+
+_return:
+	return err;
+}
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.h b/drivers/net/ethernet/freescale/fman/fman_tgec.h
index 5b256758cbec..2e45b9fea352 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.h
@@ -8,23 +8,9 @@
 
 #include "fman_mac.h"
 
-struct fman_mac *tgec_config(struct fman_mac_params *params);
-int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val);
-int tgec_modify_mac_address(struct fman_mac *tgec, const enet_addr_t *enet_addr);
-int tgec_cfg_max_frame_len(struct fman_mac *tgec, u16 new_val);
-int tgec_enable(struct fman_mac *tgec);
-int tgec_disable(struct fman_mac *tgec);
-int tgec_init(struct fman_mac *tgec);
-int tgec_free(struct fman_mac *tgec);
-int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en);
-int tgec_set_tx_pause_frames(struct fman_mac *tgec, u8 priority,
-			     u16 pause_time, u16 thresh_time);
-int tgec_set_exception(struct fman_mac *tgec,
-		       enum fman_mac_exceptions exception, bool enable);
-int tgec_add_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr);
-int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr);
-int tgec_get_version(struct fman_mac *tgec, u32 *mac_version);
-int tgec_set_allmulti(struct fman_mac *tgec, bool enable);
-int tgec_set_tstamp(struct fman_mac *tgec, bool enable);
+struct mac_device;
+
+int tgec_initialization(struct mac_device *mac_dev,
+			struct device_node *mac_node);
 
 #endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index b3f947f071ee..e33d8b87f70f 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -220,273 +220,6 @@ void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause,
 }
 EXPORT_SYMBOL(fman_get_pause_cfg);
 
-static void adjust_link_void(struct mac_device *mac_dev)
-{
-}
-
-static void adjust_link_dtsec(struct mac_device *mac_dev)
-{
-	struct phy_device *phy_dev = mac_dev->phy_dev;
-	struct fman_mac *fman_mac;
-	bool rx_pause, tx_pause;
-	int err;
-
-	fman_mac = mac_dev->fman_mac;
-	if (!phy_dev->link) {
-		dtsec_restart_autoneg(fman_mac);
-
-		return;
-	}
-
-	dtsec_adjust_link(fman_mac, phy_dev->speed);
-	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
-	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
-	if (err < 0)
-		dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n",
-			err);
-}
-
-static void adjust_link_memac(struct mac_device *mac_dev)
-{
-	struct phy_device *phy_dev = mac_dev->phy_dev;
-	struct fman_mac *fman_mac;
-	bool rx_pause, tx_pause;
-	int err;
-
-	fman_mac = mac_dev->fman_mac;
-	memac_adjust_link(fman_mac, phy_dev->speed);
-
-	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
-	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
-	if (err < 0)
-		dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n",
-			err);
-}
-
-static int tgec_initialization(struct mac_device *mac_dev,
-			       struct device_node *mac_node)
-{
-	int err;
-	struct mac_priv_s	*priv;
-	struct fman_mac_params	params;
-	u32			version;
-
-	priv = mac_dev->priv;
-	mac_dev->set_promisc		= tgec_set_promiscuous;
-	mac_dev->change_addr		= tgec_modify_mac_address;
-	mac_dev->add_hash_mac_addr	= tgec_add_hash_mac_address;
-	mac_dev->remove_hash_mac_addr	= tgec_del_hash_mac_address;
-	mac_dev->set_tx_pause		= tgec_set_tx_pause_frames;
-	mac_dev->set_rx_pause		= tgec_accept_rx_pause_frames;
-	mac_dev->set_exception		= tgec_set_exception;
-	mac_dev->set_allmulti		= tgec_set_allmulti;
-	mac_dev->set_tstamp		= tgec_set_tstamp;
-	mac_dev->set_multi		= fman_set_multi;
-	mac_dev->adjust_link            = adjust_link_void;
-	mac_dev->enable			= tgec_enable;
-	mac_dev->disable		= tgec_disable;
-
-	err = set_fman_mac_params(mac_dev, &params);
-	if (err)
-		goto _return;
-
-	mac_dev->fman_mac = tgec_config(&params);
-	if (!mac_dev->fman_mac) {
-		err = -EINVAL;
-		goto _return;
-	}
-
-	err = tgec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = tgec_init(mac_dev->fman_mac);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	/* For 10G MAC, disable Tx ECC exception */
-	err = mac_dev->set_exception(mac_dev->fman_mac,
-				     FM_MAC_EX_10G_TX_ECC_ER, false);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = tgec_get_version(mac_dev->fman_mac, &version);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	dev_info(mac_dev->dev, "FMan XGEC version: 0x%08x\n", version);
-
-	goto _return;
-
-_return_fm_mac_free:
-	tgec_free(mac_dev->fman_mac);
-
-_return:
-	return err;
-}
-
-static int dtsec_initialization(struct mac_device *mac_dev,
-				struct device_node *mac_node)
-{
-	int			err;
-	struct mac_priv_s	*priv;
-	struct fman_mac_params	params;
-	u32			version;
-
-	priv = mac_dev->priv;
-	mac_dev->set_promisc		= dtsec_set_promiscuous;
-	mac_dev->change_addr		= dtsec_modify_mac_address;
-	mac_dev->add_hash_mac_addr	= dtsec_add_hash_mac_address;
-	mac_dev->remove_hash_mac_addr	= dtsec_del_hash_mac_address;
-	mac_dev->set_tx_pause		= dtsec_set_tx_pause_frames;
-	mac_dev->set_rx_pause		= dtsec_accept_rx_pause_frames;
-	mac_dev->set_exception		= dtsec_set_exception;
-	mac_dev->set_allmulti		= dtsec_set_allmulti;
-	mac_dev->set_tstamp		= dtsec_set_tstamp;
-	mac_dev->set_multi		= fman_set_multi;
-	mac_dev->adjust_link            = adjust_link_dtsec;
-	mac_dev->enable			= dtsec_enable;
-	mac_dev->disable		= dtsec_disable;
-
-	err = set_fman_mac_params(mac_dev, &params);
-	if (err)
-		goto _return;
-	params.internal_phy_node = of_parse_phandle(mac_node, "tbi-handle", 0);
-
-	mac_dev->fman_mac = dtsec_config(&params);
-	if (!mac_dev->fman_mac) {
-		err = -EINVAL;
-		goto _return;
-	}
-
-	err = dtsec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = dtsec_cfg_pad_and_crc(mac_dev->fman_mac, true);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = dtsec_init(mac_dev->fman_mac);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	/* For 1G MAC, disable by default the MIB counters overflow interrupt */
-	err = mac_dev->set_exception(mac_dev->fman_mac,
-				     FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = dtsec_get_version(mac_dev->fman_mac, &version);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	dev_info(mac_dev->dev, "FMan dTSEC version: 0x%08x\n", version);
-
-	goto _return;
-
-_return_fm_mac_free:
-	dtsec_free(mac_dev->fman_mac);
-
-_return:
-	return err;
-}
-
-static int memac_initialization(struct mac_device *mac_dev,
-				struct device_node *mac_node)
-{
-	int			 err;
-	struct mac_priv_s	*priv;
-	struct fman_mac_params	 params;
-	struct fixed_phy_status *fixed_link;
-
-	priv = mac_dev->priv;
-	mac_dev->set_promisc		= memac_set_promiscuous;
-	mac_dev->change_addr		= memac_modify_mac_address;
-	mac_dev->add_hash_mac_addr	= memac_add_hash_mac_address;
-	mac_dev->remove_hash_mac_addr	= memac_del_hash_mac_address;
-	mac_dev->set_tx_pause		= memac_set_tx_pause_frames;
-	mac_dev->set_rx_pause		= memac_accept_rx_pause_frames;
-	mac_dev->set_exception		= memac_set_exception;
-	mac_dev->set_allmulti		= memac_set_allmulti;
-	mac_dev->set_tstamp		= memac_set_tstamp;
-	mac_dev->set_multi		= fman_set_multi;
-	mac_dev->adjust_link            = adjust_link_memac;
-	mac_dev->enable			= memac_enable;
-	mac_dev->disable		= memac_disable;
-
-	err = set_fman_mac_params(mac_dev, &params);
-	if (err)
-		goto _return;
-	params.internal_phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0);
-
-	if (params.max_speed == SPEED_10000)
-		params.phy_if = PHY_INTERFACE_MODE_XGMII;
-
-	mac_dev->fman_mac = memac_config(&params);
-	if (!mac_dev->fman_mac) {
-		err = -EINVAL;
-		goto _return;
-	}
-
-	err = memac_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = memac_cfg_reset_on_init(mac_dev->fman_mac, true);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
-		struct phy_device *phy;
-
-		err = of_phy_register_fixed_link(mac_node);
-		if (err)
-			goto _return_fm_mac_free;
-
-		fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL);
-		if (!fixed_link) {
-			err = -ENOMEM;
-			goto _return_fm_mac_free;
-		}
-
-		mac_dev->phy_node = of_node_get(mac_node);
-		phy = of_phy_find_device(mac_dev->phy_node);
-		if (!phy) {
-			err = -EINVAL;
-			of_node_put(mac_dev->phy_node);
-			goto _return_fixed_link_free;
-		}
-
-		fixed_link->link = phy->link;
-		fixed_link->speed = phy->speed;
-		fixed_link->duplex = phy->duplex;
-		fixed_link->pause = phy->pause;
-		fixed_link->asym_pause = phy->asym_pause;
-
-		put_device(&phy->mdio.dev);
-
-		err = memac_cfg_fixed_link(mac_dev->fman_mac, fixed_link);
-		if (err < 0)
-			goto _return_fixed_link_free;
-	}
-
-	err = memac_init(mac_dev->fman_mac);
-	if (err < 0)
-		goto _return_fixed_link_free;
-
-	dev_info(mac_dev->dev, "FMan MEMAC\n");
-
-	goto _return;
-
-_return_fixed_link_free:
-	kfree(fixed_link);
-_return_fm_mac_free:
-	memac_free(mac_dev->fman_mac);
-_return:
-	return err;
-}
-
 #define DTSEC_SUPPORTED \
 	(SUPPORTED_10baseT_Half \
 	| SUPPORTED_10baseT_Full \
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 15/28] net: fman: Mark mac methods static
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (13 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 14/28] net: fman: Move initialization to mac-specific files Sean Anderson
@ 2022-06-17 20:32 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 16/28] net: fman: Inline several functions into initialization Sean Anderson
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:32 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

These methods are no longer accessed outside of the driver file, so mark
them as static.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../net/ethernet/freescale/fman/fman_dtsec.c  | 48 ++++++++++---------
 .../net/ethernet/freescale/fman/fman_memac.c  | 45 +++++++++--------
 .../net/ethernet/freescale/fman/fman_tgec.c   | 40 +++++++++-------
 3 files changed, 72 insertions(+), 61 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 12ce079a356d..8da50c56c440 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -814,7 +814,7 @@ static void free_init_resources(struct fman_mac *dtsec)
 	dtsec->unicast_addr_hash = NULL;
 }
 
-int dtsec_cfg_max_frame_len(struct fman_mac *dtsec, u16 new_val)
+static int dtsec_cfg_max_frame_len(struct fman_mac *dtsec, u16 new_val)
 {
 	if (is_init_done(dtsec->dtsec_drv_param))
 		return -EINVAL;
@@ -824,7 +824,7 @@ int dtsec_cfg_max_frame_len(struct fman_mac *dtsec, u16 new_val)
 	return 0;
 }
 
-int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val)
+static int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val)
 {
 	if (is_init_done(dtsec->dtsec_drv_param))
 		return -EINVAL;
@@ -872,7 +872,7 @@ static void graceful_stop(struct fman_mac *dtsec)
 	}
 }
 
-int dtsec_enable(struct fman_mac *dtsec)
+static int dtsec_enable(struct fman_mac *dtsec)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 tmp;
@@ -891,7 +891,7 @@ int dtsec_enable(struct fman_mac *dtsec)
 	return 0;
 }
 
-int dtsec_disable(struct fman_mac *dtsec)
+static int dtsec_disable(struct fman_mac *dtsec)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 tmp;
@@ -909,9 +909,10 @@ int dtsec_disable(struct fman_mac *dtsec)
 	return 0;
 }
 
-int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
-			      u8 __maybe_unused priority,
-			      u16 pause_time, u16 __maybe_unused thresh_time)
+static int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
+				     u8 __maybe_unused priority,
+				     u16 pause_time,
+				     u16 __maybe_unused thresh_time)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 ptv = 0;
@@ -946,7 +947,7 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
 	return 0;
 }
 
-int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
+static int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 tmp;
@@ -968,7 +969,8 @@ int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
 	return 0;
 }
 
-int dtsec_modify_mac_address(struct fman_mac *dtsec, const enet_addr_t *enet_addr)
+static int dtsec_modify_mac_address(struct fman_mac *dtsec,
+				    const enet_addr_t *enet_addr)
 {
 	if (!is_init_done(dtsec->dtsec_drv_param))
 		return -EINVAL;
@@ -986,7 +988,8 @@ int dtsec_modify_mac_address(struct fman_mac *dtsec, const enet_addr_t *enet_add
 	return 0;
 }
 
-int dtsec_add_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr)
+static int dtsec_add_hash_mac_address(struct fman_mac *dtsec,
+				      enet_addr_t *eth_addr)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	struct eth_hash_entry *hash_entry;
@@ -1052,7 +1055,7 @@ int dtsec_add_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr)
 	return 0;
 }
 
-int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable)
+static int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable)
 {
 	u32 tmp;
 	struct dtsec_regs __iomem *regs = dtsec->regs;
@@ -1071,7 +1074,7 @@ int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable)
 	return 0;
 }
 
-int dtsec_set_tstamp(struct fman_mac *dtsec, bool enable)
+static int dtsec_set_tstamp(struct fman_mac *dtsec, bool enable)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 rctrl, tctrl;
@@ -1096,7 +1099,8 @@ int dtsec_set_tstamp(struct fman_mac *dtsec, bool enable)
 	return 0;
 }
 
-int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr)
+static int dtsec_del_hash_mac_address(struct fman_mac *dtsec,
+				      enet_addr_t *eth_addr)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	struct list_head *pos;
@@ -1167,7 +1171,7 @@ int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr)
 	return 0;
 }
 
-int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val)
+static int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 tmp;
@@ -1196,7 +1200,7 @@ int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val)
 	return 0;
 }
 
-int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
+static int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 tmp;
@@ -1230,7 +1234,7 @@ int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
 	return 0;
 }
 
-int dtsec_restart_autoneg(struct fman_mac *dtsec)
+static int dtsec_restart_autoneg(struct fman_mac *dtsec)
 {
 	u16 tmp_reg16;
 
@@ -1270,7 +1274,7 @@ static void adjust_link_dtsec(struct mac_device *mac_dev)
 			err);
 }
 
-int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version)
+static int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 
@@ -1282,8 +1286,8 @@ int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version)
 	return 0;
 }
 
-int dtsec_set_exception(struct fman_mac *dtsec,
-			enum fman_mac_exceptions exception, bool enable)
+static int dtsec_set_exception(struct fman_mac *dtsec,
+			       enum fman_mac_exceptions exception, bool enable)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	u32 bit_mask = 0;
@@ -1336,7 +1340,7 @@ int dtsec_set_exception(struct fman_mac *dtsec,
 	return 0;
 }
 
-int dtsec_init(struct fman_mac *dtsec)
+static int dtsec_init(struct fman_mac *dtsec)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
 	struct dtsec_cfg *dtsec_drv_param;
@@ -1430,7 +1434,7 @@ int dtsec_init(struct fman_mac *dtsec)
 	return 0;
 }
 
-int dtsec_free(struct fman_mac *dtsec)
+static int dtsec_free(struct fman_mac *dtsec)
 {
 	free_init_resources(dtsec);
 
@@ -1441,7 +1445,7 @@ int dtsec_free(struct fman_mac *dtsec)
 	return 0;
 }
 
-struct fman_mac *dtsec_config(struct fman_mac_params *params)
+static struct fman_mac *dtsec_config(struct fman_mac_params *params)
 {
 	struct fman_mac *dtsec;
 	struct dtsec_cfg *dtsec_drv_param;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 4300a21a553b..2b4df8f3a27a 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -686,7 +686,7 @@ static bool is_init_done(struct memac_cfg *memac_drv_params)
 	return false;
 }
 
-int memac_enable(struct fman_mac *memac)
+static int memac_enable(struct fman_mac *memac)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
@@ -701,7 +701,7 @@ int memac_enable(struct fman_mac *memac)
 	return 0;
 }
 
-int memac_disable(struct fman_mac *memac)
+static int memac_disable(struct fman_mac *memac)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
@@ -716,7 +716,7 @@ int memac_disable(struct fman_mac *memac)
 	return 0;
 }
 
-int memac_set_promiscuous(struct fman_mac *memac, bool new_val)
+static int memac_set_promiscuous(struct fman_mac *memac, bool new_val)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
@@ -735,7 +735,7 @@ int memac_set_promiscuous(struct fman_mac *memac, bool new_val)
 	return 0;
 }
 
-int memac_adjust_link(struct fman_mac *memac, u16 speed)
+static int memac_adjust_link(struct fman_mac *memac, u16 speed)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
@@ -792,7 +792,7 @@ static void adjust_link_memac(struct mac_device *mac_dev)
 			err);
 }
 
-int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val)
+static int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val)
 {
 	if (is_init_done(memac->memac_drv_param))
 		return -EINVAL;
@@ -802,7 +802,7 @@ int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val)
 	return 0;
 }
 
-int memac_cfg_reset_on_init(struct fman_mac *memac, bool enable)
+static int memac_cfg_reset_on_init(struct fman_mac *memac, bool enable)
 {
 	if (is_init_done(memac->memac_drv_param))
 		return -EINVAL;
@@ -812,8 +812,8 @@ int memac_cfg_reset_on_init(struct fman_mac *memac, bool enable)
 	return 0;
 }
 
-int memac_cfg_fixed_link(struct fman_mac *memac,
-			 struct fixed_phy_status *fixed_link)
+static int memac_cfg_fixed_link(struct fman_mac *memac,
+				struct fixed_phy_status *fixed_link)
 {
 	if (is_init_done(memac->memac_drv_param))
 		return -EINVAL;
@@ -823,8 +823,8 @@ int memac_cfg_fixed_link(struct fman_mac *memac,
 	return 0;
 }
 
-int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority,
-			      u16 pause_time, u16 thresh_time)
+static int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority,
+				     u16 pause_time, u16 thresh_time)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
@@ -861,7 +861,7 @@ int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority,
 	return 0;
 }
 
-int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en)
+static int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
@@ -880,7 +880,8 @@ int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en)
 	return 0;
 }
 
-int memac_modify_mac_address(struct fman_mac *memac, const enet_addr_t *enet_addr)
+static int memac_modify_mac_address(struct fman_mac *memac,
+				    const enet_addr_t *enet_addr)
 {
 	if (!is_init_done(memac->memac_drv_param))
 		return -EINVAL;
@@ -890,7 +891,8 @@ int memac_modify_mac_address(struct fman_mac *memac, const enet_addr_t *enet_add
 	return 0;
 }
 
-int memac_add_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr)
+static int memac_add_hash_mac_address(struct fman_mac *memac,
+				      enet_addr_t *eth_addr)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	struct eth_hash_entry *hash_entry;
@@ -923,7 +925,7 @@ int memac_add_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr)
 	return 0;
 }
 
-int memac_set_allmulti(struct fman_mac *memac, bool enable)
+static int memac_set_allmulti(struct fman_mac *memac, bool enable)
 {
 	u32 entry;
 	struct memac_regs __iomem *regs = memac->regs;
@@ -946,12 +948,13 @@ int memac_set_allmulti(struct fman_mac *memac, bool enable)
 	return 0;
 }
 
-int memac_set_tstamp(struct fman_mac *memac, bool enable)
+static int memac_set_tstamp(struct fman_mac *memac, bool enable)
 {
 	return 0; /* Always enabled. */
 }
 
-int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr)
+static int memac_del_hash_mac_address(struct fman_mac *memac,
+				      enet_addr_t *eth_addr)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	struct eth_hash_entry *hash_entry = NULL;
@@ -984,8 +987,8 @@ int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr)
 	return 0;
 }
 
-int memac_set_exception(struct fman_mac *memac,
-			enum fman_mac_exceptions exception, bool enable)
+static int memac_set_exception(struct fman_mac *memac,
+			       enum fman_mac_exceptions exception, bool enable)
 {
 	u32 bit_mask = 0;
 
@@ -1007,7 +1010,7 @@ int memac_set_exception(struct fman_mac *memac,
 	return 0;
 }
 
-int memac_init(struct fman_mac *memac)
+static int memac_init(struct fman_mac *memac)
 {
 	struct memac_cfg *memac_drv_param;
 	u8 i;
@@ -1124,7 +1127,7 @@ int memac_init(struct fman_mac *memac)
 	return 0;
 }
 
-int memac_free(struct fman_mac *memac)
+static int memac_free(struct fman_mac *memac)
 {
 	free_init_resources(memac);
 
@@ -1137,7 +1140,7 @@ int memac_free(struct fman_mac *memac)
 	return 0;
 }
 
-struct fman_mac *memac_config(struct fman_mac_params *params)
+static struct fman_mac *memac_config(struct fman_mac_params *params)
 {
 	struct fman_mac *memac;
 	struct memac_cfg *memac_drv_param;
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index 2f2c4ef45f6f..ca0e00386c66 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -393,7 +393,7 @@ static bool is_init_done(struct tgec_cfg *cfg)
 	return false;
 }
 
-int tgec_enable(struct fman_mac *tgec)
+static int tgec_enable(struct fman_mac *tgec)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 	u32 tmp;
@@ -408,7 +408,7 @@ int tgec_enable(struct fman_mac *tgec)
 	return 0;
 }
 
-int tgec_disable(struct fman_mac *tgec)
+static int tgec_disable(struct fman_mac *tgec)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 	u32 tmp;
@@ -423,7 +423,7 @@ int tgec_disable(struct fman_mac *tgec)
 	return 0;
 }
 
-int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val)
+static int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 	u32 tmp;
@@ -441,7 +441,7 @@ int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val)
 	return 0;
 }
 
-int tgec_cfg_max_frame_len(struct fman_mac *tgec, u16 new_val)
+static int tgec_cfg_max_frame_len(struct fman_mac *tgec, u16 new_val)
 {
 	if (is_init_done(tgec->cfg))
 		return -EINVAL;
@@ -451,8 +451,9 @@ int tgec_cfg_max_frame_len(struct fman_mac *tgec, u16 new_val)
 	return 0;
 }
 
-int tgec_set_tx_pause_frames(struct fman_mac *tgec, u8 __maybe_unused priority,
-			     u16 pause_time, u16 __maybe_unused thresh_time)
+static int tgec_set_tx_pause_frames(struct fman_mac *tgec,
+				    u8 __maybe_unused priority, u16 pause_time,
+				    u16 __maybe_unused thresh_time)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 
@@ -464,7 +465,7 @@ int tgec_set_tx_pause_frames(struct fman_mac *tgec, u8 __maybe_unused priority,
 	return 0;
 }
 
-int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en)
+static int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 	u32 tmp;
@@ -482,7 +483,8 @@ int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en)
 	return 0;
 }
 
-int tgec_modify_mac_address(struct fman_mac *tgec, const enet_addr_t *p_enet_addr)
+static int tgec_modify_mac_address(struct fman_mac *tgec,
+				   const enet_addr_t *p_enet_addr)
 {
 	if (!is_init_done(tgec->cfg))
 		return -EINVAL;
@@ -493,7 +495,8 @@ int tgec_modify_mac_address(struct fman_mac *tgec, const enet_addr_t *p_enet_add
 	return 0;
 }
 
-int tgec_add_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr)
+static int tgec_add_hash_mac_address(struct fman_mac *tgec,
+				     enet_addr_t *eth_addr)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 	struct eth_hash_entry *hash_entry;
@@ -530,7 +533,7 @@ int tgec_add_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr)
 	return 0;
 }
 
-int tgec_set_allmulti(struct fman_mac *tgec, bool enable)
+static int tgec_set_allmulti(struct fman_mac *tgec, bool enable)
 {
 	u32 entry;
 	struct tgec_regs __iomem *regs = tgec->regs;
@@ -553,7 +556,7 @@ int tgec_set_allmulti(struct fman_mac *tgec, bool enable)
 	return 0;
 }
 
-int tgec_set_tstamp(struct fman_mac *tgec, bool enable)
+static int tgec_set_tstamp(struct fman_mac *tgec, bool enable)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 	u32 tmp;
@@ -573,7 +576,8 @@ int tgec_set_tstamp(struct fman_mac *tgec, bool enable)
 	return 0;
 }
 
-int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr)
+static int tgec_del_hash_mac_address(struct fman_mac *tgec,
+				     enet_addr_t *eth_addr)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 	struct eth_hash_entry *hash_entry = NULL;
@@ -614,7 +618,7 @@ static void adjust_link_void(struct mac_device *mac_dev)
 {
 }
 
-int tgec_get_version(struct fman_mac *tgec, u32 *mac_version)
+static int tgec_get_version(struct fman_mac *tgec, u32 *mac_version)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 
@@ -626,8 +630,8 @@ int tgec_get_version(struct fman_mac *tgec, u32 *mac_version)
 	return 0;
 }
 
-int tgec_set_exception(struct fman_mac *tgec,
-		       enum fman_mac_exceptions exception, bool enable)
+static int tgec_set_exception(struct fman_mac *tgec,
+			      enum fman_mac_exceptions exception, bool enable)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
 	u32 bit_mask = 0;
@@ -653,7 +657,7 @@ int tgec_set_exception(struct fman_mac *tgec,
 	return 0;
 }
 
-int tgec_init(struct fman_mac *tgec)
+static int tgec_init(struct fman_mac *tgec)
 {
 	struct tgec_cfg *cfg;
 	enet_addr_t eth_addr;
@@ -736,7 +740,7 @@ int tgec_init(struct fman_mac *tgec)
 	return 0;
 }
 
-int tgec_free(struct fman_mac *tgec)
+static int tgec_free(struct fman_mac *tgec)
 {
 	free_init_resources(tgec);
 
@@ -746,7 +750,7 @@ int tgec_free(struct fman_mac *tgec)
 	return 0;
 }
 
-struct fman_mac *tgec_config(struct fman_mac_params *params)
+static struct fman_mac *tgec_config(struct fman_mac_params *params)
 {
 	struct fman_mac *tgec;
 	struct tgec_cfg *cfg;
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 16/28] net: fman: Inline several functions into initialization
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (14 preceding siblings ...)
  2022-06-17 20:32 ` [PATCH net-next 15/28] net: fman: Mark mac methods static Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 17/28] net: fman: Remove internal_phy_node from params Sean Anderson
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

There are several small functions which weer only necessary because the
initialization functions didn't have access to the mac private data. Now
that they do, just do things directly.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../net/ethernet/freescale/fman/fman_dtsec.c  | 59 +++----------------
 .../net/ethernet/freescale/fman/fman_memac.c  | 47 ++-------------
 .../net/ethernet/freescale/fman/fman_tgec.c   | 43 +++-----------
 3 files changed, 21 insertions(+), 128 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 8da50c56c440..44718c34c899 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -814,26 +814,6 @@ static void free_init_resources(struct fman_mac *dtsec)
 	dtsec->unicast_addr_hash = NULL;
 }
 
-static int dtsec_cfg_max_frame_len(struct fman_mac *dtsec, u16 new_val)
-{
-	if (is_init_done(dtsec->dtsec_drv_param))
-		return -EINVAL;
-
-	dtsec->dtsec_drv_param->maximum_frame = new_val;
-
-	return 0;
-}
-
-static int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val)
-{
-	if (is_init_done(dtsec->dtsec_drv_param))
-		return -EINVAL;
-
-	dtsec->dtsec_drv_param->tx_pad_crc = new_val;
-
-	return 0;
-}
-
 static void graceful_start(struct fman_mac *dtsec)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
@@ -1274,18 +1254,6 @@ static void adjust_link_dtsec(struct mac_device *mac_dev)
 			err);
 }
 
-static int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version)
-{
-	struct dtsec_regs __iomem *regs = dtsec->regs;
-
-	if (!is_init_done(dtsec->dtsec_drv_param))
-		return -EINVAL;
-
-	*mac_version = ioread32be(&regs->tsec_id);
-
-	return 0;
-}
-
 static int dtsec_set_exception(struct fman_mac *dtsec,
 			       enum fman_mac_exceptions exception, bool enable)
 {
@@ -1526,7 +1494,7 @@ int dtsec_initialization(struct mac_device *mac_dev,
 	int			err;
 	struct mac_priv_s	*priv;
 	struct fman_mac_params	params;
-	u32			version;
+	struct fman_mac		*dtsec;
 
 	priv = mac_dev->priv;
 	mac_dev->set_promisc		= dtsec_set_promiscuous;
@@ -1554,34 +1522,25 @@ int dtsec_initialization(struct mac_device *mac_dev,
 		goto _return;
 	}
 
-	err = dtsec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = dtsec_cfg_pad_and_crc(mac_dev->fman_mac, true);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = dtsec_init(mac_dev->fman_mac);
+	dtsec = mac_dev->fman_mac;
+	dtsec->dtsec_drv_param->maximum_frame = fman_get_max_frm();
+	dtsec->dtsec_drv_param->tx_pad_crc = true;
+	err = dtsec_init(dtsec);
 	if (err < 0)
 		goto _return_fm_mac_free;
 
 	/* For 1G MAC, disable by default the MIB counters overflow interrupt */
-	err = mac_dev->set_exception(mac_dev->fman_mac,
-				     FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false);
+	err = dtsec_set_exception(dtsec, FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false);
 	if (err < 0)
 		goto _return_fm_mac_free;
 
-	err = dtsec_get_version(mac_dev->fman_mac, &version);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	dev_info(mac_dev->dev, "FMan dTSEC version: 0x%08x\n", version);
+	dev_info(mac_dev->dev, "FMan dTSEC version: 0x%08x\n",
+		 ioread32be(&dtsec->regs->tsec_id));
 
 	goto _return;
 
 _return_fm_mac_free:
-	dtsec_free(mac_dev->fman_mac);
+	dtsec_free(dtsec);
 
 _return:
 	return err;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 2b4df8f3a27a..a97815287b31 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -792,37 +792,6 @@ static void adjust_link_memac(struct mac_device *mac_dev)
 			err);
 }
 
-static int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val)
-{
-	if (is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
-	memac->memac_drv_param->max_frame_length = new_val;
-
-	return 0;
-}
-
-static int memac_cfg_reset_on_init(struct fman_mac *memac, bool enable)
-{
-	if (is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
-	memac->memac_drv_param->reset_on_init = enable;
-
-	return 0;
-}
-
-static int memac_cfg_fixed_link(struct fman_mac *memac,
-				struct fixed_phy_status *fixed_link)
-{
-	if (is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
-	memac->memac_drv_param->fixed_link = fixed_link;
-
-	return 0;
-}
-
 static int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority,
 				     u16 pause_time, u16 thresh_time)
 {
@@ -1207,6 +1176,7 @@ int memac_initialization(struct mac_device *mac_dev,
 	struct mac_priv_s	*priv;
 	struct fman_mac_params	 params;
 	struct fixed_phy_status *fixed_link;
+	struct fman_mac		*memac;
 
 	priv = mac_dev->priv;
 	mac_dev->set_promisc		= memac_set_promiscuous;
@@ -1237,13 +1207,9 @@ int memac_initialization(struct mac_device *mac_dev,
 		goto _return;
 	}
 
-	err = memac_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = memac_cfg_reset_on_init(mac_dev->fman_mac, true);
-	if (err < 0)
-		goto _return_fm_mac_free;
+	memac = mac_dev->fman_mac;
+	memac->memac_drv_param->max_frame_length = fman_get_max_frm();
+	memac->memac_drv_param->reset_on_init = true;
 
 	if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
 		struct phy_device *phy;
@@ -1273,10 +1239,7 @@ int memac_initialization(struct mac_device *mac_dev,
 		fixed_link->asym_pause = phy->asym_pause;
 
 		put_device(&phy->mdio.dev);
-
-		err = memac_cfg_fixed_link(mac_dev->fman_mac, fixed_link);
-		if (err < 0)
-			goto _return_fixed_link_free;
+		memac->memac_drv_param->fixed_link = fixed_link;
 	}
 
 	err = memac_init(mac_dev->fman_mac);
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index ca0e00386c66..32ee1674ff2f 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -441,16 +441,6 @@ static int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val)
 	return 0;
 }
 
-static int tgec_cfg_max_frame_len(struct fman_mac *tgec, u16 new_val)
-{
-	if (is_init_done(tgec->cfg))
-		return -EINVAL;
-
-	tgec->cfg->max_frame_length = new_val;
-
-	return 0;
-}
-
 static int tgec_set_tx_pause_frames(struct fman_mac *tgec,
 				    u8 __maybe_unused priority, u16 pause_time,
 				    u16 __maybe_unused thresh_time)
@@ -618,18 +608,6 @@ static void adjust_link_void(struct mac_device *mac_dev)
 {
 }
 
-static int tgec_get_version(struct fman_mac *tgec, u32 *mac_version)
-{
-	struct tgec_regs __iomem *regs = tgec->regs;
-
-	if (!is_init_done(tgec->cfg))
-		return -EINVAL;
-
-	*mac_version = ioread32be(&regs->tgec_id);
-
-	return 0;
-}
-
 static int tgec_set_exception(struct fman_mac *tgec,
 			      enum fman_mac_exceptions exception, bool enable)
 {
@@ -809,7 +787,7 @@ int tgec_initialization(struct mac_device *mac_dev,
 {
 	int err;
 	struct fman_mac_params	params;
-	u32			version;
+	struct fman_mac		*tgec;
 
 	mac_dev->set_promisc		= tgec_set_promiscuous;
 	mac_dev->change_addr		= tgec_modify_mac_address;
@@ -835,26 +813,19 @@ int tgec_initialization(struct mac_device *mac_dev,
 		goto _return;
 	}
 
-	err = tgec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	err = tgec_init(mac_dev->fman_mac);
+	tgec = mac_dev->fman_mac;
+	tgec->cfg->max_frame_length = fman_get_max_frm();
+	err = tgec_init(tgec);
 	if (err < 0)
 		goto _return_fm_mac_free;
 
 	/* For 10G MAC, disable Tx ECC exception */
-	err = mac_dev->set_exception(mac_dev->fman_mac,
-				     FM_MAC_EX_10G_TX_ECC_ER, false);
+	err = tgec_set_exception(tgec, FM_MAC_EX_10G_TX_ECC_ER, false);
 	if (err < 0)
 		goto _return_fm_mac_free;
 
-	err = tgec_get_version(mac_dev->fman_mac, &version);
-	if (err < 0)
-		goto _return_fm_mac_free;
-
-	pr_info("FMan XGEC version: 0x%08x\n", version);
-
+	pr_info("FMan XGEC version: 0x%08x\n",
+		ioread32be(&tgec->regs->tgec_id));
 	goto _return;
 
 _return_fm_mac_free:
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 17/28] net: fman: Remove internal_phy_node from params
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (15 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 16/28] net: fman: Inline several functions into initialization Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 18/28] net: fman: Map the base address once Sean Anderson
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

This member was used to pass the phy node between mac_probe and the
mac-specific initialization function. But now that the phy node is
gotten in the initialization function, this parameter does not serve a
purpose. Remove it, and do the grabbing of the node/grabbing of the phy
in the same place.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../net/ethernet/freescale/fman/fman_dtsec.c  | 33 +++++++++---------
 .../net/ethernet/freescale/fman/fman_mac.h    |  2 --
 .../net/ethernet/freescale/fman/fman_memac.c  | 34 +++++++++----------
 3 files changed, 34 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 44718c34c899..b94fbc38cdd9 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -1463,26 +1463,11 @@ static struct fman_mac *dtsec_config(struct fman_mac_params *params)
 	dtsec->fm = params->fm;
 	dtsec->basex_if = params->basex_if;
 
-	if (!params->internal_phy_node) {
-		pr_err("TBI PHY node is not available\n");
-		goto err_dtsec_drv_param;
-	}
-
-	dtsec->tbiphy = of_phy_find_device(params->internal_phy_node);
-	if (!dtsec->tbiphy) {
-		pr_err("of_phy_find_device (TBI PHY) failed\n");
-		goto err_dtsec_drv_param;
-	}
-
-	put_device(&dtsec->tbiphy->mdio.dev);
-
 	/* Save FMan revision */
 	fman_get_revision(dtsec->fm, &dtsec->fm_rev_info);
 
 	return dtsec;
 
-err_dtsec_drv_param:
-	kfree(dtsec_drv_param);
 err_dtsec:
 	kfree(dtsec);
 	return NULL;
@@ -1495,6 +1480,7 @@ int dtsec_initialization(struct mac_device *mac_dev,
 	struct mac_priv_s	*priv;
 	struct fman_mac_params	params;
 	struct fman_mac		*dtsec;
+	struct device_node	*phy_node;
 
 	priv = mac_dev->priv;
 	mac_dev->set_promisc		= dtsec_set_promiscuous;
@@ -1514,7 +1500,6 @@ int dtsec_initialization(struct mac_device *mac_dev,
 	err = set_fman_mac_params(mac_dev, &params);
 	if (err)
 		goto _return;
-	params.internal_phy_node = of_parse_phandle(mac_node, "tbi-handle", 0);
 
 	mac_dev->fman_mac = dtsec_config(&params);
 	if (!mac_dev->fman_mac) {
@@ -1525,6 +1510,22 @@ int dtsec_initialization(struct mac_device *mac_dev,
 	dtsec = mac_dev->fman_mac;
 	dtsec->dtsec_drv_param->maximum_frame = fman_get_max_frm();
 	dtsec->dtsec_drv_param->tx_pad_crc = true;
+
+	phy_node = of_parse_phandle(mac_node, "tbi-handle", 0);
+	if (!phy_node) {
+		pr_err("TBI PHY node is not available\n");
+		err = -EINVAL;
+		goto _return_fm_mac_free;
+	}
+
+	dtsec->tbiphy = of_phy_find_device(phy_node);
+	if (!dtsec->tbiphy) {
+		pr_err("of_phy_find_device (TBI PHY) failed\n");
+		err = -EINVAL;
+		goto _return_fm_mac_free;
+	}
+	put_device(&dtsec->tbiphy->mdio.dev);
+
 	err = dtsec_init(dtsec);
 	if (err < 0)
 		goto _return_fm_mac_free;
diff --git a/drivers/net/ethernet/freescale/fman/fman_mac.h b/drivers/net/ethernet/freescale/fman/fman_mac.h
index 418d1de85702..7774af6463e5 100644
--- a/drivers/net/ethernet/freescale/fman/fman_mac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_mac.h
@@ -190,8 +190,6 @@ struct fman_mac_params {
 	 * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps
 	*/
 	bool basex_if;
-	/* Pointer to TBI/PCS PHY node, used for TBI/PCS PHY access */
-	struct device_node *internal_phy_node;
 };
 
 struct eth_hash_t {
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index a97815287b31..cfa451c98d74 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -1150,22 +1150,6 @@ static struct fman_mac *memac_config(struct fman_mac_params *params)
 	/* Save FMan revision */
 	fman_get_revision(memac->fm, &memac->fm_rev_info);
 
-	if (memac->phy_if == PHY_INTERFACE_MODE_SGMII ||
-	    memac->phy_if == PHY_INTERFACE_MODE_QSGMII) {
-		if (!params->internal_phy_node) {
-			pr_err("PCS PHY node is not available\n");
-			memac_free(memac);
-			return NULL;
-		}
-
-		memac->pcsphy = of_phy_find_device(params->internal_phy_node);
-		if (!memac->pcsphy) {
-			pr_err("of_phy_find_device (PCS PHY) failed\n");
-			memac_free(memac);
-			return NULL;
-		}
-	}
-
 	return memac;
 }
 
@@ -1173,6 +1157,7 @@ int memac_initialization(struct mac_device *mac_dev,
 			 struct device_node *mac_node)
 {
 	int			 err;
+	struct device_node	*phy_node;
 	struct mac_priv_s	*priv;
 	struct fman_mac_params	 params;
 	struct fixed_phy_status *fixed_link;
@@ -1196,7 +1181,6 @@ int memac_initialization(struct mac_device *mac_dev,
 	err = set_fman_mac_params(mac_dev, &params);
 	if (err)
 		goto _return;
-	params.internal_phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0);
 
 	if (params.max_speed == SPEED_10000)
 		params.phy_if = PHY_INTERFACE_MODE_XGMII;
@@ -1210,6 +1194,22 @@ int memac_initialization(struct mac_device *mac_dev,
 	memac = mac_dev->fman_mac;
 	memac->memac_drv_param->max_frame_length = fman_get_max_frm();
 	memac->memac_drv_param->reset_on_init = true;
+	if (memac->phy_if == PHY_INTERFACE_MODE_SGMII ||
+	    memac->phy_if == PHY_INTERFACE_MODE_QSGMII) {
+		phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0);
+		if (!phy_node) {
+			pr_err("PCS PHY node is not available\n");
+			err = -EINVAL;
+			goto _return_fm_mac_free;
+		}
+
+		memac->pcsphy = of_phy_find_device(phy_node);
+		if (!memac->pcsphy) {
+			pr_err("of_phy_find_device (PCS PHY) failed\n");
+			err = -EINVAL;
+			goto _return_fm_mac_free;
+		}
+	}
 
 	if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
 		struct phy_device *phy;
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 18/28] net: fman: Map the base address once
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (16 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 17/28] net: fman: Remove internal_phy_node from params Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-18  2:01   ` kernel test robot
  2022-06-17 20:33 ` [PATCH net-next 19/28] net: fman: Pass params directly to mac init Sean Anderson
                   ` (9 subsequent siblings)
  27 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

We don't need to remap the base address from the resource twice (once in
mac_probe() and again in set_fman_mac_params()). We still need the
resource to get the end address, but we can use a single function call
to get both at once.

While we're at it, use platform_get_mem_or_io and devm_request_resource
to map the resource. I think this is the more "correct" way to do things
here, since we use the pdev resource, instead of creating a new one.
It's still a bit tricy, since we need to ensure that the resource is a
child of the fman region when it gets requested.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  4 +--
 .../ethernet/freescale/dpaa/dpaa_eth_sysfs.c  |  2 +-
 drivers/net/ethernet/freescale/fman/mac.c     | 35 +++++++------------
 drivers/net/ethernet/freescale/fman/mac.h     |  3 +-
 4 files changed, 17 insertions(+), 27 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index a548598b2e2d..d443d53c4504 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -218,8 +218,8 @@ static int dpaa_netdev_init(struct net_device *net_dev,
 	net_dev->netdev_ops = dpaa_ops;
 	mac_addr = priv->mac_dev->addr;
 
-	net_dev->mem_start = priv->mac_dev->res->start;
-	net_dev->mem_end = priv->mac_dev->res->end;
+	net_dev->mem_start = (unsigned long)priv->mac_dev->vaddr;
+	net_dev->mem_end = (unsigned long)priv->mac_dev->vaddr_end;
 
 	net_dev->min_mtu = ETH_MIN_MTU;
 	net_dev->max_mtu = dpaa_get_max_mtu();
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c
index 4fee74c024bd..258eb6c8f4c0 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c
@@ -18,7 +18,7 @@ static ssize_t dpaa_eth_show_addr(struct device *dev,
 
 	if (mac_dev)
 		return sprintf(buf, "%llx",
-				(unsigned long long)mac_dev->res->start);
+				(unsigned long long)mac_dev->vaddr);
 	else
 		return sprintf(buf, "none");
 }
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index e33d8b87f70f..e8ef307bd1ca 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -28,7 +28,6 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("FSL FMan MAC API based driver");
 
 struct mac_priv_s {
-	void __iomem			*vaddr;
 	u8				cell_index;
 	struct fman			*fman;
 	/* List of multicast addresses */
@@ -67,12 +66,7 @@ int set_fman_mac_params(struct mac_device *mac_dev,
 {
 	struct mac_priv_s *priv = mac_dev->priv;
 
-	params->base_addr = (typeof(params->base_addr))
-		devm_ioremap(mac_dev->dev, mac_dev->res->start,
-			     resource_size(mac_dev->res));
-	if (!params->base_addr)
-		return -ENOMEM;
-
+	params->base_addr = mac_dev->vaddr;
 	memcpy(&params->addr, mac_dev->addr, sizeof(mac_dev->addr));
 	params->max_speed	= priv->max_speed;
 	params->phy_if		= mac_dev->phy_if;
@@ -309,7 +303,7 @@ static int mac_probe(struct platform_device *_of_dev)
 	struct device_node	*mac_node, *dev_node;
 	struct mac_device	*mac_dev;
 	struct platform_device	*of_dev;
-	struct resource		 res;
+	struct resource		*res;
 	struct mac_priv_s	*priv;
 	u32			 val;
 	u8			fman_id;
@@ -372,30 +366,25 @@ static int mac_probe(struct platform_device *_of_dev)
 	of_node_put(dev_node);
 
 	/* Get the address of the memory mapped registers */
-	err = of_address_to_resource(mac_node, 0, &res);
-	if (err < 0) {
-		dev_err(dev, "of_address_to_resource(%pOF) = %d\n",
-			mac_node, err);
-		goto _return_of_node_put;
+	res = platform_get_mem_or_io(_of_dev, 0);
+	if (!res) {
+		dev_err(dev, "could not get registers\n");
+		return -EINVAL;
 	}
 
-	mac_dev->res = __devm_request_region(dev,
-					     fman_get_mem_region(priv->fman),
-					     res.start, resource_size(&res),
-					     "mac");
-	if (!mac_dev->res) {
-		dev_err(dev, "__devm_request_mem_region(mac) failed\n");
-		err = -EBUSY;
+	err = devm_request_resource(dev, fman_get_mem_region(priv->fman), res);
+	if (err) {
+		dev_err_probe(dev, err, "could not request resource\n");
 		goto _return_of_node_put;
 	}
 
-	priv->vaddr = devm_ioremap(dev, mac_dev->res->start,
-				   resource_size(mac_dev->res));
-	if (!priv->vaddr) {
+	mac_dev->vaddr = devm_ioremap(dev, res->start, resource_size(res));
+	if (!mac_dev->vaddr) {
 		dev_err(dev, "devm_ioremap() failed\n");
 		err = -EIO;
 		goto _return_of_node_put;
 	}
+	mac_dev->vaddr_end = (void *)res->end;
 
 	if (!of_device_is_available(mac_node)) {
 		err = -ENODEV;
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index da410a7d00c9..7aa71b05bd3e 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -19,8 +19,9 @@ struct fman_mac;
 struct mac_priv_s;
 
 struct mac_device {
+	void __iomem		*vaddr;
+	void __iomem		*vaddr_end;
 	struct device		*dev;
-	struct resource		*res;
 	u8			 addr[ETH_ALEN];
 	struct fman_port	*port[2];
 	u32			 if_support;
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 19/28] net: fman: Pass params directly to mac init
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (17 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 18/28] net: fman: Map the base address once Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 20/28] net: fman: Use mac_dev for some params Sean Anderson
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

Instead of having the mac init functions call back into the fman core to
get their params, just pass them directly to the init functions.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../net/ethernet/freescale/fman/fman_dtsec.c  | 10 ++----
 .../net/ethernet/freescale/fman/fman_memac.c  | 14 +++-----
 .../net/ethernet/freescale/fman/fman_memac.h  |  3 +-
 .../net/ethernet/freescale/fman/fman_tgec.c   | 10 ++----
 .../net/ethernet/freescale/fman/fman_tgec.h   |  3 +-
 drivers/net/ethernet/freescale/fman/mac.c     | 36 ++++++++-----------
 drivers/net/ethernet/freescale/fman/mac.h     |  2 --
 7 files changed, 30 insertions(+), 48 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index b94fbc38cdd9..7acdaed67d9d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -1474,11 +1474,11 @@ static struct fman_mac *dtsec_config(struct fman_mac_params *params)
 }
 
 int dtsec_initialization(struct mac_device *mac_dev,
-			 struct device_node *mac_node)
+			 struct device_node *mac_node,
+			 struct fman_mac_params *params)
 {
 	int			err;
 	struct mac_priv_s	*priv;
-	struct fman_mac_params	params;
 	struct fman_mac		*dtsec;
 	struct device_node	*phy_node;
 
@@ -1497,11 +1497,7 @@ int dtsec_initialization(struct mac_device *mac_dev,
 	mac_dev->enable			= dtsec_enable;
 	mac_dev->disable		= dtsec_disable;
 
-	err = set_fman_mac_params(mac_dev, &params);
-	if (err)
-		goto _return;
-
-	mac_dev->fman_mac = dtsec_config(&params);
+	mac_dev->fman_mac = dtsec_config(params);
 	if (!mac_dev->fman_mac) {
 		err = -EINVAL;
 		goto _return;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index cfa451c98d74..fa84467e10da 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -1154,12 +1154,12 @@ static struct fman_mac *memac_config(struct fman_mac_params *params)
 }
 
 int memac_initialization(struct mac_device *mac_dev,
-			 struct device_node *mac_node)
+			 struct device_node *mac_node,
+			 struct fman_mac_params *params)
 {
 	int			 err;
 	struct device_node	*phy_node;
 	struct mac_priv_s	*priv;
-	struct fman_mac_params	 params;
 	struct fixed_phy_status *fixed_link;
 	struct fman_mac		*memac;
 
@@ -1178,14 +1178,10 @@ int memac_initialization(struct mac_device *mac_dev,
 	mac_dev->enable			= memac_enable;
 	mac_dev->disable		= memac_disable;
 
-	err = set_fman_mac_params(mac_dev, &params);
-	if (err)
-		goto _return;
+	if (params->max_speed == SPEED_10000)
+		params->phy_if = PHY_INTERFACE_MODE_XGMII;
 
-	if (params.max_speed == SPEED_10000)
-		params.phy_if = PHY_INTERFACE_MODE_XGMII;
-
-	mac_dev->fman_mac = memac_config(&params);
+	mac_dev->fman_mac = memac_config(params);
 	if (!mac_dev->fman_mac) {
 		err = -EINVAL;
 		goto _return;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.h b/drivers/net/ethernet/freescale/fman/fman_memac.h
index a58215a3b1d9..5a3a14f9684f 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.h
@@ -14,6 +14,7 @@
 struct mac_device;
 
 int memac_initialization(struct mac_device *mac_dev,
-			 struct device_node *mac_node);
+			 struct device_node *mac_node,
+			 struct fman_mac_params *params);
 
 #endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index 32ee1674ff2f..f34f89e46a6f 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -783,10 +783,10 @@ static struct fman_mac *tgec_config(struct fman_mac_params *params)
 }
 
 int tgec_initialization(struct mac_device *mac_dev,
-			struct device_node *mac_node)
+			struct device_node *mac_node,
+			struct fman_mac_params *params)
 {
 	int err;
-	struct fman_mac_params	params;
 	struct fman_mac		*tgec;
 
 	mac_dev->set_promisc		= tgec_set_promiscuous;
@@ -803,11 +803,7 @@ int tgec_initialization(struct mac_device *mac_dev,
 	mac_dev->enable			= tgec_enable;
 	mac_dev->disable		= tgec_disable;
 
-	err = set_fman_mac_params(mac_dev, &params);
-	if (err)
-		goto _return;
-
-	mac_dev->fman_mac = tgec_config(&params);
+	mac_dev->fman_mac = tgec_config(params);
 	if (!mac_dev->fman_mac) {
 		err = -EINVAL;
 		goto _return;
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.h b/drivers/net/ethernet/freescale/fman/fman_tgec.h
index 2e45b9fea352..768b8d165e05 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.h
@@ -11,6 +11,7 @@
 struct mac_device;
 
 int tgec_initialization(struct mac_device *mac_dev,
-			struct device_node *mac_node);
+			struct device_node *mac_node,
+			struct fman_mac_params *params);
 
 #endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index e8ef307bd1ca..5d08c4696c21 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -61,25 +61,6 @@ static void mac_exception(void *handle, enum fman_mac_exceptions ex)
 		__func__, ex);
 }
 
-int set_fman_mac_params(struct mac_device *mac_dev,
-			struct fman_mac_params *params)
-{
-	struct mac_priv_s *priv = mac_dev->priv;
-
-	params->base_addr = mac_dev->vaddr;
-	memcpy(&params->addr, mac_dev->addr, sizeof(mac_dev->addr));
-	params->max_speed	= priv->max_speed;
-	params->phy_if		= mac_dev->phy_if;
-	params->basex_if	= false;
-	params->mac_id		= priv->cell_index;
-	params->fm		= (void *)priv->fman;
-	params->exception_cb	= mac_exception;
-	params->event_cb	= mac_exception;
-	params->dev_id		= mac_dev;
-
-	return 0;
-}
-
 int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
 {
 	struct mac_priv_s	*priv;
@@ -298,13 +279,15 @@ MODULE_DEVICE_TABLE(of, mac_match);
 static int mac_probe(struct platform_device *_of_dev)
 {
 	int			 err, i, nph;
-	int (*init)(struct mac_device *mac_dev, struct device_node *mac_node);
+	int (*init)(struct mac_device *mac_dev, struct device_node *mac_node,
+		    struct fman_mac_params *params);
 	struct device		*dev;
 	struct device_node	*mac_node, *dev_node;
 	struct mac_device	*mac_dev;
 	struct platform_device	*of_dev;
 	struct resource		*res;
 	struct mac_priv_s	*priv;
+	struct fman_mac_params	 params;
 	u32			 val;
 	u8			fman_id;
 	phy_interface_t          phy_if;
@@ -478,7 +461,18 @@ static int mac_probe(struct platform_device *_of_dev)
 	/* Get the rest of the PHY information */
 	mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0);
 
-	err = init(mac_dev, mac_node);
+	params.base_addr = mac_dev->vaddr;
+	memcpy(&params.addr, mac_dev->addr, sizeof(mac_dev->addr));
+	params.max_speed	= priv->max_speed;
+	params.phy_if		= mac_dev->phy_if;
+	params.basex_if		= false;
+	params.mac_id		= priv->cell_index;
+	params.fm		= (void *)priv->fman;
+	params.exception_cb	= mac_exception;
+	params.event_cb		= mac_exception;
+	params.dev_id		= mac_dev;
+
+	err = init(mac_dev, mac_node, &params);
 	if (err < 0) {
 		dev_err(dev, "mac_dev->init() = %d\n", err);
 		of_node_put(mac_dev->phy_node);
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index 7aa71b05bd3e..c5fb4d46210f 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -72,8 +72,6 @@ int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx);
 
 void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause,
 			bool *tx_pause);
-int set_fman_mac_params(struct mac_device *mac_dev,
-			struct fman_mac_params *params);
 int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev);
 
 #endif	/* __MAC_H */
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 20/28] net: fman: Use mac_dev for some params
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (18 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 19/28] net: fman: Pass params directly to mac init Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 21/28] net: fman: Clean up error handling Sean Anderson
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

Some params are already present in mac_dev. Use them directly instead of
passing them through params.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../net/ethernet/freescale/fman/fman_dtsec.c    | 16 +++++++---------
 drivers/net/ethernet/freescale/fman/fman_mac.h  |  7 -------
 .../net/ethernet/freescale/fman/fman_memac.c    | 17 ++++++++---------
 drivers/net/ethernet/freescale/fman/fman_tgec.c | 12 +++++-------
 drivers/net/ethernet/freescale/fman/mac.c       | 10 ++--------
 5 files changed, 22 insertions(+), 40 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 7acdaed67d9d..c5cc20b9ebed 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -1413,13 +1413,11 @@ static int dtsec_free(struct fman_mac *dtsec)
 	return 0;
 }
 
-static struct fman_mac *dtsec_config(struct fman_mac_params *params)
+static struct fman_mac *dtsec_config(struct mac_device *mac_dev,
+				     struct fman_mac_params *params)
 {
 	struct fman_mac *dtsec;
 	struct dtsec_cfg *dtsec_drv_param;
-	void __iomem *base_addr;
-
-	base_addr = params->base_addr;
 
 	/* allocate memory for the UCC GETH data structure. */
 	dtsec = kzalloc(sizeof(*dtsec), GFP_KERNEL);
@@ -1436,10 +1434,10 @@ static struct fman_mac *dtsec_config(struct fman_mac_params *params)
 
 	set_dflts(dtsec_drv_param);
 
-	dtsec->regs = base_addr;
-	dtsec->addr = ENET_ADDR_TO_UINT64(params->addr);
+	dtsec->regs = mac_dev->vaddr;
+	dtsec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr);
 	dtsec->max_speed = params->max_speed;
-	dtsec->phy_if = params->phy_if;
+	dtsec->phy_if = mac_dev->phy_if;
 	dtsec->mac_id = params->mac_id;
 	dtsec->exceptions = (DTSEC_IMASK_BREN	|
 			     DTSEC_IMASK_RXCEN	|
@@ -1456,7 +1454,7 @@ static struct fman_mac *dtsec_config(struct fman_mac_params *params)
 			     DTSEC_IMASK_RDPEEN);
 	dtsec->exception_cb = params->exception_cb;
 	dtsec->event_cb = params->event_cb;
-	dtsec->dev_id = params->dev_id;
+	dtsec->dev_id = mac_dev;
 	dtsec->ptp_tsu_enabled = dtsec->dtsec_drv_param->ptp_tsu_en;
 	dtsec->en_tsu_err_exception = dtsec->dtsec_drv_param->ptp_exception_en;
 
@@ -1497,7 +1495,7 @@ int dtsec_initialization(struct mac_device *mac_dev,
 	mac_dev->enable			= dtsec_enable;
 	mac_dev->disable		= dtsec_disable;
 
-	mac_dev->fman_mac = dtsec_config(params);
+	mac_dev->fman_mac = dtsec_config(mac_dev, params);
 	if (!mac_dev->fman_mac) {
 		err = -EINVAL;
 		goto _return;
diff --git a/drivers/net/ethernet/freescale/fman/fman_mac.h b/drivers/net/ethernet/freescale/fman/fman_mac.h
index 7774af6463e5..730aae7fed13 100644
--- a/drivers/net/ethernet/freescale/fman/fman_mac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_mac.h
@@ -163,25 +163,18 @@ typedef void (fman_mac_exception_cb)(void *dev_id,
 
 /* FMan MAC config input */
 struct fman_mac_params {
-	/* Base of memory mapped FM MAC registers */
-	void __iomem *base_addr;
-	/* MAC address of device; First octet is sent first */
-	enet_addr_t addr;
 	/* MAC ID; numbering of dTSEC and 1G-mEMAC:
 	 * 0 - FM_MAX_NUM_OF_1G_MACS;
 	 * numbering of 10G-MAC (TGEC) and 10G-mEMAC:
 	 * 0 - FM_MAX_NUM_OF_10G_MACS
 	 */
 	u8 mac_id;
-	/* PHY interface */
-	phy_interface_t	 phy_if;
 	/* Note that the speed should indicate the maximum rate that
 	 * this MAC should support rather than the actual speed;
 	 */
 	u16 max_speed;
 	/* A handle to the FM object this port related to */
 	void *fm;
-	void *dev_id; /* device cookie used by the exception cbs */
 	fman_mac_exception_cb *event_cb;    /* MDIO Events Callback Routine */
 	fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */
 	/* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index fa84467e10da..4d4c235d5dbc 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -1109,13 +1109,12 @@ static int memac_free(struct fman_mac *memac)
 	return 0;
 }
 
-static struct fman_mac *memac_config(struct fman_mac_params *params)
+static struct fman_mac *memac_config(struct mac_device *mac_dev,
+				     struct fman_mac_params *params)
 {
 	struct fman_mac *memac;
 	struct memac_cfg *memac_drv_param;
-	void __iomem *base_addr;
 
-	base_addr = params->base_addr;
 	/* allocate memory for the m_emac data structure */
 	memac = kzalloc(sizeof(*memac), GFP_KERNEL);
 	if (!memac)
@@ -1133,17 +1132,17 @@ static struct fman_mac *memac_config(struct fman_mac_params *params)
 
 	set_dflts(memac_drv_param);
 
-	memac->addr = ENET_ADDR_TO_UINT64(params->addr);
+	memac->addr = ENET_ADDR_TO_UINT64(mac_dev->addr);
 
-	memac->regs = base_addr;
+	memac->regs = mac_dev->vaddr;
 	memac->max_speed = params->max_speed;
-	memac->phy_if = params->phy_if;
+	memac->phy_if = mac_dev->phy_if;
 	memac->mac_id = params->mac_id;
 	memac->exceptions = (MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER |
 			     MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI);
 	memac->exception_cb = params->exception_cb;
 	memac->event_cb = params->event_cb;
-	memac->dev_id = params->dev_id;
+	memac->dev_id = mac_dev;
 	memac->fm = params->fm;
 	memac->basex_if = params->basex_if;
 
@@ -1179,9 +1178,9 @@ int memac_initialization(struct mac_device *mac_dev,
 	mac_dev->disable		= memac_disable;
 
 	if (params->max_speed == SPEED_10000)
-		params->phy_if = PHY_INTERFACE_MODE_XGMII;
+		mac_dev->phy_if = PHY_INTERFACE_MODE_XGMII;
 
-	mac_dev->fman_mac = memac_config(params);
+	mac_dev->fman_mac = memac_config(mac_dev, params);
 	if (!mac_dev->fman_mac) {
 		err = -EINVAL;
 		goto _return;
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index f34f89e46a6f..2642a4c27292 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -728,13 +728,11 @@ static int tgec_free(struct fman_mac *tgec)
 	return 0;
 }
 
-static struct fman_mac *tgec_config(struct fman_mac_params *params)
+static struct fman_mac *tgec_config(struct mac_device *mac_dev, struct fman_mac_params *params)
 {
 	struct fman_mac *tgec;
 	struct tgec_cfg *cfg;
-	void __iomem *base_addr;
 
-	base_addr = params->base_addr;
 	/* allocate memory for the UCC GETH data structure. */
 	tgec = kzalloc(sizeof(*tgec), GFP_KERNEL);
 	if (!tgec)
@@ -752,8 +750,8 @@ static struct fman_mac *tgec_config(struct fman_mac_params *params)
 
 	set_dflts(cfg);
 
-	tgec->regs = base_addr;
-	tgec->addr = ENET_ADDR_TO_UINT64(params->addr);
+	tgec->regs = mac_dev->vaddr;
+	tgec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr);
 	tgec->max_speed = params->max_speed;
 	tgec->mac_id = params->mac_id;
 	tgec->exceptions = (TGEC_IMASK_MDIO_SCAN_EVENT	|
@@ -773,7 +771,7 @@ static struct fman_mac *tgec_config(struct fman_mac_params *params)
 			    TGEC_IMASK_RX_ALIGN_ER);
 	tgec->exception_cb = params->exception_cb;
 	tgec->event_cb = params->event_cb;
-	tgec->dev_id = params->dev_id;
+	tgec->dev_id = mac_dev;
 	tgec->fm = params->fm;
 
 	/* Save FMan revision */
@@ -803,7 +801,7 @@ int tgec_initialization(struct mac_device *mac_dev,
 	mac_dev->enable			= tgec_enable;
 	mac_dev->disable		= tgec_disable;
 
-	mac_dev->fman_mac = tgec_config(params);
+	mac_dev->fman_mac = tgec_config(mac_dev, params);
 	if (!mac_dev->fman_mac) {
 		err = -EINVAL;
 		goto _return;
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 5d08c4696c21..88b9174531a6 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -34,7 +34,6 @@ struct mac_priv_s {
 	struct list_head		mc_addr_list;
 	struct platform_device		*eth_dev;
 	u16				speed;
-	u16				max_speed;
 };
 
 struct mac_address {
@@ -443,7 +442,7 @@ static int mac_probe(struct platform_device *_of_dev)
 	mac_dev->phy_if = phy_if;
 
 	priv->speed		= phy2speed[mac_dev->phy_if];
-	priv->max_speed		= priv->speed;
+	params.max_speed	= priv->speed;
 	mac_dev->if_support	= DTSEC_SUPPORTED;
 	/* We don't support half-duplex in SGMII mode */
 	if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII)
@@ -451,7 +450,7 @@ static int mac_probe(struct platform_device *_of_dev)
 					SUPPORTED_100baseT_Half);
 
 	/* Gigabit support (no half-duplex) */
-	if (priv->max_speed == 1000)
+	if (params.max_speed == 1000)
 		mac_dev->if_support |= SUPPORTED_1000baseT_Full;
 
 	/* The 10G interface only supports one mode */
@@ -461,16 +460,11 @@ static int mac_probe(struct platform_device *_of_dev)
 	/* Get the rest of the PHY information */
 	mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0);
 
-	params.base_addr = mac_dev->vaddr;
-	memcpy(&params.addr, mac_dev->addr, sizeof(mac_dev->addr));
-	params.max_speed	= priv->max_speed;
-	params.phy_if		= mac_dev->phy_if;
 	params.basex_if		= false;
 	params.mac_id		= priv->cell_index;
 	params.fm		= (void *)priv->fman;
 	params.exception_cb	= mac_exception;
 	params.event_cb		= mac_exception;
-	params.dev_id		= mac_dev;
 
 	err = init(mac_dev, mac_node, &params);
 	if (err < 0) {
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 21/28] net: fman: Clean up error handling
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (19 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 20/28] net: fman: Use mac_dev for some params Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 22/28] net: fman: memac: Add serdes support Sean Anderson
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

This removes the _return label, since something like

	err = -EFOO;
	goto _return;

can be replaced by the briefer

	return -EFOO;

Additionally, this skips going to _return_of_node_put when dev_node has
already been put (preventing a double put).

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/net/ethernet/freescale/fman/mac.c | 43 ++++++++---------------
 1 file changed, 15 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 88b9174531a6..c02f38ab335e 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -296,15 +296,11 @@ static int mac_probe(struct platform_device *_of_dev)
 	init = of_device_get_match_data(dev);
 
 	mac_dev = devm_kzalloc(dev, sizeof(*mac_dev), GFP_KERNEL);
-	if (!mac_dev) {
-		err = -ENOMEM;
-		goto _return;
-	}
+	if (!mac_dev)
+		return -ENOMEM;
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		err = -ENOMEM;
-		goto _return;
-	}
+	if (!priv)
+		return -ENOMEM;
 
 	/* Save private information */
 	mac_dev->priv = priv;
@@ -317,8 +313,7 @@ static int mac_probe(struct platform_device *_of_dev)
 	if (!dev_node) {
 		dev_err(dev, "of_get_parent(%pOF) failed\n",
 			mac_node);
-		err = -EINVAL;
-		goto _return_of_node_put;
+		return -EINVAL;
 	}
 
 	of_dev = of_find_device_by_node(dev_node);
@@ -357,28 +352,24 @@ static int mac_probe(struct platform_device *_of_dev)
 	err = devm_request_resource(dev, fman_get_mem_region(priv->fman), res);
 	if (err) {
 		dev_err_probe(dev, err, "could not request resource\n");
-		goto _return_of_node_put;
+		return err;
 	}
 
 	mac_dev->vaddr = devm_ioremap(dev, res->start, resource_size(res));
 	if (!mac_dev->vaddr) {
 		dev_err(dev, "devm_ioremap() failed\n");
-		err = -EIO;
-		goto _return_of_node_put;
+		return -EIO;
 	}
 	mac_dev->vaddr_end = (void *)res->end;
 
-	if (!of_device_is_available(mac_node)) {
-		err = -ENODEV;
-		goto _return_of_node_put;
-	}
+	if (!of_device_is_available(mac_node))
+		return -ENODEV;
 
 	/* Get the cell-index */
 	err = of_property_read_u32(mac_node, "cell-index", &val);
 	if (err) {
 		dev_err(dev, "failed to read cell-index for %pOF\n", mac_node);
-		err = -EINVAL;
-		goto _return_of_node_put;
+		return -EINVAL;
 	}
 	priv->cell_index = (u8)val;
 
@@ -392,15 +383,13 @@ static int mac_probe(struct platform_device *_of_dev)
 	if (unlikely(nph < 0)) {
 		dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n",
 			mac_node);
-		err = nph;
-		goto _return_of_node_put;
+		return nph;
 	}
 
 	if (nph != ARRAY_SIZE(mac_dev->port)) {
 		dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n",
 			mac_node);
-		err = -EINVAL;
-		goto _return_of_node_put;
+		return -EINVAL;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
@@ -409,8 +398,7 @@ static int mac_probe(struct platform_device *_of_dev)
 		if (!dev_node) {
 			dev_err(dev, "of_parse_phandle(%pOF, fsl,fman-ports) failed\n",
 				mac_node);
-			err = -EINVAL;
-			goto _return_of_node_put;
+			return -EINVAL;
 		}
 
 		of_dev = of_find_device_by_node(dev_node);
@@ -470,7 +458,7 @@ static int mac_probe(struct platform_device *_of_dev)
 	if (err < 0) {
 		dev_err(dev, "mac_dev->init() = %d\n", err);
 		of_node_put(mac_dev->phy_node);
-		goto _return_of_node_put;
+		return err;
 	}
 
 	/* pause frame autonegotiation enabled */
@@ -497,11 +485,10 @@ static int mac_probe(struct platform_device *_of_dev)
 		priv->eth_dev = NULL;
 	}
 
-	goto _return;
+	return err;
 
 _return_of_node_put:
 	of_node_put(dev_node);
-_return:
 	return err;
 }
 
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 22/28] net: fman: memac: Add serdes support
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (20 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 21/28] net: fman: Clean up error handling Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 23/28] net: fman: memac: Use lynx pcs driver Sean Anderson
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

This adds support for using a serdes which has to be configured. This is
primarly in preparation for the next commit, which will then change the
serdes mode dynamically.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../net/ethernet/freescale/fman/fman_memac.c  | 48 ++++++++++++++++++-
 1 file changed, 46 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 4d4c235d5dbc..5598a74ec559 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
+#include <linux/phy/phy.h>
 #include <linux/of_mdio.h>
 
 /* PCS registers */
@@ -324,6 +325,7 @@ struct fman_mac {
 	void *fm;
 	struct fman_rev_info fm_rev_info;
 	bool basex_if;
+	struct phy *serdes;
 	struct phy_device *pcsphy;
 	bool allmulti_enabled;
 };
@@ -1206,17 +1208,55 @@ int memac_initialization(struct mac_device *mac_dev,
 		}
 	}
 
+	memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes");
+	if (PTR_ERR(memac->serdes) == -ENODEV) {
+		memac->serdes = NULL;
+	} else if (IS_ERR(memac->serdes)) {
+		err = PTR_ERR(memac->serdes);
+		dev_err_probe(mac_dev->dev, err, "could not get serdes\n");
+		goto _return_fm_mac_free;
+	} else {
+		err = phy_init(memac->serdes);
+		if (err) {
+			dev_err_probe(mac_dev->dev, err,
+				      "could not initialize serdes\n");
+			goto _return_fm_mac_free;
+		}
+
+		err = phy_power_on(memac->serdes);
+		if (err) {
+			dev_err_probe(mac_dev->dev, err,
+				      "could not power on serdes\n");
+			goto _return_phy_exit;
+		}
+
+		if (memac->phy_if == PHY_INTERFACE_MODE_SGMII ||
+		    memac->phy_if == PHY_INTERFACE_MODE_1000BASEX ||
+		    memac->phy_if == PHY_INTERFACE_MODE_2500BASEX ||
+		    memac->phy_if == PHY_INTERFACE_MODE_QSGMII ||
+		    memac->phy_if == PHY_INTERFACE_MODE_XGMII) {
+			err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET,
+					       memac->phy_if);
+			if (err) {
+				dev_err_probe(mac_dev->dev, err,
+					      "could not set serdes mode to %s\n",
+					      phy_modes(memac->phy_if));
+				goto _return_phy_power_off;
+			}
+		}
+	}
+
 	if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
 		struct phy_device *phy;
 
 		err = of_phy_register_fixed_link(mac_node);
 		if (err)
-			goto _return_fm_mac_free;
+			goto _return_phy_power_off;
 
 		fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL);
 		if (!fixed_link) {
 			err = -ENOMEM;
-			goto _return_fm_mac_free;
+			goto _return_phy_power_off;
 		}
 
 		mac_dev->phy_node = of_node_get(mac_node);
@@ -1245,6 +1285,10 @@ int memac_initialization(struct mac_device *mac_dev,
 
 	goto _return;
 
+_return_phy_power_off:
+	phy_power_off(memac->serdes);
+_return_phy_exit:
+	phy_exit(memac->serdes);
 _return_fixed_link_free:
 	kfree(fixed_link);
 _return_fm_mac_free:
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 23/28] net: fman: memac: Use lynx pcs driver
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (21 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 22/28] net: fman: memac: Add serdes support Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 24/28] net: dpaa: Use mac_dev variable in dpaa_netdev_init Sean Anderson
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

Although not stated in the datasheet, as far as I can tell PCS for MEMACs
is a "Lynx." By reusing the existing driver, we can remove the PCS
management code from the memac driver. This requires calling some PCS
functions manually which phylink would usually do for us, but we will let
it do that soon.

One problem is that we don't actually have a PCS for QSGMII. We pretend
that each MEMAC's MDIO bus has four QSGMII PCSs, but this is not the case.
Only the "base" MEMAC's MDIO bus has the four QSGMII PCSs. This is not an
issue yet, because we never get the PCS state. However, it will be once the
conversion to phylink is complete, since the links will appear to never
come up. To get around this, we allow specifying multiple PCSs in pcsphy.
This breaks backwards compatibility with old device trees, but only for
QSGMII. IMO this is the only reasonable way to figure out what the actual
QSGMII PCS is.

Additionally, we now also support a separate XFI PCS. This can allow the
SerDes driver to set different addresses for the SGMII and XFI PCSs so they
can be accessed at the same time.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/net/ethernet/freescale/dpaa/Kconfig   |   2 +
 .../net/ethernet/freescale/fman/fman_memac.c  | 246 +++++++-----------
 2 files changed, 92 insertions(+), 156 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/Kconfig b/drivers/net/ethernet/freescale/dpaa/Kconfig
index 0e1439fd00bd..0ddcb1355daf 100644
--- a/drivers/net/ethernet/freescale/dpaa/Kconfig
+++ b/drivers/net/ethernet/freescale/dpaa/Kconfig
@@ -4,6 +4,8 @@ menuconfig FSL_DPAA_ETH
 	depends on FSL_DPAA && FSL_FMAN
 	select PHYLIB
 	select FIXED_PHY
+	select PHYLINK
+	select PCS_LYNX
 	help
 	  Data Path Acceleration Architecture Ethernet driver,
 	  supporting the Freescale QorIQ chips.
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 5598a74ec559..3eea6710013a 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -11,43 +11,12 @@
 
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/pcs-lynx.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
 #include <linux/phy/phy.h>
 #include <linux/of_mdio.h>
 
-/* PCS registers */
-#define MDIO_SGMII_CR			0x00
-#define MDIO_SGMII_DEV_ABIL_SGMII	0x04
-#define MDIO_SGMII_LINK_TMR_L		0x12
-#define MDIO_SGMII_LINK_TMR_H		0x13
-#define MDIO_SGMII_IF_MODE		0x14
-
-/* SGMII Control defines */
-#define SGMII_CR_AN_EN			0x1000
-#define SGMII_CR_RESTART_AN		0x0200
-#define SGMII_CR_FD			0x0100
-#define SGMII_CR_SPEED_SEL1_1G		0x0040
-#define SGMII_CR_DEF_VAL		(SGMII_CR_AN_EN | SGMII_CR_FD | \
-					 SGMII_CR_SPEED_SEL1_1G)
-
-/* SGMII Device Ability for SGMII defines */
-#define MDIO_SGMII_DEV_ABIL_SGMII_MODE	0x4001
-#define MDIO_SGMII_DEV_ABIL_BASEX_MODE	0x01A0
-
-/* Link timer define */
-#define LINK_TMR_L			0xa120
-#define LINK_TMR_H			0x0007
-#define LINK_TMR_L_BASEX		0xaf08
-#define LINK_TMR_H_BASEX		0x002f
-
-/* SGMII IF Mode defines */
-#define IF_MODE_USE_SGMII_AN		0x0002
-#define IF_MODE_SGMII_EN		0x0001
-#define IF_MODE_SGMII_SPEED_100M	0x0004
-#define IF_MODE_SGMII_SPEED_1G		0x0008
-#define IF_MODE_SGMII_DUPLEX_HALF	0x0010
-
 /* Num of additional exact match MAC adr regs */
 #define MEMAC_NUM_OF_PADDRS 7
 
@@ -326,7 +295,9 @@ struct fman_mac {
 	struct fman_rev_info fm_rev_info;
 	bool basex_if;
 	struct phy *serdes;
-	struct phy_device *pcsphy;
+	struct phylink_pcs *sgmii_pcs;
+	struct phylink_pcs *qsgmii_pcs;
+	struct phylink_pcs *xfi_pcs;
 	bool allmulti_enabled;
 };
 
@@ -487,91 +458,22 @@ static u32 get_mac_addr_hash_code(u64 eth_addr)
 	return xor_val;
 }
 
-static void setup_sgmii_internal_phy(struct fman_mac *memac,
-				     struct fixed_phy_status *fixed_link)
+static void setup_sgmii_internal(struct fman_mac *memac,
+				 struct phylink_pcs *pcs,
+				 struct fixed_phy_status *fixed_link)
 {
-	u16 tmp_reg16;
-
-	if (WARN_ON(!memac->pcsphy))
-		return;
-
-	/* SGMII mode */
-	tmp_reg16 = IF_MODE_SGMII_EN;
-	if (!fixed_link)
-		/* AN enable */
-		tmp_reg16 |= IF_MODE_USE_SGMII_AN;
-	else {
-		switch (fixed_link->speed) {
-		case 10:
-			/* For 10M: IF_MODE[SPEED_10M] = 0 */
-		break;
-		case 100:
-			tmp_reg16 |= IF_MODE_SGMII_SPEED_100M;
-		break;
-		case 1000:
-		default:
-			tmp_reg16 |= IF_MODE_SGMII_SPEED_1G;
-		break;
-		}
-		if (!fixed_link->duplex)
-			tmp_reg16 |= IF_MODE_SGMII_DUPLEX_HALF;
-	}
-	phy_write(memac->pcsphy, MDIO_SGMII_IF_MODE, tmp_reg16);
-
-	/* Device ability according to SGMII specification */
-	tmp_reg16 = MDIO_SGMII_DEV_ABIL_SGMII_MODE;
-	phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16);
-
-	/* Adjust link timer for SGMII  -
-	 * According to Cisco SGMII specification the timer should be 1.6 ms.
-	 * The link_timer register is configured in units of the clock.
-	 * - When running as 1G SGMII, Serdes clock is 125 MHz, so
-	 * unit = 1 / (125*10^6 Hz) = 8 ns.
-	 * 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2*10^5 = 0x30d40
-	 * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
-	 * unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
-	 * 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5*10^5 = 0x7a120.
-	 * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
-	 * we always set up here a value of 2.5 SGMII.
-	 */
-	phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H);
-	phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L);
-
-	if (!fixed_link)
-		/* Restart AN */
-		tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN;
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
+	phy_interface_t iface = memac->basex_if ? PHY_INTERFACE_MODE_1000BASEX :
+				PHY_INTERFACE_MODE_SGMII;
+	unsigned int mode = fixed_link ? MLO_AN_FIXED : MLO_AN_INBAND;
+
+	linkmode_set_pause(advertising, true, true);
+	pcs->ops->pcs_config(pcs, mode, iface, advertising, true);
+	if (fixed_link)
+		pcs->ops->pcs_link_up(pcs, mode, iface, fixed_link->speed,
+				      fixed_link->duplex);
 	else
-		/* AN disabled */
-		tmp_reg16 = SGMII_CR_DEF_VAL & ~SGMII_CR_AN_EN;
-	phy_write(memac->pcsphy, 0x0, tmp_reg16);
-}
-
-static void setup_sgmii_internal_phy_base_x(struct fman_mac *memac)
-{
-	u16 tmp_reg16;
-
-	/* AN Device capability  */
-	tmp_reg16 = MDIO_SGMII_DEV_ABIL_BASEX_MODE;
-	phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16);
-
-	/* Adjust link timer for SGMII  -
-	 * For Serdes 1000BaseX auto-negotiation the timer should be 10 ms.
-	 * The link_timer register is configured in units of the clock.
-	 * - When running as 1G SGMII, Serdes clock is 125 MHz, so
-	 * unit = 1 / (125*10^6 Hz) = 8 ns.
-	 * 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0
-	 * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
-	 * unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
-	 * 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08.
-	 * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
-	 * we always set up here a value of 2.5 SGMII.
-	 */
-	phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H_BASEX);
-	phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L_BASEX);
-
-	/* Restart AN */
-	tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN;
-	phy_write(memac->pcsphy, 0x0, tmp_reg16);
+		pcs->ops->pcs_an_restart(pcs);
 }
 
 static int check_init_parameters(struct fman_mac *memac)
@@ -984,7 +886,6 @@ static int memac_set_exception(struct fman_mac *memac,
 static int memac_init(struct fman_mac *memac)
 {
 	struct memac_cfg *memac_drv_param;
-	u8 i;
 	enet_addr_t eth_addr;
 	bool slow_10g_if = false;
 	struct fixed_phy_status *fixed_link;
@@ -1037,32 +938,10 @@ static int memac_init(struct fman_mac *memac)
 		iowrite32be(reg32, &memac->regs->command_config);
 	}
 
-	if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) {
-		/* Configure internal SGMII PHY */
-		if (memac->basex_if)
-			setup_sgmii_internal_phy_base_x(memac);
-		else
-			setup_sgmii_internal_phy(memac, fixed_link);
-	} else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) {
-		/* Configure 4 internal SGMII PHYs */
-		for (i = 0; i < 4; i++) {
-			u8 qsmgii_phy_addr, phy_addr;
-			/* QSGMII PHY address occupies 3 upper bits of 5-bit
-			 * phy_address; the lower 2 bits are used to extend
-			 * register address space and access each one of 4
-			 * ports inside QSGMII.
-			 */
-			phy_addr = memac->pcsphy->mdio.addr;
-			qsmgii_phy_addr = (u8)((phy_addr << 2) | i);
-			memac->pcsphy->mdio.addr = qsmgii_phy_addr;
-			if (memac->basex_if)
-				setup_sgmii_internal_phy_base_x(memac);
-			else
-				setup_sgmii_internal_phy(memac, fixed_link);
-
-			memac->pcsphy->mdio.addr = phy_addr;
-		}
-	}
+	if (memac->phy_if == PHY_INTERFACE_MODE_SGMII)
+		setup_sgmii_internal(memac, memac->sgmii_pcs, fixed_link);
+	else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII)
+		setup_sgmii_internal(memac, memac->qsgmii_pcs, fixed_link);
 
 	/* Max Frame Length */
 	err = fman_set_mac_max_frame(memac->fm, memac->mac_id,
@@ -1102,8 +981,12 @@ static int memac_free(struct fman_mac *memac)
 {
 	free_init_resources(memac);
 
-	if (memac->pcsphy)
-		put_device(&memac->pcsphy->mdio.dev);
+	if (memac->sgmii_pcs)
+		lynx_pcs_destroy(memac->sgmii_pcs);
+	if (memac->qsgmii_pcs)
+		lynx_pcs_destroy(memac->qsgmii_pcs);
+	if (memac->xfi_pcs)
+		lynx_pcs_destroy(memac->xfi_pcs);
 
 	kfree(memac->memac_drv_param);
 	kfree(memac);
@@ -1154,13 +1037,30 @@ static struct fman_mac *memac_config(struct mac_device *mac_dev,
 	return memac;
 }
 
+static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node,
+					    int index)
+{
+	struct device_node *node;
+	struct mdio_device *mdiodev = NULL;
+
+	node = of_parse_phandle(mac_node, "pcsphy-handle", index);
+	if (node && of_device_is_available(node))
+		mdiodev = of_mdio_find_device(node);
+	of_node_put(node);
+
+	if (!mdiodev)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	return lynx_pcs_create(mdiodev) ?: ERR_PTR(-ENOMEM);
+}
+
 int memac_initialization(struct mac_device *mac_dev,
 			 struct device_node *mac_node,
 			 struct fman_mac_params *params)
 {
 	int			 err;
-	struct device_node	*phy_node;
 	struct mac_priv_s	*priv;
+	struct phylink_pcs	*pcs;
 	struct fixed_phy_status *fixed_link;
 	struct fman_mac		*memac;
 
@@ -1191,23 +1091,57 @@ int memac_initialization(struct mac_device *mac_dev,
 	memac = mac_dev->fman_mac;
 	memac->memac_drv_param->max_frame_length = fman_get_max_frm();
 	memac->memac_drv_param->reset_on_init = true;
-	if (memac->phy_if == PHY_INTERFACE_MODE_SGMII ||
-	    memac->phy_if == PHY_INTERFACE_MODE_QSGMII) {
-		phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0);
-		if (!phy_node) {
-			pr_err("PCS PHY node is not available\n");
-			err = -EINVAL;
+
+	err = of_property_match_string(mac_node, "pcs-names", "xfi");
+	if (err >= 0) {
+		memac->xfi_pcs = memac_pcs_create(mac_node, err);
+		if (IS_ERR(memac->xfi_pcs)) {
+			err = PTR_ERR(memac->xfi_pcs);
+			dev_err_probe(mac_dev->dev, err, "missing xfi pcs\n");
 			goto _return_fm_mac_free;
 		}
+	} else if (err != -EINVAL && err != -ENODATA) {
+		goto _return_fm_mac_free;
+	}
 
-		memac->pcsphy = of_phy_find_device(phy_node);
-		if (!memac->pcsphy) {
-			pr_err("of_phy_find_device (PCS PHY) failed\n");
-			err = -EINVAL;
+	err = of_property_match_string(mac_node, "pcs-names", "qsgmii");
+	if (err >= 0) {
+		memac->qsgmii_pcs = memac_pcs_create(mac_node, err);
+		if (IS_ERR(memac->qsgmii_pcs)) {
+			err = PTR_ERR(memac->qsgmii_pcs);
+			dev_err_probe(mac_dev->dev, err, "missing qsgmii pcs\n");
 			goto _return_fm_mac_free;
 		}
+	} else if (err != -EINVAL && err != -ENODATA) {
+		goto _return_fm_mac_free;
+	}
+
+	/* For compatibility, if pcs-names is missing, we assume this phy is
+	 * the first one in pcsphy-handle
+	 */
+	err = of_property_match_string(mac_node, "pcs-names", "sgmii");
+	if (err == -EINVAL)
+		pcs = memac_pcs_create(mac_node, 0);
+	else if (err < 0)
+		goto _return_fm_mac_free;
+	else
+		pcs = memac_pcs_create(mac_node, err);
+
+	if (!pcs) {
+		dev_err(mac_dev->dev, "missing pcs\n");
+		err = -ENOENT;
+		goto _return_fm_mac_free;
 	}
 
+	/* If err is set here, it means that pcs-names was missing above (and
+	 * therefore that xfi_pcs cannot be set). If we are defaulting to
+	 * XGMII, assume this is for XFI. Otherwise, assume it is for SGMII.
+	 */
+	if (err && mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII)
+		memac->xfi_pcs = pcs;
+	else
+		memac->sgmii_pcs = pcs;
+
 	memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes");
 	if (PTR_ERR(memac->serdes) == -ENODEV) {
 		memac->serdes = NULL;
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 24/28] net: dpaa: Use mac_dev variable in dpaa_netdev_init
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (22 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 23/28] net: fman: memac: Use lynx pcs driver Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

There are several references to mac_dev in dpaa_netdev_init. Make things a
bit more concise by adding a local variable for it.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index d443d53c4504..9d31fd1d8ad0 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -203,6 +203,7 @@ static int dpaa_netdev_init(struct net_device *net_dev,
 {
 	struct dpaa_priv *priv = netdev_priv(net_dev);
 	struct device *dev = net_dev->dev.parent;
+	struct mac_device *mac_dev = priv->mac_dev;
 	struct dpaa_percpu_priv *percpu_priv;
 	const u8 *mac_addr;
 	int i, err;
@@ -216,10 +217,10 @@ static int dpaa_netdev_init(struct net_device *net_dev,
 	}
 
 	net_dev->netdev_ops = dpaa_ops;
-	mac_addr = priv->mac_dev->addr;
+	mac_addr = mac_dev->addr;
 
-	net_dev->mem_start = (unsigned long)priv->mac_dev->vaddr;
-	net_dev->mem_end = (unsigned long)priv->mac_dev->vaddr_end;
+	net_dev->mem_start = (unsigned long)mac_dev->vaddr;
+	net_dev->mem_end = (unsigned long)mac_dev->vaddr_end;
 
 	net_dev->min_mtu = ETH_MIN_MTU;
 	net_dev->max_mtu = dpaa_get_max_mtu();
@@ -246,7 +247,7 @@ static int dpaa_netdev_init(struct net_device *net_dev,
 		eth_hw_addr_set(net_dev, mac_addr);
 	} else {
 		eth_hw_addr_random(net_dev);
-		err = priv->mac_dev->change_addr(priv->mac_dev->fman_mac,
+		err = priv->mac_dev->change_addr(mac_dev->fman_mac,
 			(const enet_addr_t *)net_dev->dev_addr);
 		if (err) {
 			dev_err(dev, "Failed to set random MAC address\n");
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (23 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 24/28] net: dpaa: Use mac_dev variable in dpaa_netdev_init Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 22:01   ` Russell King (Oracle)
  2022-06-17 20:33 ` [PATCH net-next 26/28] arm64: dts: ls1046ardb: Add serdes bindings Sean Anderson
                   ` (2 subsequent siblings)
  27 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson

This converts DPAA to phylink. For the moment, only MEMAC is converted.
This should work with no device tree modifications (including those made in
this series), except for QSGMII (as noted previously).

One area where I wasn't sure how to do things was regarding when to call
phy_init and phy_power_on. Should that happen when selecting the PCS?
Similarly, I wasn't sure where to reconfigure the thresholds in
dpaa_eth_cgr_init. Should happen in link_up? If so, I think we will need
some kind of callback.

The configuration is one of the tricker areas. I have tried to capture all
the restrictions across the various models. Most of the time, we assume
that if the serdes supports a mode or the phy-interface-mode specifies it,
then we support it. The only place we can't do this is (RG)MII, since
there's no serdes. In that case, we rely on a (new) devicetree property.
There are also several cases where half-duplex is broken. Unfortunately,
only a single compatible is used for the MAC, so we have to use the board
compatible instead.

This has been tested on an LS1046ARDB. Without the serdes enabled,
everything works. With the serdes enabled, everything works but eth3 (aka
MAC6). On that interface, SGMII never completes AN for whatever reason. I
haven't tested the counterfactual (serdes enabled but no phylink). With
managed=phy (e.g. unspecified), I was unable to get the interfaces to come
up at all.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/net/ethernet/freescale/dpaa/Kconfig   |   2 -
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  94 +---
 .../ethernet/freescale/dpaa/dpaa_ethtool.c    |  82 +--
 drivers/net/ethernet/freescale/fman/Makefile  |   3 +-
 .../net/ethernet/freescale/fman/fman_mac.h    |  10 -
 .../net/ethernet/freescale/fman/fman_memac.c  | 521 +++++++++---------
 drivers/net/ethernet/freescale/fman/mac.c     | 169 +-----
 drivers/net/ethernet/freescale/fman/mac.h     |  24 +-
 8 files changed, 327 insertions(+), 578 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/Kconfig b/drivers/net/ethernet/freescale/dpaa/Kconfig
index 0ddcb1355daf..2b560661c82a 100644
--- a/drivers/net/ethernet/freescale/dpaa/Kconfig
+++ b/drivers/net/ethernet/freescale/dpaa/Kconfig
@@ -2,8 +2,6 @@
 menuconfig FSL_DPAA_ETH
 	tristate "DPAA Ethernet"
 	depends on FSL_DPAA && FSL_FMAN
-	select PHYLIB
-	select FIXED_PHY
 	select PHYLINK
 	select PCS_LYNX
 	help
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 9d31fd1d8ad0..2caf353dd64d 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -262,12 +262,26 @@ static int dpaa_netdev_init(struct net_device *net_dev,
 	net_dev->needed_headroom = priv->tx_headroom;
 	net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout);
 
+	/* The rest of the config is filled in by the mac device already */
+	mac_dev->phylink_config.dev = &net_dev->dev;
+	mac_dev->phylink_config.type = PHYLINK_NETDEV;
+	mac_dev->phylink = phylink_create(&mac_dev->phylink_config,
+					  dev_fwnode(mac_dev->dev),
+					  mac_dev->phy_if,
+					  mac_dev->phylink_ops);
+	if (IS_ERR(mac_dev->phylink)) {
+		err = PTR_ERR(mac_dev->phylink);
+		dev_err_probe(dev, err, "Could not create phylink\n");
+		return err;
+	}
+
 	/* start without the RUNNING flag, phylib controls it later */
 	netif_carrier_off(net_dev);
 
 	err = register_netdev(net_dev);
 	if (err < 0) {
 		dev_err(dev, "register_netdev() = %d\n", err);
+		phylink_destroy(mac_dev->phylink);
 		return err;
 	}
 
@@ -289,21 +303,14 @@ static int dpaa_stop(struct net_device *net_dev)
 	 */
 	msleep(200);
 
-	if (mac_dev->phy_dev)
-		phy_stop(mac_dev->phy_dev);
-	err = mac_dev->disable(mac_dev->fman_mac);
-	if (err < 0)
-		netif_err(priv, ifdown, net_dev, "mac_dev->disable() = %d\n",
-			  err);
-
+	phylink_stop(mac_dev->phylink);
 	for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
 		error = fman_port_disable(mac_dev->port[i]);
 		if (error)
 			err = error;
 	}
 
-	if (net_dev->phydev)
-		phy_disconnect(net_dev->phydev);
+	phylink_disconnect_phy(mac_dev->phylink);
 	net_dev->phydev = NULL;
 
 	msleep(200);
@@ -834,7 +841,9 @@ static int dpaa_eth_cgr_init(struct dpaa_priv *priv)
 	 * lower than its max, e.g. if a dTSEC later negotiates a 100Mbps link.
 	 * In such cases, we ought to reconfigure the threshold, too.
 	 */
-	if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full)
+	// FIXME
+	if (true)
+	//if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full)
 		cs_th = DPAA_CS_THRESHOLD_10G;
 	else
 		cs_th = DPAA_CS_THRESHOLD_1G;
@@ -2877,54 +2886,6 @@ static void dpaa_eth_napi_disable(struct dpaa_priv *priv)
 	}
 }
 
-static void dpaa_adjust_link(struct net_device *net_dev)
-{
-	struct mac_device *mac_dev;
-	struct dpaa_priv *priv;
-
-	priv = netdev_priv(net_dev);
-	mac_dev = priv->mac_dev;
-	mac_dev->adjust_link(mac_dev);
-}
-
-/* The Aquantia PHYs are capable of performing rate adaptation */
-#define PHY_VEND_AQUANTIA	0x03a1b400
-
-static int dpaa_phy_init(struct net_device *net_dev)
-{
-	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
-	struct mac_device *mac_dev;
-	struct phy_device *phy_dev;
-	struct dpaa_priv *priv;
-
-	priv = netdev_priv(net_dev);
-	mac_dev = priv->mac_dev;
-
-	phy_dev = of_phy_connect(net_dev, mac_dev->phy_node,
-				 &dpaa_adjust_link, 0,
-				 mac_dev->phy_if);
-	if (!phy_dev) {
-		netif_err(priv, ifup, net_dev, "init_phy() failed\n");
-		return -ENODEV;
-	}
-
-	/* Unless the PHY is capable of rate adaptation */
-	if (mac_dev->phy_if != PHY_INTERFACE_MODE_XGMII ||
-	    ((phy_dev->drv->phy_id & GENMASK(31, 10)) != PHY_VEND_AQUANTIA)) {
-		/* remove any features not supported by the controller */
-		ethtool_convert_legacy_u32_to_link_mode(mask,
-							mac_dev->if_support);
-		linkmode_and(phy_dev->supported, phy_dev->supported, mask);
-	}
-
-	phy_support_asym_pause(phy_dev);
-
-	mac_dev->phy_dev = phy_dev;
-	net_dev->phydev = phy_dev;
-
-	return 0;
-}
-
 static int dpaa_open(struct net_device *net_dev)
 {
 	struct mac_device *mac_dev;
@@ -2935,7 +2896,8 @@ static int dpaa_open(struct net_device *net_dev)
 	mac_dev = priv->mac_dev;
 	dpaa_eth_napi_enable(priv);
 
-	err = dpaa_phy_init(net_dev);
+	err = phylink_of_phy_connect(mac_dev->phylink,
+				     mac_dev->dev->of_node, 0);
 	if (err)
 		goto phy_init_failed;
 
@@ -2945,13 +2907,7 @@ static int dpaa_open(struct net_device *net_dev)
 			goto mac_start_failed;
 	}
 
-	err = priv->mac_dev->enable(mac_dev->fman_mac);
-	if (err < 0) {
-		netif_err(priv, ifup, net_dev, "mac_dev->enable() = %d\n", err);
-		goto mac_start_failed;
-	}
-	phy_start(priv->mac_dev->phy_dev);
-
+	phylink_start(mac_dev->phylink);
 	netif_tx_start_all_queues(net_dev);
 
 	return 0;
@@ -2959,6 +2915,7 @@ static int dpaa_open(struct net_device *net_dev)
 mac_start_failed:
 	for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++)
 		fman_port_disable(mac_dev->port[i]);
+	phylink_disconnect_phy(mac_dev->phylink);
 
 phy_init_failed:
 	dpaa_eth_napi_disable(priv);
@@ -3114,10 +3071,12 @@ static int dpaa_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
 {
 	int ret = -EINVAL;
+	struct dpaa_priv *priv = netdev_priv(net_dev);
 
 	if (cmd == SIOCGMIIREG) {
 		if (net_dev->phydev)
-			return phy_mii_ioctl(net_dev->phydev, rq, cmd);
+			return phylink_mii_ioctl(priv->mac_dev->phylink, rq,
+						 cmd);
 	}
 
 	if (cmd == SIOCSHWTSTAMP)
@@ -3521,6 +3480,7 @@ static int dpaa_remove(struct platform_device *pdev)
 
 	dev_set_drvdata(dev, NULL);
 	unregister_netdev(net_dev);
+	phylink_destroy(priv->mac_dev->phylink);
 
 	err = dpaa_fq_free(dev, &priv->dpaa_fq_list);
 
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
index 73f07881ce2d..bf0690d21e3d 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
@@ -54,27 +54,19 @@ static char dpaa_stats_global[][ETH_GSTRING_LEN] = {
 static int dpaa_get_link_ksettings(struct net_device *net_dev,
 				   struct ethtool_link_ksettings *cmd)
 {
-	if (!net_dev->phydev)
-		return 0;
+	struct dpaa_priv *priv = netdev_priv(net_dev);
+	struct mac_device *mac_dev = priv->mac_dev;
 
-	phy_ethtool_ksettings_get(net_dev->phydev, cmd);
-
-	return 0;
+	return phylink_ethtool_ksettings_get(mac_dev->phylink, cmd);
 }
 
 static int dpaa_set_link_ksettings(struct net_device *net_dev,
 				   const struct ethtool_link_ksettings *cmd)
 {
-	int err;
+	struct dpaa_priv *priv = netdev_priv(net_dev);
+	struct mac_device *mac_dev = priv->mac_dev;
 
-	if (!net_dev->phydev)
-		return -ENODEV;
-
-	err = phy_ethtool_ksettings_set(net_dev->phydev, cmd);
-	if (err < 0)
-		netdev_err(net_dev, "phy_ethtool_ksettings_set() = %d\n", err);
-
-	return err;
+	return phylink_ethtool_ksettings_set(mac_dev->phylink, cmd);
 }
 
 static void dpaa_get_drvinfo(struct net_device *net_dev,
@@ -115,66 +107,6 @@ static int dpaa_nway_reset(struct net_device *net_dev)
 	return err;
 }
 
-static void dpaa_get_pauseparam(struct net_device *net_dev,
-				struct ethtool_pauseparam *epause)
-{
-	struct mac_device *mac_dev;
-	struct dpaa_priv *priv;
-
-	priv = netdev_priv(net_dev);
-	mac_dev = priv->mac_dev;
-
-	if (!net_dev->phydev)
-		return;
-
-	epause->autoneg = mac_dev->autoneg_pause;
-	epause->rx_pause = mac_dev->rx_pause_active;
-	epause->tx_pause = mac_dev->tx_pause_active;
-}
-
-static int dpaa_set_pauseparam(struct net_device *net_dev,
-			       struct ethtool_pauseparam *epause)
-{
-	struct mac_device *mac_dev;
-	struct phy_device *phydev;
-	bool rx_pause, tx_pause;
-	struct dpaa_priv *priv;
-	int err;
-
-	priv = netdev_priv(net_dev);
-	mac_dev = priv->mac_dev;
-
-	phydev = net_dev->phydev;
-	if (!phydev) {
-		netdev_err(net_dev, "phy device not initialized\n");
-		return -ENODEV;
-	}
-
-	if (!phy_validate_pause(phydev, epause))
-		return -EINVAL;
-
-	/* The MAC should know how to handle PAUSE frame autonegotiation before
-	 * adjust_link is triggered by a forced renegotiation of sym/asym PAUSE
-	 * settings.
-	 */
-	mac_dev->autoneg_pause = !!epause->autoneg;
-	mac_dev->rx_pause_req = !!epause->rx_pause;
-	mac_dev->tx_pause_req = !!epause->tx_pause;
-
-	/* Determine the sym/asym advertised PAUSE capabilities from the desired
-	 * rx/tx pause settings.
-	 */
-
-	phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause);
-
-	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
-	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
-	if (err < 0)
-		netdev_err(net_dev, "set_mac_active_pause() = %d\n", err);
-
-	return err;
-}
-
 static int dpaa_get_sset_count(struct net_device *net_dev, int type)
 {
 	unsigned int total_stats, num_stats;
@@ -566,8 +498,6 @@ const struct ethtool_ops dpaa_ethtool_ops = {
 	.get_msglevel = dpaa_get_msglevel,
 	.set_msglevel = dpaa_set_msglevel,
 	.nway_reset = dpaa_nway_reset,
-	.get_pauseparam = dpaa_get_pauseparam,
-	.set_pauseparam = dpaa_set_pauseparam,
 	.get_link = ethtool_op_get_link,
 	.get_sset_count = dpaa_get_sset_count,
 	.get_ethtool_stats = dpaa_get_ethtool_stats,
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index b618091db091..ee0b9178187c 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -7,4 +7,5 @@ obj-$(CONFIG_FSL_FMAN) += fsl_dpaa_mac.o
 
 fsl_dpaa_fman-objs	:= fman_muram.o fman.o fman_sp.o fman_keygen.o
 fsl_dpaa_fman_port-objs := fman_port.o
-fsl_dpaa_mac-objs:= mac.o fman_dtsec.o fman_memac.o fman_tgec.o
+#fsl_dpaa_mac-objs:= mac.o fman_dtsec.o fman_memac.o fman_tgec.o
+fsl_dpaa_mac-objs := mac.o fman_memac.o
diff --git a/drivers/net/ethernet/freescale/fman/fman_mac.h b/drivers/net/ethernet/freescale/fman/fman_mac.h
index 730aae7fed13..837ecf1c97c8 100644
--- a/drivers/net/ethernet/freescale/fman/fman_mac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_mac.h
@@ -169,20 +169,10 @@ struct fman_mac_params {
 	 * 0 - FM_MAX_NUM_OF_10G_MACS
 	 */
 	u8 mac_id;
-	/* Note that the speed should indicate the maximum rate that
-	 * this MAC should support rather than the actual speed;
-	 */
-	u16 max_speed;
 	/* A handle to the FM object this port related to */
 	void *fm;
 	fman_mac_exception_cb *event_cb;    /* MDIO Events Callback Routine */
 	fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */
-	/* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC
-	 * and phy or backplane; Note: 1000BaseX auto-negotiation relates only
-	 * to interface between MAC and phy/backplane, SGMII phy can still
-	 * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps
-	*/
-	bool basex_if;
 };
 
 struct eth_hash_t {
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 3eea6710013a..d12dbb7f173a 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -66,6 +66,12 @@ do {									\
 #define IF_MODE_RGMII_FD	0x00001000 /* Full duplex RGMII */
 #define IF_MODE_HD		0x00000040 /* Half duplex operation */
 
+#define IF_STATUS_RGLINK	BIT(15)
+#define IF_STATUS_RGSP		GENMASK(14, 13)
+#define IF_STATUS_RGSP_10	0
+#define IF_STATUS_RGSP_100	1
+#define IF_STATUS_RGSP_1000	2
+
 /* Hash table Control Register (HASHTABLE_CTRL) */
 #define HASH_CTRL_MCAST_EN	0x00000100
 /* 26-31 Hash table address code */
@@ -273,14 +279,16 @@ struct memac_cfg {
 	u32 tx_ipg_length;
 };
 
+struct memac_pcs {
+	struct phylink_pcs pcs;
+	struct phy_device *phy;
+};
+
 struct fman_mac {
 	/* Pointer to MAC memory mapped registers */
 	struct memac_regs __iomem *regs;
 	/* MAC address of device */
 	u64 addr;
-	/* Ethernet physical interface */
-	phy_interface_t phy_if;
-	u16 max_speed;
 	void *dev_id; /* device cookie used by the exception cbs */
 	fman_mac_exception_cb *exception_cb;
 	fman_mac_exception_cb *event_cb;
@@ -293,7 +301,6 @@ struct fman_mac {
 	struct memac_cfg *memac_drv_param;
 	void *fm;
 	struct fman_rev_info fm_rev_info;
-	bool basex_if;
 	struct phy *serdes;
 	struct phylink_pcs *sgmii_pcs;
 	struct phylink_pcs *qsgmii_pcs;
@@ -356,7 +363,6 @@ static void set_exception(struct memac_regs __iomem *regs, u32 val,
 }
 
 static int init(struct memac_regs __iomem *regs, struct memac_cfg *cfg,
-		phy_interface_t phy_if, u16 speed, bool slow_10g_if,
 		u32 exceptions)
 {
 	u32 tmp;
@@ -384,41 +390,6 @@ static int init(struct memac_regs __iomem *regs, struct memac_cfg *cfg,
 	iowrite32be((u32)cfg->pause_quanta, &regs->pause_quanta[0]);
 	iowrite32be((u32)0, &regs->pause_thresh[0]);
 
-	/* IF_MODE */
-	tmp = 0;
-	switch (phy_if) {
-	case PHY_INTERFACE_MODE_XGMII:
-		tmp |= IF_MODE_10G;
-		break;
-	case PHY_INTERFACE_MODE_MII:
-		tmp |= IF_MODE_MII;
-		break;
-	default:
-		tmp |= IF_MODE_GMII;
-		if (phy_if == PHY_INTERFACE_MODE_RGMII ||
-		    phy_if == PHY_INTERFACE_MODE_RGMII_ID ||
-		    phy_if == PHY_INTERFACE_MODE_RGMII_RXID ||
-		    phy_if == PHY_INTERFACE_MODE_RGMII_TXID)
-			tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO;
-	}
-	iowrite32be(tmp, &regs->if_mode);
-
-	/* TX_FIFO_SECTIONS */
-	tmp = 0;
-	if (phy_if == PHY_INTERFACE_MODE_XGMII) {
-		if (slow_10g_if) {
-			tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G |
-				TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);
-		} else {
-			tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G |
-				TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);
-		}
-	} else {
-		tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G |
-			TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G);
-	}
-	iowrite32be(tmp, &regs->tx_fifo_sections);
-
 	/* clear all pending events and set-up interrupts */
 	iowrite32be(0xffffffff, &regs->ievent);
 	set_exception(regs, exceptions, true);
@@ -458,24 +429,6 @@ static u32 get_mac_addr_hash_code(u64 eth_addr)
 	return xor_val;
 }
 
-static void setup_sgmii_internal(struct fman_mac *memac,
-				 struct phylink_pcs *pcs,
-				 struct fixed_phy_status *fixed_link)
-{
-	__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
-	phy_interface_t iface = memac->basex_if ? PHY_INTERFACE_MODE_1000BASEX :
-				PHY_INTERFACE_MODE_SGMII;
-	unsigned int mode = fixed_link ? MLO_AN_FIXED : MLO_AN_INBAND;
-
-	linkmode_set_pause(advertising, true, true);
-	pcs->ops->pcs_config(pcs, mode, iface, advertising, true);
-	if (fixed_link)
-		pcs->ops->pcs_link_up(pcs, mode, iface, fixed_link->speed,
-				      fixed_link->duplex);
-	else
-		pcs->ops->pcs_an_restart(pcs);
-}
-
 static int check_init_parameters(struct fman_mac *memac)
 {
 	if (!memac->exception_cb) {
@@ -581,53 +534,11 @@ static void free_init_resources(struct fman_mac *memac)
 	memac->unicast_addr_hash = NULL;
 }
 
-static bool is_init_done(struct memac_cfg *memac_drv_params)
-{
-	/* Checks if mEMAC driver parameters were initialized */
-	if (!memac_drv_params)
-		return true;
-
-	return false;
-}
-
-static int memac_enable(struct fman_mac *memac)
-{
-	struct memac_regs __iomem *regs = memac->regs;
-	u32 tmp;
-
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
-	tmp = ioread32be(&regs->command_config);
-	tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN;
-	iowrite32be(tmp, &regs->command_config);
-
-	return 0;
-}
-
-static int memac_disable(struct fman_mac *memac)
-{
-	struct memac_regs __iomem *regs = memac->regs;
-	u32 tmp;
-
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
-	tmp = ioread32be(&regs->command_config);
-	tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN);
-	iowrite32be(tmp, &regs->command_config);
-
-	return 0;
-}
-
 static int memac_set_promiscuous(struct fman_mac *memac, bool new_val)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
 
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
 	tmp = ioread32be(&regs->command_config);
 	if (new_val)
 		tmp |= CMD_CFG_PROMIS_EN;
@@ -639,72 +550,12 @@ static int memac_set_promiscuous(struct fman_mac *memac, bool new_val)
 	return 0;
 }
 
-static int memac_adjust_link(struct fman_mac *memac, u16 speed)
-{
-	struct memac_regs __iomem *regs = memac->regs;
-	u32 tmp;
-
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
-	tmp = ioread32be(&regs->if_mode);
-
-	/* Set full duplex */
-	tmp &= ~IF_MODE_HD;
-
-	if (phy_interface_mode_is_rgmii(memac->phy_if)) {
-		/* Configure RGMII in manual mode */
-		tmp &= ~IF_MODE_RGMII_AUTO;
-		tmp &= ~IF_MODE_RGMII_SP_MASK;
-		/* Full duplex */
-		tmp |= IF_MODE_RGMII_FD;
-
-		switch (speed) {
-		case SPEED_1000:
-			tmp |= IF_MODE_RGMII_1000;
-			break;
-		case SPEED_100:
-			tmp |= IF_MODE_RGMII_100;
-			break;
-		case SPEED_10:
-			tmp |= IF_MODE_RGMII_10;
-			break;
-		default:
-			break;
-		}
-	}
-
-	iowrite32be(tmp, &regs->if_mode);
-
-	return 0;
-}
-
-static void adjust_link_memac(struct mac_device *mac_dev)
-{
-	struct phy_device *phy_dev = mac_dev->phy_dev;
-	struct fman_mac *fman_mac;
-	bool rx_pause, tx_pause;
-	int err;
-
-	fman_mac = mac_dev->fman_mac;
-	memac_adjust_link(fman_mac, phy_dev->speed);
-
-	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
-	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
-	if (err < 0)
-		dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n",
-			err);
-}
-
 static int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority,
 				     u16 pause_time, u16 thresh_time)
 {
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
 
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
 	tmp = ioread32be(&regs->tx_fifo_sections);
 
 	GET_TX_EMPTY_DEFAULT_VALUE(tmp);
@@ -739,9 +590,6 @@ static int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en)
 	struct memac_regs __iomem *regs = memac->regs;
 	u32 tmp;
 
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
 	tmp = ioread32be(&regs->command_config);
 	if (en)
 		tmp &= ~CMD_CFG_PAUSE_IGNORE;
@@ -753,12 +601,160 @@ static int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en)
 	return 0;
 }
 
+/**
+ * memac_if_mode() - Convert an interface mode into an IF_MODE config
+ * @interface: A phy interface mode
+ *
+ * Return: A configuration word, suitable for programming into the lower bits
+ *         of %IF_MODE.
+ */
+static u32 memac_if_mode(phy_interface_t interface)
+{
+	switch (interface) {
+	case PHY_INTERFACE_MODE_MII:
+		return IF_MODE_MII;
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		return IF_MODE_GMII | IF_MODE_RGMII;
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_1000BASEX:
+	case PHY_INTERFACE_MODE_QSGMII:
+		return IF_MODE_GMII;
+	case PHY_INTERFACE_MODE_10GBASER:
+		return IF_MODE_10G;
+	default:
+		WARN_ON_ONCE(1);
+		return 0;
+	}
+}
+
+static struct phylink_pcs *memac_select_pcs(struct phylink_config *config,
+					    phy_interface_t iface)
+{
+	struct fman_mac *memac = fman_config_to_mac(config)->fman_mac;
+
+	switch (iface) {
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_1000BASEX:
+		return memac->sgmii_pcs;
+	case PHY_INTERFACE_MODE_QSGMII:
+		return memac->qsgmii_pcs;
+	case PHY_INTERFACE_MODE_10GBASER:
+		return memac->xfi_pcs;
+	default:
+		return NULL;
+	}
+}
+
+static int memac_prepare(struct phylink_config *config, unsigned int mode,
+			 phy_interface_t iface)
+{
+	struct fman_mac *memac = fman_config_to_mac(config)->fman_mac;
+
+	switch (iface) {
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_1000BASEX:
+	case PHY_INTERFACE_MODE_QSGMII:
+	case PHY_INTERFACE_MODE_10GBASER:
+		return phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET,
+					iface);
+	default:
+		return 0;
+	}
+}
+
+static void memac_mac_config(struct phylink_config *config, unsigned int mode,
+			     const struct phylink_link_state *state)
+{
+	struct mac_device *mac_dev = fman_config_to_mac(config);
+	struct memac_regs __iomem *regs = mac_dev->fman_mac->regs;
+	u32 tmp = ioread32be(&regs->if_mode);
+
+	tmp &= ~(IF_MODE_MASK | IF_MODE_RGMII);
+	tmp |= memac_if_mode(state->interface);
+	if (phylink_autoneg_inband(mode))
+		tmp |= IF_MODE_RGMII_AUTO;
+	iowrite32be(tmp, &regs->if_mode);
+}
+
+static void memac_link_up(struct phylink_config *config, struct phy_device *phy,
+			  unsigned int mode, phy_interface_t interface,
+			  int speed, int duplex, bool tx_pause, bool rx_pause)
+{
+	struct mac_device *mac_dev = fman_config_to_mac(config);
+	struct fman_mac *memac = mac_dev->fman_mac;
+	struct memac_regs __iomem *regs = memac->regs;
+	u32 tmp = memac_if_mode(interface);
+	u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE :
+			 FSL_FM_PAUSE_TIME_DISABLE;
+
+	memac_set_tx_pause_frames(memac, 0, pause_time, 0);
+	memac_accept_rx_pause_frames(memac, rx_pause);
+
+	if (duplex == DUPLEX_HALF)
+		tmp |= IF_MODE_HD;
+
+	switch (speed) {
+	case SPEED_1000:
+		tmp |= IF_MODE_RGMII_1000;
+		break;
+	case SPEED_100:
+		tmp |= IF_MODE_RGMII_100;
+		break;
+	case SPEED_10:
+		tmp |= IF_MODE_RGMII_10;
+		break;
+	}
+	iowrite32be(tmp, &regs->if_mode);
+
+	if (phy)
+		phy_init_eee(phy, 0);
+
+	if (speed == SPEED_10000) {
+		if (memac->fm_rev_info.major == 6 &&
+		    memac->fm_rev_info.minor == 4)
+			tmp = TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G;
+		else
+			tmp = TX_FIFO_SECTIONS_TX_AVAIL_10G;
+		tmp |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G;
+	} else {
+		tmp = TX_FIFO_SECTIONS_TX_AVAIL_1G |
+		      TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G;
+	}
+	iowrite32be(tmp, &regs->tx_fifo_sections);
+
+	tmp = ioread32be(&regs->command_config);
+	tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN;
+	iowrite32be(tmp, &regs->command_config);
+}
+
+static void memac_link_down(struct phylink_config *config, unsigned int mode,
+			    phy_interface_t interface)
+{
+	struct fman_mac *memac = fman_config_to_mac(config)->fman_mac;
+	struct memac_regs __iomem *regs = memac->regs;
+	u32 tmp;
+
+	/* TODO: graceful */
+	tmp = ioread32be(&regs->command_config);
+	tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN);
+	iowrite32be(tmp, &regs->command_config);
+}
+
+static const struct phylink_mac_ops memac_phylink_mac_ops = {
+	.validate = phylink_generic_validate,
+	.mac_select_pcs = memac_select_pcs,
+	.mac_prepare = memac_prepare,
+	.mac_config = memac_mac_config,
+	.mac_link_up = memac_link_up,
+	.mac_link_down = memac_link_down,
+};
+
 static int memac_modify_mac_address(struct fman_mac *memac,
 				    const enet_addr_t *enet_addr)
 {
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
 	add_addr_in_paddr(memac->regs, (const u8 *)(*enet_addr), 0);
 
 	return 0;
@@ -772,9 +768,6 @@ static int memac_add_hash_mac_address(struct fman_mac *memac,
 	u32 hash;
 	u64 addr;
 
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
 	addr = ENET_ADDR_TO_UINT64(*eth_addr);
 
 	if (!(addr & GROUP_ADDRESS)) {
@@ -803,9 +796,6 @@ static int memac_set_allmulti(struct fman_mac *memac, bool enable)
 	u32 entry;
 	struct memac_regs __iomem *regs = memac->regs;
 
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
 	if (enable) {
 		for (entry = 0; entry < HASH_TABLE_SIZE; entry++)
 			iowrite32be(entry | HASH_CTRL_MCAST_EN,
@@ -835,9 +825,6 @@ static int memac_del_hash_mac_address(struct fman_mac *memac,
 	u32 hash;
 	u64 addr;
 
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
 	addr = ENET_ADDR_TO_UINT64(*eth_addr);
 
 	hash = get_mac_addr_hash_code(addr) & HASH_CTRL_ADDR_MASK;
@@ -865,9 +852,6 @@ static int memac_set_exception(struct fman_mac *memac,
 {
 	u32 bit_mask = 0;
 
-	if (!is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
 	bit_mask = get_exception_flag(exception);
 	if (bit_mask) {
 		if (enable)
@@ -888,13 +872,9 @@ static int memac_init(struct fman_mac *memac)
 	struct memac_cfg *memac_drv_param;
 	enet_addr_t eth_addr;
 	bool slow_10g_if = false;
-	struct fixed_phy_status *fixed_link;
 	int err;
 	u32 reg32 = 0;
 
-	if (is_init_done(memac->memac_drv_param))
-		return -EINVAL;
-
 	err = check_init_parameters(memac);
 	if (err)
 		return err;
@@ -919,10 +899,7 @@ static int memac_init(struct fman_mac *memac)
 		add_addr_in_paddr(memac->regs, (const u8 *)eth_addr, 0);
 	}
 
-	fixed_link = memac_drv_param->fixed_link;
-
-	init(memac->regs, memac->memac_drv_param, memac->phy_if,
-	     memac->max_speed, slow_10g_if, memac->exceptions);
+	init(memac->regs, memac->memac_drv_param, memac->exceptions);
 
 	/* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 errata workaround
 	 * Exists only in FMan 6.0 and 6.3.
@@ -938,11 +915,6 @@ static int memac_init(struct fman_mac *memac)
 		iowrite32be(reg32, &memac->regs->command_config);
 	}
 
-	if (memac->phy_if == PHY_INTERFACE_MODE_SGMII)
-		setup_sgmii_internal(memac, memac->sgmii_pcs, fixed_link);
-	else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII)
-		setup_sgmii_internal(memac, memac->qsgmii_pcs, fixed_link);
-
 	/* Max Frame Length */
 	err = fman_set_mac_max_frame(memac->fm, memac->mac_id,
 				     memac_drv_param->max_frame_length);
@@ -971,9 +943,6 @@ static int memac_init(struct fman_mac *memac)
 	fman_register_intr(memac->fm, FMAN_MOD_MAC, memac->mac_id,
 			   FMAN_INTR_TYPE_NORMAL, memac_exception, memac);
 
-	kfree(memac_drv_param);
-	memac->memac_drv_param = NULL;
-
 	return 0;
 }
 
@@ -1020,8 +989,6 @@ static struct fman_mac *memac_config(struct mac_device *mac_dev,
 	memac->addr = ENET_ADDR_TO_UINT64(mac_dev->addr);
 
 	memac->regs = mac_dev->vaddr;
-	memac->max_speed = params->max_speed;
-	memac->phy_if = mac_dev->phy_if;
 	memac->mac_id = params->mac_id;
 	memac->exceptions = (MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER |
 			     MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI);
@@ -1029,7 +996,6 @@ static struct fman_mac *memac_config(struct mac_device *mac_dev,
 	memac->event_cb = params->event_cb;
 	memac->dev_id = mac_dev;
 	memac->fm = params->fm;
-	memac->basex_if = params->basex_if;
 
 	/* Save FMan revision */
 	fman_get_revision(memac->fm, &memac->fm_rev_info);
@@ -1054,33 +1020,40 @@ static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node,
 	return lynx_pcs_create(mdiodev) ?: ERR_PTR(-ENOMEM);
 }
 
+static bool memac_supports(struct mac_device *mac_dev, phy_interface_t iface)
+{
+	/* If there's no serdes device, assume that it's been configured for
+	 * whatever the default interface mode is.
+	 */
+	if (!mac_dev->fman_mac->serdes)
+		return mac_dev->phy_if == iface;
+	/* Otherwise, ask the serdes */
+	return !phy_validate(mac_dev->fman_mac->serdes, PHY_MODE_ETHERNET,
+			     iface, NULL);
+}
+
 int memac_initialization(struct mac_device *mac_dev,
 			 struct device_node *mac_node,
 			 struct fman_mac_params *params)
 {
 	int			 err;
+	struct device_node	*fixed;
 	struct mac_priv_s	*priv;
 	struct phylink_pcs	*pcs;
-	struct fixed_phy_status *fixed_link;
 	struct fman_mac		*memac;
+	unsigned long		capabilities;
+	unsigned long		*supported;
 
 	priv = mac_dev->priv;
+	mac_dev->phylink_ops		= &memac_phylink_mac_ops;
 	mac_dev->set_promisc		= memac_set_promiscuous;
 	mac_dev->change_addr		= memac_modify_mac_address;
 	mac_dev->add_hash_mac_addr	= memac_add_hash_mac_address;
 	mac_dev->remove_hash_mac_addr	= memac_del_hash_mac_address;
-	mac_dev->set_tx_pause		= memac_set_tx_pause_frames;
-	mac_dev->set_rx_pause		= memac_accept_rx_pause_frames;
 	mac_dev->set_exception		= memac_set_exception;
 	mac_dev->set_allmulti		= memac_set_allmulti;
 	mac_dev->set_tstamp		= memac_set_tstamp;
 	mac_dev->set_multi		= fman_set_multi;
-	mac_dev->adjust_link            = adjust_link_memac;
-	mac_dev->enable			= memac_enable;
-	mac_dev->disable		= memac_disable;
-
-	if (params->max_speed == SPEED_10000)
-		mac_dev->phy_if = PHY_INTERFACE_MODE_XGMII;
 
 	mac_dev->fman_mac = memac_config(mac_dev, params);
 	if (!mac_dev->fman_mac) {
@@ -1150,6 +1123,7 @@ int memac_initialization(struct mac_device *mac_dev,
 		dev_err_probe(mac_dev->dev, err, "could not get serdes\n");
 		goto _return_fm_mac_free;
 	} else {
+		/* FIXME: init/power on at an appropriate time... */
 		err = phy_init(memac->serdes);
 		if (err) {
 			dev_err_probe(mac_dev->dev, err,
@@ -1163,57 +1137,114 @@ int memac_initialization(struct mac_device *mac_dev,
 				      "could not power on serdes\n");
 			goto _return_phy_exit;
 		}
+	}
 
-		if (memac->phy_if == PHY_INTERFACE_MODE_SGMII ||
-		    memac->phy_if == PHY_INTERFACE_MODE_1000BASEX ||
-		    memac->phy_if == PHY_INTERFACE_MODE_2500BASEX ||
-		    memac->phy_if == PHY_INTERFACE_MODE_QSGMII ||
-		    memac->phy_if == PHY_INTERFACE_MODE_XGMII) {
-			err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET,
-					       memac->phy_if);
-			if (err) {
-				dev_err_probe(mac_dev->dev, err,
-					      "could not set serdes mode to %s\n",
-					      phy_modes(memac->phy_if));
-				goto _return_phy_power_off;
-			}
-		}
+	/* The internal connection to the serdes is XGMII, but this isn't
+	 * really correct for the phy mode (which is the external connection).
+	 * However, this is how all older device trees say that they want
+	 * 10GBase-R (aka XFI), so just convert it for them.
+	 */
+	if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII)
+		mac_dev->phy_if = PHY_INTERFACE_MODE_10GBASER;
+
+	/* TODO: The following interface modes are supported by (some) hardware
+	 * but not by this driver:
+	 * - 1000Base-KX
+	 * - 10GBase-KR
+	 * - XAUI/HiGig
+	 */
+	supported = mac_dev->phylink_config.supported_interfaces;
+	capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
+
+	/* Note that half duplex is only supported on 10/100M interfaces. */
+
+	if (memac->sgmii_pcs &&
+	    (memac_supports(mac_dev, PHY_INTERFACE_MODE_SGMII) ||
+	     memac_supports(mac_dev, PHY_INTERFACE_MODE_1000BASEX))) {
+		capabilities |= MAC_10 | MAC_100 | MAC_1000FD;
+		__set_bit(PHY_INTERFACE_MODE_SGMII, supported);
+		__set_bit(PHY_INTERFACE_MODE_1000BASEX, supported);
 	}
 
-	if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
-		struct phy_device *phy;
+	if (memac->sgmii_pcs &&
+	    memac_supports(mac_dev, PHY_INTERFACE_MODE_2500BASEX)) {
+		capabilities |= MAC_2500FD;
+		__set_bit(PHY_INTERFACE_MODE_2500BASEX, supported);
+	}
 
-		err = of_phy_register_fixed_link(mac_node);
-		if (err)
-			goto _return_phy_power_off;
+	if (memac->qsgmii_pcs &&
+	    memac_supports(mac_dev, PHY_INTERFACE_MODE_QSGMII)) {
+		capabilities |= MAC_10 | MAC_100 | MAC_1000FD;
+		__set_bit(PHY_INTERFACE_MODE_QSGMII, supported);
+	} else if (mac_dev->phy_if == PHY_INTERFACE_MODE_QSGMII) {
+		dev_warn(mac_dev->dev, "no QSGMII pcs specified\n");
+	}
+
+	if (memac->xfi_pcs &&
+	    memac_supports(mac_dev, PHY_INTERFACE_MODE_10GBASER)) {
+		capabilities |= MAC_10000FD;
+		__set_bit(PHY_INTERFACE_MODE_10GBASER, supported);
+	} else {
+		/* From what I can tell, only 1G macs support RGMII. */
+		/* For compatibility, default to enabled if the rgmii property
+		 * is absent
+		 */
+		unsigned int rgmii = 1;
 
-		fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL);
-		if (!fixed_link) {
-			err = -ENOMEM;
+		err = of_property_read_u32(mac_node, "rgmii", &rgmii);
+		if (err == -EINVAL)
+			dev_warn(mac_dev->dev,
+				 "missing 'rgmii' property; assuming supported\n");
+		else if (err)
 			goto _return_phy_power_off;
-		}
 
-		mac_dev->phy_node = of_node_get(mac_node);
-		phy = of_phy_find_device(mac_dev->phy_node);
-		if (!phy) {
-			err = -EINVAL;
-			of_node_put(mac_dev->phy_node);
-			goto _return_fixed_link_free;
+		if (rgmii) {
+			capabilities |= MAC_10FD | MAC_100FD | MAC_1000FD;
+			/* The T2080 and T4240 don't support half duplex RGMII.
+			 * There is no other way to identify these SoCs, so
+			 * just use the machine compatible.
+			 */
+			if (!of_machine_is_compatible("fsl,T2080QDS") &&
+			    !of_machine_is_compatible("fsl,T2080RDB") &&
+			    !of_machine_is_compatible("fsl,T2081QDS") &&
+			    !of_machine_is_compatible("fsl,T4240QDS") &&
+			    !of_machine_is_compatible("fsl,T4240RDB"))
+				capabilities |= MAC_10HD | MAC_100HD;
+			phy_interface_set_rgmii(supported);
+
+			if (of_property_read_bool(mac_node, "mii"))
+				__set_bit(PHY_INTERFACE_MODE_MII, supported);
 		}
+	}
 
-		fixed_link->link = phy->link;
-		fixed_link->speed = phy->speed;
-		fixed_link->duplex = phy->duplex;
-		fixed_link->pause = phy->pause;
-		fixed_link->asym_pause = phy->asym_pause;
+	/* These SoCs don't support half duplex at all; there's no different
+	 * FMan version or compatible, so we just have to check the machine
+	 * compatible instead
+	 */
+	if (of_machine_is_compatible("fsl,ls1043a") ||
+	    of_machine_is_compatible("fsl,ls1046a") ||
+	    of_machine_is_compatible("fsl,B4QDS"))
+		capabilities &= ~(MAC_10HD | MAC_100HD);
 
-		put_device(&phy->mdio.dev);
-		memac->memac_drv_param->fixed_link = fixed_link;
-	}
+	mac_dev->phylink_config.mac_capabilities = capabilities;
+
+	/* Most boards should use MLO_AN_INBAND, but existing boards don't have
+	 * a managed property. Default to MLO_AN_INBAND if nothing else is
+	 * specified. We need to be careful and not enable this if we have a
+	 * fixed link or if we are using MII or RGMII, since those
+	 * configurations modes don't use in-band autonegotiation.
+	 */
+	fixed = of_get_child_by_name(mac_node, "fixed-link");
+	if (!fixed && !of_property_read_bool(mac_node, "fixed-link") &&
+	    !of_property_read_bool(mac_node, "managed") &&
+	    mac_dev->phy_if != PHY_INTERFACE_MODE_MII &&
+	    !phy_interface_mode_is_rgmii(mac_dev->phy_if))
+		mac_dev->phylink_config.ovr_an_inband = true;
+	of_node_put(fixed);
 
 	err = memac_init(mac_dev->fman_mac);
 	if (err < 0)
-		goto _return_fixed_link_free;
+		goto _return_fm_mac_free;
 
 	dev_info(mac_dev->dev, "FMan MEMAC\n");
 
@@ -1223,8 +1254,6 @@ int memac_initialization(struct mac_device *mac_dev,
 	phy_power_off(memac->serdes);
 _return_phy_exit:
 	phy_exit(memac->serdes);
-_return_fixed_link_free:
-	kfree(fixed_link);
 _return_fm_mac_free:
 	memac_free(mac_dev->fman_mac);
 _return:
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index c02f38ab335e..f59e71c23569 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -15,6 +15,7 @@
 #include <linux/phy.h>
 #include <linux/netdevice.h>
 #include <linux/phy_fixed.h>
+#include <linux/phylink.h>
 #include <linux/etherdevice.h>
 #include <linux/libfdt_env.h>
 
@@ -98,130 +99,8 @@ int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
 	return 0;
 }
 
-/**
- * fman_set_mac_active_pause
- * @mac_dev:	A pointer to the MAC device
- * @rx:		Pause frame setting for RX
- * @tx:		Pause frame setting for TX
- *
- * Set the MAC RX/TX PAUSE frames settings
- *
- * Avoid redundant calls to FMD, if the MAC driver already contains the desired
- * active PAUSE settings. Otherwise, the new active settings should be reflected
- * in FMan.
- *
- * Return: 0 on success; Error code otherwise.
- */
-int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx)
-{
-	struct fman_mac *fman_mac = mac_dev->fman_mac;
-	int err = 0;
-
-	if (rx != mac_dev->rx_pause_active) {
-		err = mac_dev->set_rx_pause(fman_mac, rx);
-		if (likely(err == 0))
-			mac_dev->rx_pause_active = rx;
-	}
-
-	if (tx != mac_dev->tx_pause_active) {
-		u16 pause_time = (tx ? FSL_FM_PAUSE_TIME_ENABLE :
-					 FSL_FM_PAUSE_TIME_DISABLE);
-
-		err = mac_dev->set_tx_pause(fman_mac, 0, pause_time, 0);
-
-		if (likely(err == 0))
-			mac_dev->tx_pause_active = tx;
-	}
-
-	return err;
-}
-EXPORT_SYMBOL(fman_set_mac_active_pause);
-
-/**
- * fman_get_pause_cfg
- * @mac_dev:	A pointer to the MAC device
- * @rx_pause:	Return value for RX setting
- * @tx_pause:	Return value for TX setting
- *
- * Determine the MAC RX/TX PAUSE frames settings based on PHY
- * autonegotiation or values set by eththool.
- *
- * Return: Pointer to FMan device.
- */
-void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause,
-			bool *tx_pause)
-{
-	struct phy_device *phy_dev = mac_dev->phy_dev;
-	u16 lcl_adv, rmt_adv;
-	u8 flowctrl;
-
-	*rx_pause = *tx_pause = false;
-
-	if (!phy_dev->duplex)
-		return;
-
-	/* If PAUSE autonegotiation is disabled, the TX/RX PAUSE settings
-	 * are those set by ethtool.
-	 */
-	if (!mac_dev->autoneg_pause) {
-		*rx_pause = mac_dev->rx_pause_req;
-		*tx_pause = mac_dev->tx_pause_req;
-		return;
-	}
-
-	/* Else if PAUSE autonegotiation is enabled, the TX/RX PAUSE
-	 * settings depend on the result of the link negotiation.
-	 */
-
-	/* get local capabilities */
-	lcl_adv = linkmode_adv_to_lcl_adv_t(phy_dev->advertising);
-
-	/* get link partner capabilities */
-	rmt_adv = 0;
-	if (phy_dev->pause)
-		rmt_adv |= LPA_PAUSE_CAP;
-	if (phy_dev->asym_pause)
-		rmt_adv |= LPA_PAUSE_ASYM;
-
-	/* Calculate TX/RX settings based on local and peer advertised
-	 * symmetric/asymmetric PAUSE capabilities.
-	 */
-	flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
-	if (flowctrl & FLOW_CTRL_RX)
-		*rx_pause = true;
-	if (flowctrl & FLOW_CTRL_TX)
-		*tx_pause = true;
-}
-EXPORT_SYMBOL(fman_get_pause_cfg);
-
-#define DTSEC_SUPPORTED \
-	(SUPPORTED_10baseT_Half \
-	| SUPPORTED_10baseT_Full \
-	| SUPPORTED_100baseT_Half \
-	| SUPPORTED_100baseT_Full \
-	| SUPPORTED_Autoneg \
-	| SUPPORTED_Pause \
-	| SUPPORTED_Asym_Pause \
-	| SUPPORTED_FIBRE \
-	| SUPPORTED_MII)
-
 static DEFINE_MUTEX(eth_lock);
 
-static const u16 phy2speed[] = {
-	[PHY_INTERFACE_MODE_MII]		= SPEED_100,
-	[PHY_INTERFACE_MODE_GMII]		= SPEED_1000,
-	[PHY_INTERFACE_MODE_SGMII]		= SPEED_1000,
-	[PHY_INTERFACE_MODE_TBI]		= SPEED_1000,
-	[PHY_INTERFACE_MODE_RMII]		= SPEED_100,
-	[PHY_INTERFACE_MODE_RGMII]		= SPEED_1000,
-	[PHY_INTERFACE_MODE_RGMII_ID]		= SPEED_1000,
-	[PHY_INTERFACE_MODE_RGMII_RXID]	= SPEED_1000,
-	[PHY_INTERFACE_MODE_RGMII_TXID]	= SPEED_1000,
-	[PHY_INTERFACE_MODE_RTBI]		= SPEED_1000,
-	[PHY_INTERFACE_MODE_QSGMII]		= SPEED_1000,
-	[PHY_INTERFACE_MODE_XGMII]		= SPEED_10000
-};
-
 static struct platform_device *dpaa_eth_add_device(int fman_id,
 						   struct mac_device *mac_dev)
 {
@@ -268,8 +147,9 @@ static struct platform_device *dpaa_eth_add_device(int fman_id,
 }
 
 static const struct of_device_id mac_match[] = {
-	{ .compatible	= "fsl,fman-dtsec", .data = dtsec_initialization },
-	{ .compatible	= "fsl,fman-xgec", .data = tgec_initialization },
+	// TODO
+	//{ .compatible   = "fsl,fman-dtsec", .data = dtsec_initialization },
+	//{ .compatible   = "fsl,fman-xgec", .data = tgec_initialization },
 	{ .compatible	= "fsl,fman-memac", .data = memac_initialization },
 	{}
 };
@@ -301,6 +181,7 @@ static int mac_probe(struct platform_device *_of_dev)
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
+	platform_set_drvdata(_of_dev, mac_dev);
 
 	/* Save private information */
 	mac_dev->priv = priv;
@@ -429,57 +310,21 @@ static int mac_probe(struct platform_device *_of_dev)
 	}
 	mac_dev->phy_if = phy_if;
 
-	priv->speed		= phy2speed[mac_dev->phy_if];
-	params.max_speed	= priv->speed;
-	mac_dev->if_support	= DTSEC_SUPPORTED;
-	/* We don't support half-duplex in SGMII mode */
-	if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII)
-		mac_dev->if_support &= ~(SUPPORTED_10baseT_Half |
-					SUPPORTED_100baseT_Half);
-
-	/* Gigabit support (no half-duplex) */
-	if (params.max_speed == 1000)
-		mac_dev->if_support |= SUPPORTED_1000baseT_Full;
-
-	/* The 10G interface only supports one mode */
-	if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII)
-		mac_dev->if_support = SUPPORTED_10000baseT_Full;
-
-	/* Get the rest of the PHY information */
-	mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0);
-
-	params.basex_if		= false;
 	params.mac_id		= priv->cell_index;
 	params.fm		= (void *)priv->fman;
 	params.exception_cb	= mac_exception;
 	params.event_cb		= mac_exception;
 
 	err = init(mac_dev, mac_node, &params);
-	if (err < 0) {
-		dev_err(dev, "mac_dev->init() = %d\n", err);
-		of_node_put(mac_dev->phy_node);
-		return err;
-	}
-
-	/* pause frame autonegotiation enabled */
-	mac_dev->autoneg_pause = true;
-
-	/* By intializing the values to false, force FMD to enable PAUSE frames
-	 * on RX and TX
-	 */
-	mac_dev->rx_pause_req = true;
-	mac_dev->tx_pause_req = true;
-	mac_dev->rx_pause_active = false;
-	mac_dev->tx_pause_active = false;
-	err = fman_set_mac_active_pause(mac_dev, true, true);
 	if (err < 0)
-		dev_err(dev, "fman_set_mac_active_pause() = %d\n", err);
+		return err;
 
 	if (!is_zero_ether_addr(mac_dev->addr))
 		dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr);
 
 	priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev);
 	if (IS_ERR(priv->eth_dev)) {
+		err = PTR_ERR(priv->eth_dev);
 		dev_err(dev, "failed to add Ethernet platform device for MAC %d\n",
 			priv->cell_index);
 		priv->eth_dev = NULL;
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index c5fb4d46210f..199ea046580a 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -9,6 +9,7 @@
 #include <linux/device.h>
 #include <linux/if_ether.h>
 #include <linux/phy.h>
+#include <linux/phylink.h>
 #include <linux/list.h>
 
 #include "fman_port.h"
@@ -24,31 +25,20 @@ struct mac_device {
 	struct device		*dev;
 	u8			 addr[ETH_ALEN];
 	struct fman_port	*port[2];
-	u32			 if_support;
-	struct phy_device	*phy_dev;
+	struct phylink		*phylink;
+	struct phylink_config	phylink_config;
 	phy_interface_t		phy_if;
-	struct device_node	*phy_node;
 
-	bool autoneg_pause;
-	bool rx_pause_req;
-	bool tx_pause_req;
-	bool rx_pause_active;
-	bool tx_pause_active;
 	bool promisc;
 	bool allmulti;
 
-	int (*enable)(struct fman_mac *mac_dev);
-	int (*disable)(struct fman_mac *mac_dev);
-	void (*adjust_link)(struct mac_device *mac_dev);
+	const struct phylink_mac_ops *phylink_ops;
 	int (*set_promisc)(struct fman_mac *mac_dev, bool enable);
 	int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr);
 	int (*set_allmulti)(struct fman_mac *mac_dev, bool enable);
 	int (*set_tstamp)(struct fman_mac *mac_dev, bool enable);
 	int (*set_multi)(struct net_device *net_dev,
 			 struct mac_device *mac_dev);
-	int (*set_rx_pause)(struct fman_mac *mac_dev, bool en);
-	int (*set_tx_pause)(struct fman_mac *mac_dev, u8 priority,
-			    u16 pause_time, u16 thresh_time);
 	int (*set_exception)(struct fman_mac *mac_dev,
 			     enum fman_mac_exceptions exception, bool enable);
 	int (*add_hash_mac_addr)(struct fman_mac *mac_dev,
@@ -60,6 +50,12 @@ struct mac_device {
 	struct mac_priv_s	*priv;
 };
 
+static inline struct mac_device
+*fman_config_to_mac(struct phylink_config *config)
+{
+	return container_of(config, struct mac_device, phylink_config);
+}
+
 struct dpaa_eth_data {
 	struct mac_device *mac_dev;
 	int mac_hw_id;
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 26/28] arm64: dts: ls1046ardb: Add serdes bindings
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (24 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 27/28] arm64: dts: ls1046a: Add SerDes bindings Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 28/28] arm64: dts: ls1046a: Specify which MACs support RGMII Sean Anderson
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Krzysztof Kozlowski, Li Yang,
	Rob Herring, Shawn Guo, devicetree

This adds appropriate bindings for the macs which use the SerDes. The
156.25MHz fixed clock is a crystal. The 100MHz clocks (there are
actually 3) come from a Renesas 6V49205B at address 69 on i2c0. There is
no driver for this device (and as far as I know all you can do with the
100MHz clocks is gate them), so I have chosen to model it as a single
fixed clock.

Note: the SerDes1 lane numbering for the LS1046A is *reversed*.
This means that Lane A (what the driver thinks is lane 0) uses pins
SD1_TX3_P/N.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 .../boot/dts/freescale/fsl-ls1046a-rdb.dts    | 32 +++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
index 7025aad8ae89..21a153349359 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
@@ -26,6 +26,30 @@ aliases {
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
+
+	clocks {
+		clk_100mhz: clock-100mhz {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <100000000>;
+		};
+
+		clk_156mhz: clock-156mhz {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <156250000>;
+		};
+	};
+};
+
+&serdes1 {
+	clocks = <&clk_100mhz>, <&clk_156mhz>;
+	clock-names = "ref0", "ref1";
+};
+
+&serdes2 {
+	clocks = <&clk_100mhz>, <&clk_100mhz>;
+	clock-names = "ref0", "ref1";
 };
 
 &duart0 {
@@ -140,21 +164,29 @@ ethernet@e6000 {
 	ethernet@e8000 {
 		phy-handle = <&sgmii_phy1>;
 		phy-connection-type = "sgmii";
+		phys = <&serdes1 1 1>;
+		phy-names = "serdes";
 	};
 
 	ethernet@ea000 {
 		phy-handle = <&sgmii_phy2>;
 		phy-connection-type = "sgmii";
+		phys = <&serdes1 0 0>;
+		phy-names = "serdes";
 	};
 
 	ethernet@f0000 { /* 10GEC1 */
 		phy-handle = <&aqr106_phy>;
 		phy-connection-type = "xgmii";
+		phys = <&serdes1 3 3>;
+		phy-names = "serdes";
 	};
 
 	ethernet@f2000 { /* 10GEC2 */
 		fixed-link = <0 1 1000 0 0>;
 		phy-connection-type = "xgmii";
+		phys = <&serdes1 2 2>;
+		phy-names = "serdes";
 	};
 
 	mdio@fc000 {
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 27/28] arm64: dts: ls1046a: Add SerDes bindings
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (25 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 26/28] arm64: dts: ls1046ardb: Add serdes bindings Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  2022-06-17 20:33 ` [PATCH net-next 28/28] arm64: dts: ls1046a: Specify which MACs support RGMII Sean Anderson
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Krzysztof Kozlowski, Li Yang,
	Rob Herring, Shawn Guo, devicetree

This adds bindings for the SerDes devices.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 0085e83adf65..de2cf36824fb 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -413,6 +413,18 @@ bportals: bman-portals@508000000 {
 			ranges = <0x0 0x5 0x08000000 0x8000000>;
 		};
 
+		serdes1: phy@1ea0000 {
+			#phy-cells = <2>;
+			compatible = "fsl,ls1046a-serdes-1";
+			reg = <0x0 0x1ea0000 0x0 0x2000>;
+		};
+
+		serdes2: phy@1eb0000 {
+			#phy-cells = <2>;
+			compatible = "fsl,ls1046a-serdes-2";
+			reg = <0x0 0x1eb0000 0x0 0x2000>;
+		};
+
 		dcfg: dcfg@1ee0000 {
 			compatible = "fsl,ls1046a-dcfg", "syscon";
 			reg = <0x0 0x1ee0000 0x0 0x1000>;
-- 
2.35.1.1320.gc452695387.dirty


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

* [PATCH net-next 28/28] arm64: dts: ls1046a: Specify which MACs support RGMII
  2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
                   ` (26 preceding siblings ...)
  2022-06-17 20:33 ` [PATCH net-next 27/28] arm64: dts: ls1046a: Add SerDes bindings Sean Anderson
@ 2022-06-17 20:33 ` Sean Anderson
  27 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-17 20:33 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Sean Anderson, Krzysztof Kozlowski, Li Yang,
	Rob Herring, Shawn Guo, devicetree

For more precise link mode support, we can add a property specifying
which MACs support RGMII. This silences the warning

	missing 'rgmii' property; assuming supported

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi
index d6caaea57d90..4bb314388a72 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi
@@ -23,26 +23,34 @@ &soc {
 &fman0 {
 	/* these aliases provide the FMan ports mapping */
 	enet0: ethernet@e0000 {
+		rgmii = <0>;
 	};
 
 	enet1: ethernet@e2000 {
+		rgmii = <0>;
 	};
 
 	enet2: ethernet@e4000 {
+		rgmii = <1>;
 	};
 
 	enet3: ethernet@e6000 {
+		rgmii = <1>;
 	};
 
 	enet4: ethernet@e8000 {
+		rgmii = <0>;
 	};
 
 	enet5: ethernet@ea000 {
+		rgmii = <0>;
 	};
 
 	enet6: ethernet@f0000 {
+		rgmii = <0>;
 	};
 
 	enet7: ethernet@f2000 {
+		rgmii = <0>;
 	};
 };
-- 
2.35.1.1320.gc452695387.dirty


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

* Re: [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink
  2022-06-17 20:33 ` [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
@ 2022-06-17 22:01   ` Russell King (Oracle)
  2022-06-18  0:45     ` Sean Anderson
  0 siblings, 1 reply; 56+ messages in thread
From: Russell King (Oracle) @ 2022-06-17 22:01 UTC (permalink / raw)
  To: Sean Anderson
  Cc: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev,
	linux-kernel, linux-arm-kernel, Paolo Abeni, Eric Dumazet

Hi,

On Fri, Jun 17, 2022 at 04:33:09PM -0400, Sean Anderson wrote:
> This converts DPAA to phylink. For the moment, only MEMAC is converted.
> This should work with no device tree modifications (including those made in
> this series), except for QSGMII (as noted previously).
> 
> One area where I wasn't sure how to do things was regarding when to call
> phy_init and phy_power_on. Should that happen when selecting the PCS?

Is this a common serdes PHY that is shared amongst the various PCS? I
think from what I understand having read the other patches, it is. In
which case, initialising the PHY prior to calling phylink_start() and
powering down the PHY after phylink_stop() should be sufficient.

> Similarly, I wasn't sure where to reconfigure the thresholds in
> dpaa_eth_cgr_init. Should happen in link_up? If so, I think we will need
> some kind of callback.

Bear in mind that with 1000BASE-X, SGMII, etc, we need the link working
in order for the link to come up, so if the serdes PHY hasn't been
properly configured for the interface mode, then the link may not come
up.

How granular are these threshold configurations? Do they depend on
speed? (Note that SGMII operates at a constant speed irrespective of
the data rate due to symbol replication, so there shouldn't be a speed
component beyond that described by the interface mode, aka
phy_interface_t.)

> This has been tested on an LS1046ARDB. Without the serdes enabled,
> everything works. With the serdes enabled, everything works but eth3 (aka
> MAC6). On that interface, SGMII never completes AN for whatever reason. I
> haven't tested the counterfactual (serdes enabled but no phylink). With
> managed=phy (e.g. unspecified), I was unable to get the interfaces to come
> up at all.

I'm not sure of the level of accurate detail in the above statement,
so the following is just to cover all bases...

It's worth enabling debug in phylink so you can see what's going on -
for example, whether the "MAC" (actually PCS today) is reporting that
the link came up (via its pcs_get_state() callback.) Also whether
phylib is reporting that the PHY is saying that the link is up. That
should allow you to identify which part of the system is not

Having looked through your phylink implementation, nothing obviously
wrong stands out horribly in terms of how you're using it.

The only issue I've noticed is in dpaa_ioctl(), where you only forward
one ioctl command to phylink, whereas there are actually three ioctls
for PHY access - SIOCGMIIPHY, SIOCGMIIREG and SIOCSMIIREG. Note that
phylink (and phylib) return -EOPNOTSUPP if the ioctl is not appropriate
for them to handle. However, note that phylib will handle
SIOCSHWTSTAMP.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

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

* Re: [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-17 20:32 ` [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding Sean Anderson
@ 2022-06-17 23:27   ` Rob Herring
  2022-06-18  1:15   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 56+ messages in thread
From: Rob Herring @ 2022-06-17 23:27 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Eric Dumazet, Vinod Koul, netdev, Rob Herring, linux-kernel,
	Paolo Abeni, devicetree, linux-arm-kernel, Jakub Kicinski,
	Russell King, Kishon Vijay Abraham I, David S . Miller,
	linux-phy, Krzysztof Kozlowski, Madalin Bucur

On Fri, 17 Jun 2022 16:32:45 -0400, Sean Anderson wrote:
> This adds a binding for the SerDes module found on QorIQ processors. The
> phy reference has two cells, one for the first lane and one for the
> last. This should allow for good support of multi-lane protocols when
> (if) they are added. There is no protocol option, because the driver is
> designed to be able to completely reconfigure lanes at runtime.
> Generally, the phy consumer can select the appropriate protocol using
> set_mode. For the most part there is only one protocol controller
> (consumer) per lane/protocol combination. The exception to this is the
> B4860 processor, which has some lanes which can be connected to
> multiple MACs. For that processor, I anticipate the easiest way to
> resolve this will be to add an additional cell with a "protocol
> controller instance" property.
> 
> Each serdes has a unique set of supported protocols (and lanes). The
> support matrix is stored in the driver and is selected based on the
> compatible string. It is anticipated that a new compatible string will
> need to be added for each serdes on each SoC that drivers support is
> added for.
> 
> There are two PLLs, each of which can be used as the master clock for
> each lane. Each PLL has its own reference. For the moment they are
> required, because it simplifies the driver implementation. Absent
> reference clocks can be modeled by a fixed-clock with a rate of 0.
> 
> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
> ---
> 
>  .../bindings/phy/fsl,qoriq-serdes.yaml        | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.example.dtb: phy@1ea0000: reg: [[0, 32112640], [0, 8192]] is too long
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


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

* Re: [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink
  2022-06-17 22:01   ` Russell King (Oracle)
@ 2022-06-18  0:45     ` Sean Anderson
  2022-06-18  8:22       ` Russell King (Oracle)
  0 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-18  0:45 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev,
	linux-kernel, linux-arm-kernel, Paolo Abeni, Eric Dumazet

Hi Russell,

Thanks for the quick response.

On 6/17/22 6:01 PM, Russell King (Oracle) wrote:
> Hi,
> 
> On Fri, Jun 17, 2022 at 04:33:09PM -0400, Sean Anderson wrote:
>> This converts DPAA to phylink. For the moment, only MEMAC is converted.
>> This should work with no device tree modifications (including those made in
>> this series), except for QSGMII (as noted previously).
>>
>> One area where I wasn't sure how to do things was regarding when to call
>> phy_init and phy_power_on. Should that happen when selecting the PCS?
> 
> Is this a common serdes PHY that is shared amongst the various PCS? I
> think from what I understand having read the other patches, it is.

Each serdes has multiple lanes. There is a many-to-many relationship between
lanes and MACs. That is,

- One lane can service multiple MACs (QSGMII)
- One lane services a single MAC (SGMII, 10GBase-R, etc.)
- Multiple lanes may be used together (XAUI, HiGig, etc.) (these are not
   implemented (yet))

Each "group" of lanes corresponds to a struct phy. So in each of the above
scenarios, there would be one phy. Each PCS is a "protocol controller,"
which also corresponds to a "group" of lanes. Protocol controllers are usually
in a 1-to-many relationship with lanes (e.g. SGMIIA might be associated with
Lane A, and QSGMII A might also be associated with Lane A). The only exception
to this is the B4860 where there are some SGMII protocol controllers which can
be selected by two lanes (but not at the same time).

For Ethernet, protocol controller correspond to PCSs. Each MAC has a set of
PCSs, and an MDIO bus. Traditionally, the address for all PCSs is set to 0.
This would cause address collisions, so the serdes has to make sure to enable
only one PCS at once. It does this in pcs_set_mode.

> In which case, initialising the PHY prior to calling phylink_start() and
> powering down the PHY after phylink_stop() should be sufficient.

OK, that sounds reasonable.

>> Similarly, I wasn't sure where to reconfigure the thresholds in
>> dpaa_eth_cgr_init. Should happen in link_up? If so, I think we will need
>> some kind of callback.
> 
> Bear in mind that with 1000BASE-X, SGMII, etc, we need the link working
> in order for the link to come up, so if the serdes PHY hasn't been
> properly configured for the interface mode, then the link may not come
> up.
> 
> How granular are these threshold configurations? Do they depend on
> speed? (Note that SGMII operates at a constant speed irrespective of
> the data rate due to symbol replication, so there shouldn't be a speed
> component beyond that described by the interface mode, aka
> phy_interface_t.)

I believe these thresholds are for e.g. queue depths. So it shouldn't (TM)
matter what the depth is until the link comes up and we have to receive packets.
So I guess link up is the place? TBH I'm not terribly familiar with the QMan/BMan
half of the driver.

>> This has been tested on an LS1046ARDB. Without the serdes enabled,
>> everything works. With the serdes enabled, everything works but eth3 (aka
>> MAC6). On that interface, SGMII never completes AN for whatever reason. I
>> haven't tested the counterfactual (serdes enabled but no phylink). With
>> managed=phy (e.g. unspecified), I was unable to get the interfaces to come
>> up at all.
> 
> I'm not sure of the level of accurate detail in the above statement,
> so the following is just to cover all bases...

Just to clarify, I've tested

- Without phylink or serdes (e.g. stop at patch 21 or 24) (works)
- With phylink but no serdes (e.g. stop at patch 25) (works)
- With both phylink and serdes (e.g. everything applied) (eth3 broken)

But in this case I think it might be good to investigate e.g. patch 25 reverted.

> It's worth enabling debug in phylink so you can see what's going on -
> for example, whether the "MAC" (actually PCS today) is reporting that
> the link came up (via its pcs_get_state() callback.) Also whether
> phylib is reporting that the PHY is saying that the link is up. That
> should allow you to identify which part of the system is not

Yes, I've been using the debug prints in phylink extensively as part of
debugging :)

In this case, I added a debug statement to phylink_resolve printing out
cur_link_state, link_state.link, and pl->phy_state.link. I could see that
the phy link state was up and the mac (pcs) state was down. By inspecting
the PCS's registers, I determined that this was because AN had not completed
(in particular, the link was up in BMSR). I believe that forcing in-band-status
(by setting ovr_an_inband) shouldn't be necessary, but I was unable to get a link
up on any interface without it. In particular, the pre-phylink implementation
disabled PCS AN only for fixed links (which you can see in patch 23).

> Having looked through your phylink implementation, nothing obviously
> wrong stands out horribly in terms of how you're using it.
> 
> The only issue I've noticed is in dpaa_ioctl(), where you only forward
> one ioctl command to phylink, whereas there are actually three ioctls
> for PHY access - SIOCGMIIPHY, SIOCGMIIREG and SIOCSMIIREG. Note that
> phylink (and phylib) return -EOPNOTSUPP if the ioctl is not appropriate
> for them to handle. However, note that phylib will handle
> SIOCSHWTSTAMP.
> 

Ah, I'll make sure to fix that up.

--Sean

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

* Re: [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-17 20:32 ` [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding Sean Anderson
  2022-06-17 23:27   ` Rob Herring
@ 2022-06-18  1:15   ` Krzysztof Kozlowski
  2022-06-18  3:38     ` Sean Anderson
  1 sibling, 1 reply; 56+ messages in thread
From: Krzysztof Kozlowski @ 2022-06-18  1:15 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Kishon Vijay Abraham I, Krzysztof Kozlowski,
	Rob Herring, Vinod Koul, devicetree, linux-phy

On 17/06/2022 13:32, Sean Anderson wrote:
> This adds a binding for the SerDes module found on QorIQ processors. The
> phy reference has two cells, one for the first lane and one for the
> last. This should allow for good support of multi-lane protocols when
> (if) they are added. There is no protocol option, because the driver is
> designed to be able to completely reconfigure lanes at runtime.
> Generally, the phy consumer can select the appropriate protocol using
> set_mode. For the most part there is only one protocol controller
> (consumer) per lane/protocol combination. The exception to this is the
> B4860 processor, which has some lanes which can be connected to
> multiple MACs. For that processor, I anticipate the easiest way to
> resolve this will be to add an additional cell with a "protocol
> controller instance" property.
> 
> Each serdes has a unique set of supported protocols (and lanes). The
> support matrix is stored in the driver and is selected based on the
> compatible string. It is anticipated that a new compatible string will
> need to be added for each serdes on each SoC that drivers support is
> added for.
> 
> There are two PLLs, each of which can be used as the master clock for
> each lane. Each PLL has its own reference. For the moment they are
> required, because it simplifies the driver implementation. Absent
> reference clocks can be modeled by a fixed-clock with a rate of 0.
> 
> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
> ---
> 
>  .../bindings/phy/fsl,qoriq-serdes.yaml        | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
> 
> diff --git a/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml b/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
> new file mode 100644
> index 000000000000..4b9c1fcdab10
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
> @@ -0,0 +1,78 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/fsl,qoriq-serdes.yaml#

File name: fsl,ls1046a-serdes.yaml

> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NXP QorIQ SerDes Device Tree Bindings

s/Device Tree Bindings//

> +
> +maintainers:
> +  - Sean Anderson <sean.anderson@seco.com>
> +
> +description: |
> +  This binding describes the SerDes devices found in NXP's QorIQ line of

Describe the device, not the binding, so wording "This binding" is not
appropriate.

> +  processors. The SerDes provides up to eight lanes. Each lane may be
> +  configured individually, or may be combined with adjacent lanes for a
> +  multi-lane protocol. The SerDes supports a variety of protocols, including up
> +  to 10G Ethernet, PCIe, SATA, and others. The specific protocols supported for
> +  each lane depend on the particular SoC.
> +
> +properties:

Compatible goes first.

> +  "#phy-cells":
> +    const: 2
> +    description: |
> +      The cells contain the following arguments.
> +
> +      - description: |

Not a correct schema. What is this "- description" attached to? There is
no items here...

> +          The first lane in the group. Lanes are numbered based on the register
> +          offsets, not the I/O ports. This corresponds to the letter-based
> +          ("Lane A") naming scheme, and not the number-based ("Lane 0") naming
> +          scheme. On most SoCs, "Lane A" is "Lane 0", but not always.
> +        minimum: 0
> +        maximum: 7
> +      - description: |
> +          Last lane. For single-lane protocols, this should be the same as the
> +          first lane.
> +        minimum: 0
> +        maximum: 7
> +
> +  compatible:
> +    enum:
> +      - fsl,ls1046a-serdes-1
> +      - fsl,ls1046a-serdes-2

Does not look like proper compatible and your explanation from commit
msg did not help me. What "1" and "2" stand for? Usually compatibles
cannot have some arbitrary properties encoded.

> +
> +  clocks:
> +    minItems: 2

No need for minItems.

> +    maxItems: 2
> +    description: |
> +      Clock for each PLL reference clock input.
> +
> +  clock-names:
> +    minItems: 2
> +    maxItems: 2
> +    items:
> +      pattern: "^ref[0-1]$"

No, instead describe actual items with "const". See other examples.

> +
> +  reg:
> +    maxItems: 1
> +
> +required:
> +  - "#phy-cells"
> +  - compatible
> +  - clocks
> +  - clock-names
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    serdes1: phy@1ea0000 {
> +      #phy-cells = <2>;
> +      compatible = "fsl,ls1046a-serdes-1";
> +      reg = <0x0 0x1ea0000 0x0 0x2000>;
> +      clocks = <&clk_100mhz>, <&clk_156mhz>;
> +      clock-names = "ref0", "ref1";
> +    };
> +
> +...


Best regards,
Krzysztof

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

* Re: [PATCH net-next 02/28] dt-bindings: net: fman: Add additional interface properties
  2022-06-17 20:32 ` [PATCH net-next 02/28] dt-bindings: net: fman: Add additional interface properties Sean Anderson
@ 2022-06-18  1:16   ` Krzysztof Kozlowski
  2022-06-18 15:55     ` Sean Anderson
  0 siblings, 1 reply; 56+ messages in thread
From: Krzysztof Kozlowski @ 2022-06-18  1:16 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Krzysztof Kozlowski, Rob Herring, devicetree

On 17/06/2022 13:32, Sean Anderson wrote:
> At the moment, MEMACs are configured almost completely based on the
> phy-connection-type. That is, if the phy interface is RGMII, it assumed
> that RGMII is supported. For some interfaces, it is assumed that the
> RCW/bootloader has set up the SerDes properly. The actual link state is
> never reported.
> 
> To address these shortcomings, the driver will need additional
> information. First, it needs to know how to access the PCS/PMAs (in
> order to configure them and get the link status). The SGMII PCS/PMA is
> the only currently-described PCS/PMA. Add the XFI and QSGMII PCS/PMAs as
> well. The XFI (and 1GBase-KR) PCS/PMA is a c45 "phy" which sits on the
> same MDIO bus as SGMII PCS/PMA. By default they will have conflicting
> addresses, but they are also not enabled at the same time by default.
> Therefore, we can let the default address for the XFI PCS/PMA be the
> same as for SGMII. This will allow for backwards-compatibility.
> 
> QSGMII, however, cannot work with the current binding. This is because
> the QSGMII PCS/PMAs are only present on one MAC's MDIO bus. At the
> moment this is worked around by having every MAC write to the PCS/PMA
> addresses (without checking if they are present). This only works if
> each MAC has the same configuration, and only if we don't need to know
> the status. Because the QSGMII PCS/PMA will typically be located on a
> different MDIO bus than the MAC's SGMII PCS/PMA, there is no fallback
> for the QSGMII PCS/PMA.
> 
> MEMACs (across all SoCs) support the following protocols:
> 
> - MII
> - RGMII
> - SGMII, 1000Base-X, and 1000Base-KX
> - 2500Base-X (aka 2.5G SGMII)
> - QSGMII
> - 10GBase-R (aka XFI) and 10GBase-KR
> - XAUI and HiGig
> 
> Each line documents a set of orthogonal protocols (e.g. XAUI is
> supported if and only if HiGig is supported). Additionally,
> 
> - XAUI implies support for 10GBase-R
> - 10GBase-R is supported if and only if RGMII is not supported
> - 2500Base-X implies support for 1000Base-X
> - MII implies support for RGMII
> 
> To switch between different protocols, we must reconfigure the SerDes.
> This is done by using the standard phys property. We can also use it to
> validate whether different protocols are supported (e.g. using
> phy_validate). This will work for serial protocols, but not RGMII or
> MII. Additionally, we still need to be compatible when there is no
> SerDes.
> 
> While we can detect 10G support by examining the port speed (as set by
> fsl,fman-10g-port), we cannot determine support for any of the other
> protocols based on the existing binding. In fact, the binding works
> against us in some respects, because pcsphy-handle is required even if
> there is no possible PCS/PMA for that MAC. To allow for backwards-
> compatibility, we use a boolean-style property for RGMII (instead of
> presence/absence-style). When the property for RGMII is missing, we will
> assume that it is supported. The exception is MII, since no existing
> device trees use it (as far as I could tell).
> 
> Unfortunately, QSGMII support will be broken for old device trees. There
> is nothing we can do about this because of the PCS/PMA situation (as
> described above).
> 
> Signed-off-by: Sean Anderson <sean.anderson@seco.com>

Thanks for the patch but you add too many new properties. The file
should be converted to YAML/DT schema first.


Best regards,
Krzysztof

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

* Re: [PATCH net-next 18/28] net: fman: Map the base address once
  2022-06-17 20:33 ` [PATCH net-next 18/28] net: fman: Map the base address once Sean Anderson
@ 2022-06-18  2:01   ` kernel test robot
  0 siblings, 0 replies; 56+ messages in thread
From: kernel test robot @ 2022-06-18  2:01 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: kbuild-all, linux-kernel, linux-arm-kernel, Paolo Abeni,
	Russell King, Eric Dumazet, Sean Anderson

Hi Sean,

I love your patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Sean-Anderson/net-dpaa-Convert-to-phylink/20220618-044003
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 4875d94c69d5a4836c4225b51429d277c297aae8
config: arc-allyesconfig (https://download.01.org/0day-ci/archive/20220618/202206180959.mgYg6khw-lkp@intel.com/config)
compiler: arceb-elf-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/91ca730be8451e814e919382364039413db7e5bb
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Sean-Anderson/net-dpaa-Convert-to-phylink/20220618-044003
        git checkout 91ca730be8451e814e919382364039413db7e5bb
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=arc SHELL=/bin/bash drivers/net/ethernet/freescale/fman/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/net/ethernet/freescale/fman/mac.c: In function 'mac_exception':
   drivers/net/ethernet/freescale/fman/mac.c:48:34: warning: variable 'priv' set but not used [-Wunused-but-set-variable]
      48 |         struct mac_priv_s       *priv;
         |                                  ^~~~
   drivers/net/ethernet/freescale/fman/mac.c: In function 'mac_probe':
>> drivers/net/ethernet/freescale/fman/mac.c:387:30: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     387 |         mac_dev->vaddr_end = (void *)res->end;
         |                              ^


vim +387 drivers/net/ethernet/freescale/fman/mac.c

   297	
   298	static int mac_probe(struct platform_device *_of_dev)
   299	{
   300		int			 err, i, nph;
   301		int (*init)(struct mac_device *mac_dev, struct device_node *mac_node);
   302		struct device		*dev;
   303		struct device_node	*mac_node, *dev_node;
   304		struct mac_device	*mac_dev;
   305		struct platform_device	*of_dev;
   306		struct resource		*res;
   307		struct mac_priv_s	*priv;
   308		u32			 val;
   309		u8			fman_id;
   310		phy_interface_t          phy_if;
   311	
   312		dev = &_of_dev->dev;
   313		mac_node = dev->of_node;
   314		init = of_device_get_match_data(dev);
   315	
   316		mac_dev = devm_kzalloc(dev, sizeof(*mac_dev), GFP_KERNEL);
   317		if (!mac_dev) {
   318			err = -ENOMEM;
   319			goto _return;
   320		}
   321		priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
   322		if (!priv) {
   323			err = -ENOMEM;
   324			goto _return;
   325		}
   326	
   327		/* Save private information */
   328		mac_dev->priv = priv;
   329		mac_dev->dev = dev;
   330	
   331		INIT_LIST_HEAD(&priv->mc_addr_list);
   332	
   333		/* Get the FM node */
   334		dev_node = of_get_parent(mac_node);
   335		if (!dev_node) {
   336			dev_err(dev, "of_get_parent(%pOF) failed\n",
   337				mac_node);
   338			err = -EINVAL;
   339			goto _return_of_node_put;
   340		}
   341	
   342		of_dev = of_find_device_by_node(dev_node);
   343		if (!of_dev) {
   344			dev_err(dev, "of_find_device_by_node(%pOF) failed\n", dev_node);
   345			err = -EINVAL;
   346			goto _return_of_node_put;
   347		}
   348	
   349		/* Get the FMan cell-index */
   350		err = of_property_read_u32(dev_node, "cell-index", &val);
   351		if (err) {
   352			dev_err(dev, "failed to read cell-index for %pOF\n", dev_node);
   353			err = -EINVAL;
   354			goto _return_of_node_put;
   355		}
   356		/* cell-index 0 => FMan id 1 */
   357		fman_id = (u8)(val + 1);
   358	
   359		priv->fman = fman_bind(&of_dev->dev);
   360		if (!priv->fman) {
   361			dev_err(dev, "fman_bind(%pOF) failed\n", dev_node);
   362			err = -ENODEV;
   363			goto _return_of_node_put;
   364		}
   365	
   366		of_node_put(dev_node);
   367	
   368		/* Get the address of the memory mapped registers */
   369		res = platform_get_mem_or_io(_of_dev, 0);
   370		if (!res) {
   371			dev_err(dev, "could not get registers\n");
   372			return -EINVAL;
   373		}
   374	
   375		err = devm_request_resource(dev, fman_get_mem_region(priv->fman), res);
   376		if (err) {
   377			dev_err_probe(dev, err, "could not request resource\n");
   378			goto _return_of_node_put;
   379		}
   380	
   381		mac_dev->vaddr = devm_ioremap(dev, res->start, resource_size(res));
   382		if (!mac_dev->vaddr) {
   383			dev_err(dev, "devm_ioremap() failed\n");
   384			err = -EIO;
   385			goto _return_of_node_put;
   386		}
 > 387		mac_dev->vaddr_end = (void *)res->end;
   388	
   389		if (!of_device_is_available(mac_node)) {
   390			err = -ENODEV;
   391			goto _return_of_node_put;
   392		}
   393	
   394		/* Get the cell-index */
   395		err = of_property_read_u32(mac_node, "cell-index", &val);
   396		if (err) {
   397			dev_err(dev, "failed to read cell-index for %pOF\n", mac_node);
   398			err = -EINVAL;
   399			goto _return_of_node_put;
   400		}
   401		priv->cell_index = (u8)val;
   402	
   403		/* Get the MAC address */
   404		err = of_get_mac_address(mac_node, mac_dev->addr);
   405		if (err)
   406			dev_warn(dev, "of_get_mac_address(%pOF) failed\n", mac_node);
   407	
   408		/* Get the port handles */
   409		nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL);
   410		if (unlikely(nph < 0)) {
   411			dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n",
   412				mac_node);
   413			err = nph;
   414			goto _return_of_node_put;
   415		}
   416	
   417		if (nph != ARRAY_SIZE(mac_dev->port)) {
   418			dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n",
   419				mac_node);
   420			err = -EINVAL;
   421			goto _return_of_node_put;
   422		}
   423	
   424		for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
   425			/* Find the port node */
   426			dev_node = of_parse_phandle(mac_node, "fsl,fman-ports", i);
   427			if (!dev_node) {
   428				dev_err(dev, "of_parse_phandle(%pOF, fsl,fman-ports) failed\n",
   429					mac_node);
   430				err = -EINVAL;
   431				goto _return_of_node_put;
   432			}
   433	
   434			of_dev = of_find_device_by_node(dev_node);
   435			if (!of_dev) {
   436				dev_err(dev, "of_find_device_by_node(%pOF) failed\n",
   437					dev_node);
   438				err = -EINVAL;
   439				goto _return_of_node_put;
   440			}
   441	
   442			mac_dev->port[i] = fman_port_bind(&of_dev->dev);
   443			if (!mac_dev->port[i]) {
   444				dev_err(dev, "dev_get_drvdata(%pOF) failed\n",
   445					dev_node);
   446				err = -EINVAL;
   447				goto _return_of_node_put;
   448			}
   449			of_node_put(dev_node);
   450		}
   451	
   452		/* Get the PHY connection type */
   453		err = of_get_phy_mode(mac_node, &phy_if);
   454		if (err) {
   455			dev_warn(dev,
   456				 "of_get_phy_mode() for %pOF failed. Defaulting to SGMII\n",
   457				 mac_node);
   458			phy_if = PHY_INTERFACE_MODE_SGMII;
   459		}
   460		mac_dev->phy_if = phy_if;
   461	
   462		priv->speed		= phy2speed[mac_dev->phy_if];
   463		priv->max_speed		= priv->speed;
   464		mac_dev->if_support	= DTSEC_SUPPORTED;
   465		/* We don't support half-duplex in SGMII mode */
   466		if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII)
   467			mac_dev->if_support &= ~(SUPPORTED_10baseT_Half |
   468						SUPPORTED_100baseT_Half);
   469	
   470		/* Gigabit support (no half-duplex) */
   471		if (priv->max_speed == 1000)
   472			mac_dev->if_support |= SUPPORTED_1000baseT_Full;
   473	
   474		/* The 10G interface only supports one mode */
   475		if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII)
   476			mac_dev->if_support = SUPPORTED_10000baseT_Full;
   477	
   478		/* Get the rest of the PHY information */
   479		mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0);
   480	
   481		err = init(mac_dev, mac_node);
   482		if (err < 0) {
   483			dev_err(dev, "mac_dev->init() = %d\n", err);
   484			of_node_put(mac_dev->phy_node);
   485			goto _return_of_node_put;
   486		}
   487	
   488		/* pause frame autonegotiation enabled */
   489		mac_dev->autoneg_pause = true;
   490	
   491		/* By intializing the values to false, force FMD to enable PAUSE frames
   492		 * on RX and TX
   493		 */
   494		mac_dev->rx_pause_req = true;
   495		mac_dev->tx_pause_req = true;
   496		mac_dev->rx_pause_active = false;
   497		mac_dev->tx_pause_active = false;
   498		err = fman_set_mac_active_pause(mac_dev, true, true);
   499		if (err < 0)
   500			dev_err(dev, "fman_set_mac_active_pause() = %d\n", err);
   501	
   502		if (!is_zero_ether_addr(mac_dev->addr))
   503			dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr);
   504	
   505		priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev);
   506		if (IS_ERR(priv->eth_dev)) {
   507			dev_err(dev, "failed to add Ethernet platform device for MAC %d\n",
   508				priv->cell_index);
   509			priv->eth_dev = NULL;
   510		}
   511	
   512		goto _return;
   513	
   514	_return_of_node_put:
   515		of_node_put(dev_node);
   516	_return:
   517		return err;
   518	}
   519	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

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

* Re: [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver
  2022-06-17 20:32 ` [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver Sean Anderson
@ 2022-06-18  3:02   ` kernel test robot
       [not found]   ` <GV1PR04MB905598703F5E9A0989662EFDE0AE9@GV1PR04MB9055.eurprd04.prod.outlook.com>
  1 sibling, 0 replies; 56+ messages in thread
From: kernel test robot @ 2022-06-18  3:02 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: kbuild-all, linux-kernel, linux-arm-kernel, Paolo Abeni,
	Russell King, Eric Dumazet, Sean Anderson, Ioana Ciornei,
	Jonathan Corbet, Kishon Vijay Abraham I, Krzysztof Kozlowski,
	Rob Herring, Vinod Koul, devicetree, linux-phy

Hi Sean,

I love your patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Sean-Anderson/net-dpaa-Convert-to-phylink/20220618-044003
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 4875d94c69d5a4836c4225b51429d277c297aae8
config: sh-allmodconfig (https://download.01.org/0day-ci/archive/20220618/202206181015.BLEIZObf-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/d9c7b1e909ace0c4229445647587ae1f64cf52c0
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Sean-Anderson/net-dpaa-Convert-to-phylink/20220618-044003
        git checkout d9c7b1e909ace0c4229445647587ae1f64cf52c0
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=sh SHELL=/bin/bash drivers/net/ethernet/freescale/fman/ drivers/phy/freescale/ net/ipv6/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/phy/freescale/phy-qoriq.c:382:16: warning: no previous prototype for 'qs_clk_hw_to_priv' [-Wmissing-prototypes]
     382 | struct qs_clk *qs_clk_hw_to_priv(struct clk_hw *hw)
         |                ^~~~~~~~~~~~~~~~~


vim +/qs_clk_hw_to_priv +382 drivers/phy/freescale/phy-qoriq.c

   381	
 > 382	struct qs_clk *qs_clk_hw_to_priv(struct clk_hw *hw)
   383	{
   384		return container_of(hw, struct qs_clk, hw);
   385	}
   386	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

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

* Re: [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-18  1:15   ` Krzysztof Kozlowski
@ 2022-06-18  3:38     ` Sean Anderson
  2022-06-19 11:24       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-18  3:38 UTC (permalink / raw)
  To: Krzysztof Kozlowski, David S . Miller, Jakub Kicinski,
	Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Kishon Vijay Abraham I, Krzysztof Kozlowski,
	Rob Herring, Vinod Koul, devicetree, linux-phy

Hi Krzysztof,

On 6/17/22 9:15 PM, Krzysztof Kozlowski wrote:
> On 17/06/2022 13:32, Sean Anderson wrote:
>> This adds a binding for the SerDes module found on QorIQ processors. The
>> phy reference has two cells, one for the first lane and one for the
>> last. This should allow for good support of multi-lane protocols when
>> (if) they are added. There is no protocol option, because the driver is
>> designed to be able to completely reconfigure lanes at runtime.
>> Generally, the phy consumer can select the appropriate protocol using
>> set_mode. For the most part there is only one protocol controller
>> (consumer) per lane/protocol combination. The exception to this is the
>> B4860 processor, which has some lanes which can be connected to
>> multiple MACs. For that processor, I anticipate the easiest way to
>> resolve this will be to add an additional cell with a "protocol
>> controller instance" property.
>>
>> Each serdes has a unique set of supported protocols (and lanes). The
>> support matrix is stored in the driver and is selected based on the
>> compatible string. It is anticipated that a new compatible string will
>> need to be added for each serdes on each SoC that drivers support is
>> added for.
>>
>> There are two PLLs, each of which can be used as the master clock for
>> each lane. Each PLL has its own reference. For the moment they are
>> required, because it simplifies the driver implementation. Absent
>> reference clocks can be modeled by a fixed-clock with a rate of 0.
>>
>> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
>> ---
>>
>>   .../bindings/phy/fsl,qoriq-serdes.yaml        | 78 +++++++++++++++++++
>>   1 file changed, 78 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml b/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
>> new file mode 100644
>> index 000000000000..4b9c1fcdab10
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
>> @@ -0,0 +1,78 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/phy/fsl,qoriq-serdes.yaml#
> 
> File name: fsl,ls1046a-serdes.yaml

This is not appropriate, since this binding will be used for many QorIQ
devices, not just LS1046A. The LS1046A is not even an "ur" device (first
model, etc.) but simply the one I have access to.

>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: NXP QorIQ SerDes Device Tree Bindings
> 
> s/Device Tree Bindings//

OK

>> +
>> +maintainers:
>> +  - Sean Anderson <sean.anderson@seco.com>
>> +
>> +description: |
>> +  This binding describes the SerDes devices found in NXP's QorIQ line of
> 
> Describe the device, not the binding, so wording "This binding" is not
> appropriate.

OK

>> +  processors. The SerDes provides up to eight lanes. Each lane may be
>> +  configured individually, or may be combined with adjacent lanes for a
>> +  multi-lane protocol. The SerDes supports a variety of protocols, including up
>> +  to 10G Ethernet, PCIe, SATA, and others. The specific protocols supported for
>> +  each lane depend on the particular SoC.
>> +
>> +properties:
> 
> Compatible goes first.
> 
>> +  "#phy-cells":
>> +    const: 2
>> +    description: |
>> +      The cells contain the following arguments.
>> +
>> +      - description: |
> 
> Not a correct schema. What is this "- description" attached to? There is
> no items here...

This is the same format as used by
Documentation/devicetree/bindings/phy/xlnx,zynqmp-psgtr.yaml

How should the cells be documented?

>> +          The first lane in the group. Lanes are numbered based on the register
>> +          offsets, not the I/O ports. This corresponds to the letter-based
>> +          ("Lane A") naming scheme, and not the number-based ("Lane 0") naming
>> +          scheme. On most SoCs, "Lane A" is "Lane 0", but not always.
>> +        minimum: 0
>> +        maximum: 7
>> +      - description: |
>> +          Last lane. For single-lane protocols, this should be the same as the
>> +          first lane.
>> +        minimum: 0
>> +        maximum: 7
>> +
>> +  compatible:
>> +    enum:
>> +      - fsl,ls1046a-serdes-1
>> +      - fsl,ls1046a-serdes-2
> 
> Does not look like proper compatible and your explanation from commit
> msg did not help me. What "1" and "2" stand for? Usually compatibles
> cannot have some arbitrary properties encoded.

Each serdes has a different set of supported protocols for each lane. This is encoded
in the driver data associated with the compatible, along with the appropriate values
to plug into the protocol control registers. Because each serdes has a different set
of supported protocols and register configuration, adding support for a new SoC will
require adding the appropriate configuration to the driver, and adding a new compatible
string. Although most of the driver is generic, this critical portion is shared only
between closely-related SoCs (such as variants with differing numbers of cores).

The 1 and 2 stand for the number of the SerDes on that SoC. e.g. the documentation will
refer to SerDes1 and SerDes2.
  
So e.g. other compatibles might be

- fsl,ls1043a-serdes-1 # There's only one serdes on this SoC
- fsl,t4042-serdes-1 # This SoC has four serdes
- fsl,t4042-serdes-2
- fsl,t4042-serdes-3
- fsl,t4042-serdes-4

>> +
>> +  clocks:
>> +    minItems: 2
> 
> No need for minItems.

OK

>> +    maxItems: 2
>> +    description: |
>> +      Clock for each PLL reference clock input.
>> +
>> +  clock-names:
>> +    minItems: 2
>> +    maxItems: 2
>> +    items:
>> +      pattern: "^ref[0-1]$"
> 
> No, instead describe actual items with "const". See other examples.

Again, same format as xlnx,zynqmp-psgtr.yaml

I will update this to use items.

>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +required:
>> +  - "#phy-cells"
>> +  - compatible
>> +  - clocks
>> +  - clock-names
>> +  - reg
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +    serdes1: phy@1ea0000 {
>> +      #phy-cells = <2>;
>> +      compatible = "fsl,ls1046a-serdes-1";
>> +      reg = <0x0 0x1ea0000 0x0 0x2000>;
>> +      clocks = <&clk_100mhz>, <&clk_156mhz>;
>> +      clock-names = "ref0", "ref1";
>> +    };
>> +
>> +...

--Sean


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

* Re: [PATCH net-next 10/28] net: fman: Move struct dev to mac_device
  2022-06-17 20:32 ` [PATCH net-next 10/28] net: fman: Move struct dev to mac_device Sean Anderson
@ 2022-06-18  3:57   ` kernel test robot
  0 siblings, 0 replies; 56+ messages in thread
From: kernel test robot @ 2022-06-18  3:57 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: kbuild-all, linux-kernel, linux-arm-kernel, Paolo Abeni,
	Russell King, Eric Dumazet, Sean Anderson

Hi Sean,

I love your patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Sean-Anderson/net-dpaa-Convert-to-phylink/20220618-044003
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 4875d94c69d5a4836c4225b51429d277c297aae8
config: m68k-randconfig-r036-20220617 (https://download.01.org/0day-ci/archive/20220618/202206181156.p7gQheg2-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/155c8f9a09b3f95f4804d306c2465ebc82fe608f
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Sean-Anderson/net-dpaa-Convert-to-phylink/20220618-044003
        git checkout 155c8f9a09b3f95f4804d306c2465ebc82fe608f
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash drivers/net/ethernet/freescale/fman/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/net/ethernet/freescale/fman/mac.c: In function 'mac_exception':
>> drivers/net/ethernet/freescale/fman/mac.c:50:34: warning: variable 'priv' set but not used [-Wunused-but-set-variable]
      50 |         struct mac_priv_s       *priv;
         |                                  ^~~~
   drivers/net/ethernet/freescale/fman/mac.c: In function 'tgec_initialization':
   drivers/net/ethernet/freescale/fman/mac.c:271:34: warning: variable 'priv' set but not used [-Wunused-but-set-variable]
     271 |         struct mac_priv_s       *priv;
         |                                  ^~~~
   drivers/net/ethernet/freescale/fman/mac.c: In function 'dtsec_initialization':
   drivers/net/ethernet/freescale/fman/mac.c:333:34: warning: variable 'priv' set but not used [-Wunused-but-set-variable]
     333 |         struct mac_priv_s       *priv;
         |                                  ^~~~


vim +/priv +50 drivers/net/ethernet/freescale/fman/mac.c

3933961682a30a Igal Liberman 2015-12-21  46  
3933961682a30a Igal Liberman 2015-12-21  47  static void mac_exception(void *handle, enum fman_mac_exceptions ex)
3933961682a30a Igal Liberman 2015-12-21  48  {
3933961682a30a Igal Liberman 2015-12-21  49  	struct mac_device	*mac_dev;
3933961682a30a Igal Liberman 2015-12-21 @50  	struct mac_priv_s	*priv;
3933961682a30a Igal Liberman 2015-12-21  51  
3933961682a30a Igal Liberman 2015-12-21  52  	mac_dev = handle;
3933961682a30a Igal Liberman 2015-12-21  53  	priv = mac_dev->priv;
3933961682a30a Igal Liberman 2015-12-21  54  
3933961682a30a Igal Liberman 2015-12-21  55  	if (ex == FM_MAC_EX_10G_RX_FIFO_OVFL) {
3933961682a30a Igal Liberman 2015-12-21  56  		/* don't flag RX FIFO after the first */
3933961682a30a Igal Liberman 2015-12-21  57  		mac_dev->set_exception(mac_dev->fman_mac,
3933961682a30a Igal Liberman 2015-12-21  58  				       FM_MAC_EX_10G_RX_FIFO_OVFL, false);
155c8f9a09b3f9 Sean Anderson 2022-06-17  59  		dev_err(mac_dev->dev, "10G MAC got RX FIFO Error = %x\n", ex);
3933961682a30a Igal Liberman 2015-12-21  60  	}
3933961682a30a Igal Liberman 2015-12-21  61  
155c8f9a09b3f9 Sean Anderson 2022-06-17  62  	dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c",
3933961682a30a Igal Liberman 2015-12-21  63  		__func__, ex);
3933961682a30a Igal Liberman 2015-12-21  64  }
3933961682a30a Igal Liberman 2015-12-21  65  

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

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

* Re: [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink
  2022-06-18  0:45     ` Sean Anderson
@ 2022-06-18  8:22       ` Russell King (Oracle)
  2022-06-18 15:58         ` Sean Anderson
  0 siblings, 1 reply; 56+ messages in thread
From: Russell King (Oracle) @ 2022-06-18  8:22 UTC (permalink / raw)
  To: Sean Anderson
  Cc: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev,
	linux-kernel, linux-arm-kernel, Paolo Abeni, Eric Dumazet

On Fri, Jun 17, 2022 at 08:45:38PM -0400, Sean Anderson wrote:
> Hi Russell,
> 
> Thanks for the quick response.
>...
> Yes, I've been using the debug prints in phylink extensively as part of
> debugging :)
> 
> In this case, I added a debug statement to phylink_resolve printing out
> cur_link_state, link_state.link, and pl->phy_state.link. I could see that
> the phy link state was up and the mac (pcs) state was down. By inspecting
> the PCS's registers, I determined that this was because AN had not completed
> (in particular, the link was up in BMSR). I believe that forcing in-band-status
> (by setting ovr_an_inband) shouldn't be necessary, but I was unable to get a link
> up on any interface without it. In particular, the pre-phylink implementation
> disabled PCS AN only for fixed links (which you can see in patch 23).

I notice that prior to patch 23, the advertisment register was set to
0x4001, but in phylink_mii_c22_pcs_encode_advertisement() we set it to
0x0001 (bit 14 being the acknowledge bit from the PCS to the PHY, which
is normally managed by hardware.

It may be worth testing whether setting bit 14 changes the behaviour.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

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

* Re: [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver
       [not found]   ` <GV1PR04MB905598703F5E9A0989662EFDE0AE9@GV1PR04MB9055.eurprd04.prod.outlook.com>
@ 2022-06-18 12:39     ` Ioana Ciornei
  2022-06-18 15:52       ` Sean Anderson
  0 siblings, 1 reply; 56+ messages in thread
From: Ioana Ciornei @ 2022-06-18 12:39 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Jonathan Corbet, Kishon Vijay Abraham I,
	Krzysztof Kozlowski, Rob Herring, Vinod Koul, devicetree,
	linux-phy

> > Subject: [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver
> >

Sorry for the previous HTML formatted email...

> 
> Hi Sean,
> 
> I am very much interested in giving this driver a go on other SoCs as well
> but at the moment I am in vacation until mid next week.
> 
> 
> > This adds support for the "SerDes" devices found on various NXP QorIQ SoCs.
> > There may be up to four SerDes devices on each SoC, each supporting up to
> > eight lanes. Protocol support for each SerDes is highly heterogeneous, with
> > each SoC typically having a totally different selection of supported
> > protocols for each lane. Additionally, the SerDes devices on each SoC also
> > have differing support. One SerDes will typically support Ethernet on most
> > lanes, while the other will typically support PCIe on most lanes.
> >
> > There is wide hardware support for this SerDes. I have not done extensive
> > digging, but it seems to be used on almost every QorIQ device, including
> > the AMP and Layerscape series. Because each SoC typically has specific
> > instructions and exceptions for its SerDes, I have limited the initial
> > scope of this module to just the LS1046A. Additionally, I have only added
> > support for Ethernet protocols. There is not a great need for dynamic
> > reconfiguration for other protocols (SATA and PCIe handle rate changes in
> > hardware), so support for them may never be added.>
> > Nevertheless, I have tried to provide an obvious path for adding support
> > for other SoCs as well as other protocols. SATA just needs support for
> > configuring LNmSSCR0. PCIe may need to configure the equalization
> > registers. It also uses multiple lanes. I have tried to write the driver
> > with multi-lane support in mind, so there should not need to be any large
> > changes. Although there are 6 protocols supported, I have only tested SGMII
> > and XFI. The rest have been implemented as described in the datasheet.
> >
> > The PLLs are modeled as clocks proper. This lets us take advantage of the
> > existing clock infrastructure. I have not given the same treatment to the
> > lane "clocks" (dividers) because they need to be programmed in-concert with
> > the rest of the lane settings. One tricky thing is that the VCO (pll) rate
> > exceeds 2^32 (maxing out at around 5GHz). This will be a problem on 32-bit
> > platforms, since clock rates are stored as unsigned longs. To work around
> > this, the pll clock rate is generally treated in units of kHz.>
> > The PLLs are configured rather interestingly. Instead of the usual direct
> > programming of the appropriate divisors, the input and output clock rates
> > are selected directly. Generally, the only restriction is that the input
> > and output must be integer multiples of each other. This suggests some kind
> > of internal look-up table. The datasheets generally list out the supported
> > combinations explicitly, and not all input/output combinations are
> > documented. I'm not sure if this is due to lack of support, or due to an
> > oversight. If this becomes an issue, then some combinations can be
> > blacklisted (or whitelisted). This may also be necessary for other SoCs
> > which have more stringent clock requirements.
> 
> 
> I didn't get a change to go through the driver like I would like, but are you
> changing the PLL's rate at runtime?
> Do you take into consideration that a PLL might still be used by a PCIe or SATA
> lane (which is not described in the DTS) and deny its rate reconfiguration
> if this happens?
> 
> I am asking this because when I added support for the Lynx 28G SerDes block what
> I did in order to support rate change depending of the plugged SFP module was
> just to change the PLL used by the lane, not the PLL rate itself.
> This is because I was afraid of causing more harm then needed for all the
> non-Ethernet lanes.
> 
> >
> > The general API call list for this PHY is documented under the driver-api
> > docs. I think this is rather standard, except that most driverts configure
> > the mode (protocol) at xlate-time. Unlike some other phys where e.g. PCIe
> > x4 will use 4 separate phys all configured for PCIe, this driver uses one
> > phy configured to use 4 lanes. This is because while the individual lanes
> > may be configured individually, the protocol selection acts on all lanes at
> > once. Additionally, the order which lanes should be configured in is
> > specified by the datasheet.  To coordinate this, lanes are reserved in
> > phy_init, and released in phy_exit.
> >
> > When getting a phy, if a phy already exists for those lanes, it is reused.
> > This is to make things like QSGMII work. Four MACs will all want to ensure
> > that the lane is configured properly, and we need to ensure they can all
> > call phy_init, etc. There is refcounting for phy_init and phy_power_on, so
> > the phy will only be powered on once. However, there is no refcounting for
> > phy_set_mode. A "rogue" MAC could set the mode to something non-QSGMII and
> > break the other MACs. Perhaps there is an opportunity for future
> > enhancement here.
> >
> > This driver was written with reference to the LS1046A reference manual.
> > However, it was informed by reference manuals for all processors with
> > MEMACs, especially the T4240 (which appears to have a "maxed-out"
> > configuration).
> >
> > Signed-off-by: Sean Anderson <sean.anderson@seco.com>
> > ---
> > This appears to be the same underlying hardware as the Lynx 28G phy
> > added in 8f73b37cf3fb ("phy: add support for the Layerscape SerDes
> > 28G"). 
> 
> The SerDes block used on L1046A (and a lot of other SoCs) is not the same
> one as the Lynx 28G that I submitted. The Lynx 28G block is only included
> on the LX2160A SoC and its variants.
> 
> The SerDes block that you are adding a driver for is the Lynx 10G SerDes,
> which is why I would suggest renaming it to phy-fsl-lynx-10g.c.
> 
> Ioana

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

* Re: [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver
  2022-06-18 12:39     ` Ioana Ciornei
@ 2022-06-18 15:52       ` Sean Anderson
  2022-06-20 18:53         ` Sean Anderson
  0 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-18 15:52 UTC (permalink / raw)
  To: Ioana Ciornei, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Jonathan Corbet, Kishon Vijay Abraham I,
	Krzysztof Kozlowski, Rob Herring, Vinod Koul, devicetree,
	linux-phy

Hi Ioana,

On 6/18/22 8:39 AM, Ioana Ciornei wrote:
>>> Subject: [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver
>>>
> 
> Sorry for the previous HTML formatted email...
> 
>>
>> Hi Sean,
>>
>> I am very much interested in giving this driver a go on other SoCs as well
>> but at the moment I am in vacation until mid next week.

Please let me know your results. I have documented how to add support for
additional SoCs, so hopefully it should be fairly straightforward.

>>> This adds support for the "SerDes" devices found on various NXP QorIQ SoCs.
>>> There may be up to four SerDes devices on each SoC, each supporting up to
>>> eight lanes. Protocol support for each SerDes is highly heterogeneous, with
>>> each SoC typically having a totally different selection of supported
>>> protocols for each lane. Additionally, the SerDes devices on each SoC also
>>> have differing support. One SerDes will typically support Ethernet on most
>>> lanes, while the other will typically support PCIe on most lanes.
>>>
>>> There is wide hardware support for this SerDes. I have not done extensive
>>> digging, but it seems to be used on almost every QorIQ device, including
>>> the AMP and Layerscape series. Because each SoC typically has specific
>>> instructions and exceptions for its SerDes, I have limited the initial
>>> scope of this module to just the LS1046A. Additionally, I have only added
>>> support for Ethernet protocols. There is not a great need for dynamic
>>> reconfiguration for other protocols (SATA and PCIe handle rate changes in
>>> hardware), so support for them may never be added.>
>>> Nevertheless, I have tried to provide an obvious path for adding support
>>> for other SoCs as well as other protocols. SATA just needs support for
>>> configuring LNmSSCR0. PCIe may need to configure the equalization
>>> registers. It also uses multiple lanes. I have tried to write the driver
>>> with multi-lane support in mind, so there should not need to be any large
>>> changes. Although there are 6 protocols supported, I have only tested SGMII
>>> and XFI. The rest have been implemented as described in the datasheet.
>>>
>>> The PLLs are modeled as clocks proper. This lets us take advantage of the
>>> existing clock infrastructure. I have not given the same treatment to the
>>> lane "clocks" (dividers) because they need to be programmed in-concert with
>>> the rest of the lane settings. One tricky thing is that the VCO (pll) rate
>>> exceeds 2^32 (maxing out at around 5GHz). This will be a problem on 32-bit
>>> platforms, since clock rates are stored as unsigned longs. To work around
>>> this, the pll clock rate is generally treated in units of kHz.>
>>> The PLLs are configured rather interestingly. Instead of the usual direct
>>> programming of the appropriate divisors, the input and output clock rates
>>> are selected directly. Generally, the only restriction is that the input
>>> and output must be integer multiples of each other. This suggests some kind
>>> of internal look-up table. The datasheets generally list out the supported
>>> combinations explicitly, and not all input/output combinations are
>>> documented. I'm not sure if this is due to lack of support, or due to an
>>> oversight. If this becomes an issue, then some combinations can be
>>> blacklisted (or whitelisted). This may also be necessary for other SoCs
>>> which have more stringent clock requirements.
>>
>>
>> I didn't get a change to go through the driver like I would like, but are you
>> changing the PLL's rate at runtime?

Yes.

>> Do you take into consideration that a PLL might still be used by a PCIe or SATA
>> lane (which is not described in the DTS) and deny its rate reconfiguration
>> if this happens?

Yes.

When the device is probed, we go through the PCCRs and reserve any lane which is in
use for a protocol we don't support (PCIe, SATA). We also get both PLL's rates
exclusively and mark them as enabled.

>> I am asking this because when I added support for the Lynx 28G SerDes block what
>> I did in order to support rate change depending of the plugged SFP module was
>> just to change the PLL used by the lane, not the PLL rate itself.
>> This is because I was afraid of causing more harm then needed for all the
>> non-Ethernet lanes.

Yes. Since There is not much need for dynamic reconfiguration for other protocols,
I suspect that non-ethernet support will not be added soon (or perhaps ever).

>>>
>>> The general API call list for this PHY is documented under the driver-api
>>> docs. I think this is rather standard, except that most driverts configure
>>> the mode (protocol) at xlate-time. Unlike some other phys where e.g. PCIe
>>> x4 will use 4 separate phys all configured for PCIe, this driver uses one
>>> phy configured to use 4 lanes. This is because while the individual lanes
>>> may be configured individually, the protocol selection acts on all lanes at
>>> once. Additionally, the order which lanes should be configured in is
>>> specified by the datasheet.  To coordinate this, lanes are reserved in
>>> phy_init, and released in phy_exit.
>>>
>>> When getting a phy, if a phy already exists for those lanes, it is reused.
>>> This is to make things like QSGMII work. Four MACs will all want to ensure
>>> that the lane is configured properly, and we need to ensure they can all
>>> call phy_init, etc. There is refcounting for phy_init and phy_power_on, so
>>> the phy will only be powered on once. However, there is no refcounting for
>>> phy_set_mode. A "rogue" MAC could set the mode to something non-QSGMII and
>>> break the other MACs. Perhaps there is an opportunity for future
>>> enhancement here.
>>>
>>> This driver was written with reference to the LS1046A reference manual.
>>> However, it was informed by reference manuals for all processors with
>>> MEMACs, especially the T4240 (which appears to have a "maxed-out"
>>> configuration).
>>>
>>> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
>>> ---
>>> This appears to be the same underlying hardware as the Lynx 28G phy
>>> added in 8f73b37cf3fb ("phy: add support for the Layerscape SerDes
>>> 28G").
>>
>> The SerDes block used on L1046A (and a lot of other SoCs) is not the same
>> one as the Lynx 28G that I submitted. The Lynx 28G block is only included
>> on the LX2160A SoC and its variants.

OK. I looked over it quickly and it seemed to share many of the same registers.

>> The SerDes block that you are adding a driver for is the Lynx 10G SerDes,
>> which is why I would suggest renaming it to phy-fsl-lynx-10g.c.

Ah, thanks. Is this documented anywhere?

--Sean


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

* Re: [PATCH net-next 02/28] dt-bindings: net: fman: Add additional interface properties
  2022-06-18  1:16   ` Krzysztof Kozlowski
@ 2022-06-18 15:55     ` Sean Anderson
  2022-06-19 10:33       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-18 15:55 UTC (permalink / raw)
  To: Krzysztof Kozlowski, David S . Miller, Jakub Kicinski,
	Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Krzysztof Kozlowski, Rob Herring, devicetree

Hi Krzysztof,

On 6/17/22 9:16 PM, Krzysztof Kozlowski wrote:
> On 17/06/2022 13:32, Sean Anderson wrote:
>> At the moment, MEMACs are configured almost completely based on the
>> phy-connection-type. That is, if the phy interface is RGMII, it assumed
>> that RGMII is supported. For some interfaces, it is assumed that the
>> RCW/bootloader has set up the SerDes properly. The actual link state is
>> never reported.
>>
>> To address these shortcomings, the driver will need additional
>> information. First, it needs to know how to access the PCS/PMAs (in
>> order to configure them and get the link status). The SGMII PCS/PMA is
>> the only currently-described PCS/PMA. Add the XFI and QSGMII PCS/PMAs as
>> well. The XFI (and 1GBase-KR) PCS/PMA is a c45 "phy" which sits on the
>> same MDIO bus as SGMII PCS/PMA. By default they will have conflicting
>> addresses, but they are also not enabled at the same time by default.
>> Therefore, we can let the default address for the XFI PCS/PMA be the
>> same as for SGMII. This will allow for backwards-compatibility.
>>
>> QSGMII, however, cannot work with the current binding. This is because
>> the QSGMII PCS/PMAs are only present on one MAC's MDIO bus. At the
>> moment this is worked around by having every MAC write to the PCS/PMA
>> addresses (without checking if they are present). This only works if
>> each MAC has the same configuration, and only if we don't need to know
>> the status. Because the QSGMII PCS/PMA will typically be located on a
>> different MDIO bus than the MAC's SGMII PCS/PMA, there is no fallback
>> for the QSGMII PCS/PMA.
>>
>> MEMACs (across all SoCs) support the following protocols:
>>
>> - MII
>> - RGMII
>> - SGMII, 1000Base-X, and 1000Base-KX
>> - 2500Base-X (aka 2.5G SGMII)
>> - QSGMII
>> - 10GBase-R (aka XFI) and 10GBase-KR
>> - XAUI and HiGig
>>
>> Each line documents a set of orthogonal protocols (e.g. XAUI is
>> supported if and only if HiGig is supported). Additionally,
>>
>> - XAUI implies support for 10GBase-R
>> - 10GBase-R is supported if and only if RGMII is not supported
>> - 2500Base-X implies support for 1000Base-X
>> - MII implies support for RGMII
>>
>> To switch between different protocols, we must reconfigure the SerDes.
>> This is done by using the standard phys property. We can also use it to
>> validate whether different protocols are supported (e.g. using
>> phy_validate). This will work for serial protocols, but not RGMII or
>> MII. Additionally, we still need to be compatible when there is no
>> SerDes.
>>
>> While we can detect 10G support by examining the port speed (as set by
>> fsl,fman-10g-port), we cannot determine support for any of the other
>> protocols based on the existing binding. In fact, the binding works
>> against us in some respects, because pcsphy-handle is required even if
>> there is no possible PCS/PMA for that MAC. To allow for backwards-
>> compatibility, we use a boolean-style property for RGMII (instead of
>> presence/absence-style). When the property for RGMII is missing, we will
>> assume that it is supported. The exception is MII, since no existing
>> device trees use it (as far as I could tell).
>>
>> Unfortunately, QSGMII support will be broken for old device trees. There
>> is nothing we can do about this because of the PCS/PMA situation (as
>> described above).
>>
>> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
> 
> Thanks for the patch but you add too many new properties. The file
> should be converted to YAML/DT schema first.

Perhaps. However, conversion to yaml is a non-trivial task, especially for
a complicated binding such as this one. I am more than happy to rework this
patch to be based on a yaml conversion, but I do not have the bandwidth to
do so myself.

If you have any comments on the binding changes themselves, that would be
much appreciated.

--Sean

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

* Re: [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink
  2022-06-18  8:22       ` Russell King (Oracle)
@ 2022-06-18 15:58         ` Sean Anderson
  2022-06-23 22:39           ` Sean Anderson
  0 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-18 15:58 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev,
	linux-kernel, linux-arm-kernel, Paolo Abeni, Eric Dumazet

Hi Russell,

On 6/18/22 4:22 AM, Russell King (Oracle) wrote:
> On Fri, Jun 17, 2022 at 08:45:38PM -0400, Sean Anderson wrote:
>> Hi Russell,
>>
>> Thanks for the quick response.
>> ...
>> Yes, I've been using the debug prints in phylink extensively as part of
>> debugging :)
>>
>> In this case, I added a debug statement to phylink_resolve printing out
>> cur_link_state, link_state.link, and pl->phy_state.link. I could see that
>> the phy link state was up and the mac (pcs) state was down. By inspecting
>> the PCS's registers, I determined that this was because AN had not completed
>> (in particular, the link was up in BMSR). I believe that forcing in-band-status
>> (by setting ovr_an_inband) shouldn't be necessary, but I was unable to get a link
>> up on any interface without it. In particular, the pre-phylink implementation
>> disabled PCS AN only for fixed links (which you can see in patch 23).
> 
> I notice that prior to patch 23, the advertisment register was set to
> 0x4001, but in phylink_mii_c22_pcs_encode_advertisement() we set it to
> 0x0001 (bit 14 being the acknowledge bit from the PCS to the PHY, which
> is normally managed by hardware.
> 
> It may be worth testing whether setting bit 14 changes the behaviour.

Thanks for the tip. I'll try that out on Monday.

--Sean

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

* Re: [PATCH net-next 02/28] dt-bindings: net: fman: Add additional interface properties
  2022-06-18 15:55     ` Sean Anderson
@ 2022-06-19 10:33       ` Krzysztof Kozlowski
  2022-06-27 23:05         ` Rob Herring
  0 siblings, 1 reply; 56+ messages in thread
From: Krzysztof Kozlowski @ 2022-06-19 10:33 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Krzysztof Kozlowski, Rob Herring, devicetree

On 18/06/2022 17:55, Sean Anderson wrote:
> Hi Krzysztof,
> 
> On 6/17/22 9:16 PM, Krzysztof Kozlowski wrote:
>> On 17/06/2022 13:32, Sean Anderson wrote:
>>> At the moment, MEMACs are configured almost completely based on the
>>> phy-connection-type. That is, if the phy interface is RGMII, it assumed
>>> that RGMII is supported. For some interfaces, it is assumed that the
>>> RCW/bootloader has set up the SerDes properly. The actual link state is
>>> never reported.
>>>
>>> To address these shortcomings, the driver will need additional
>>> information. First, it needs to know how to access the PCS/PMAs (in
>>> order to configure them and get the link status). The SGMII PCS/PMA is
>>> the only currently-described PCS/PMA. Add the XFI and QSGMII PCS/PMAs as
>>> well. The XFI (and 1GBase-KR) PCS/PMA is a c45 "phy" which sits on the
>>> same MDIO bus as SGMII PCS/PMA. By default they will have conflicting
>>> addresses, but they are also not enabled at the same time by default.
>>> Therefore, we can let the default address for the XFI PCS/PMA be the
>>> same as for SGMII. This will allow for backwards-compatibility.
>>>
>>> QSGMII, however, cannot work with the current binding. This is because
>>> the QSGMII PCS/PMAs are only present on one MAC's MDIO bus. At the
>>> moment this is worked around by having every MAC write to the PCS/PMA
>>> addresses (without checking if they are present). This only works if
>>> each MAC has the same configuration, and only if we don't need to know
>>> the status. Because the QSGMII PCS/PMA will typically be located on a
>>> different MDIO bus than the MAC's SGMII PCS/PMA, there is no fallback
>>> for the QSGMII PCS/PMA.
>>>
>>> MEMACs (across all SoCs) support the following protocols:
>>>
>>> - MII
>>> - RGMII
>>> - SGMII, 1000Base-X, and 1000Base-KX
>>> - 2500Base-X (aka 2.5G SGMII)
>>> - QSGMII
>>> - 10GBase-R (aka XFI) and 10GBase-KR
>>> - XAUI and HiGig
>>>
>>> Each line documents a set of orthogonal protocols (e.g. XAUI is
>>> supported if and only if HiGig is supported). Additionally,
>>>
>>> - XAUI implies support for 10GBase-R
>>> - 10GBase-R is supported if and only if RGMII is not supported
>>> - 2500Base-X implies support for 1000Base-X
>>> - MII implies support for RGMII
>>>
>>> To switch between different protocols, we must reconfigure the SerDes.
>>> This is done by using the standard phys property. We can also use it to
>>> validate whether different protocols are supported (e.g. using
>>> phy_validate). This will work for serial protocols, but not RGMII or
>>> MII. Additionally, we still need to be compatible when there is no
>>> SerDes.
>>>
>>> While we can detect 10G support by examining the port speed (as set by
>>> fsl,fman-10g-port), we cannot determine support for any of the other
>>> protocols based on the existing binding. In fact, the binding works
>>> against us in some respects, because pcsphy-handle is required even if
>>> there is no possible PCS/PMA for that MAC. To allow for backwards-
>>> compatibility, we use a boolean-style property for RGMII (instead of
>>> presence/absence-style). When the property for RGMII is missing, we will
>>> assume that it is supported. The exception is MII, since no existing
>>> device trees use it (as far as I could tell).
>>>
>>> Unfortunately, QSGMII support will be broken for old device trees. There
>>> is nothing we can do about this because of the PCS/PMA situation (as
>>> described above).
>>>
>>> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
>>
>> Thanks for the patch but you add too many new properties. The file
>> should be converted to YAML/DT schema first.
> 
> Perhaps. However, conversion to yaml is a non-trivial task, especially for
> a complicated binding such as this one. I am more than happy to rework this
> patch to be based on a yaml conversion, but I do not have the bandwidth to
> do so myself.

I understand. Although since 2020  - since when we expect the bindings
to be in YAML - this file grew by 6 properties, because each person
extends it instead of converting. Each person uses the same excuse...

You add here 5 more, so it would be 11 new properties in total.

> 
> If you have any comments on the binding changes themselves, that would be
> much appreciated.

Maybe Rob will ack it, but for me the change is too big to be accepted
in TXT, so no from me.

Best regards,
Krzysztof

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

* Re: [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-18  3:38     ` Sean Anderson
@ 2022-06-19 11:24       ` Krzysztof Kozlowski
  2022-06-19 15:53         ` Sean Anderson
  0 siblings, 1 reply; 56+ messages in thread
From: Krzysztof Kozlowski @ 2022-06-19 11:24 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Kishon Vijay Abraham I, Krzysztof Kozlowski,
	Rob Herring, Vinod Koul, devicetree, linux-phy

On 18/06/2022 05:38, Sean Anderson wrote:
> Hi Krzysztof,
> 
> On 6/17/22 9:15 PM, Krzysztof Kozlowski wrote:
>> On 17/06/2022 13:32, Sean Anderson wrote:
>>> This adds a binding for the SerDes module found on QorIQ processors. The
>>> phy reference has two cells, one for the first lane and one for the
>>> last. This should allow for good support of multi-lane protocols when
>>> (if) they are added. There is no protocol option, because the driver is
>>> designed to be able to completely reconfigure lanes at runtime.
>>> Generally, the phy consumer can select the appropriate protocol using
>>> set_mode. For the most part there is only one protocol controller
>>> (consumer) per lane/protocol combination. The exception to this is the
>>> B4860 processor, which has some lanes which can be connected to
>>> multiple MACs. For that processor, I anticipate the easiest way to
>>> resolve this will be to add an additional cell with a "protocol
>>> controller instance" property.
>>>
>>> Each serdes has a unique set of supported protocols (and lanes). The
>>> support matrix is stored in the driver and is selected based on the
>>> compatible string. It is anticipated that a new compatible string will
>>> need to be added for each serdes on each SoC that drivers support is
>>> added for.
>>>
>>> There are two PLLs, each of which can be used as the master clock for
>>> each lane. Each PLL has its own reference. For the moment they are
>>> required, because it simplifies the driver implementation. Absent
>>> reference clocks can be modeled by a fixed-clock with a rate of 0.
>>>
>>> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
>>> ---
>>>
>>>   .../bindings/phy/fsl,qoriq-serdes.yaml        | 78 +++++++++++++++++++
>>>   1 file changed, 78 insertions(+)
>>>   create mode 100644 Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
>>>
>>> diff --git a/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml b/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
>>> new file mode 100644
>>> index 000000000000..4b9c1fcdab10
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
>>> @@ -0,0 +1,78 @@
>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/phy/fsl,qoriq-serdes.yaml#
>>
>> File name: fsl,ls1046a-serdes.yaml
> 
> This is not appropriate, since this binding will be used for many QorIQ
> devices, not just LS1046A.

This is the DT bindings convention and naming style, so why do you say
it is not appropriate? If the new SoC at some point requires different
binding what filename do you use? fsl,qoriq-serdes2.yaml? And then again
fsl,qoriq-serdes3.yaml?

Please follow DT bindings convention and name it after first compatible
in the bindings.

> The LS1046A is not even an "ur" device (first
> model, etc.) but simply the one I have access to.

It does not matter that much if it is first in total. Use the first one
from the documented compatibles.

> 
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: NXP QorIQ SerDes Device Tree Bindings
>>
>> s/Device Tree Bindings//
> 
> OK
> 
>>> +
>>> +maintainers:
>>> +  - Sean Anderson <sean.anderson@seco.com>
>>> +
>>> +description: |
>>> +  This binding describes the SerDes devices found in NXP's QorIQ line of
>>
>> Describe the device, not the binding, so wording "This binding" is not
>> appropriate.
> 
> OK
> 
>>> +  processors. The SerDes provides up to eight lanes. Each lane may be
>>> +  configured individually, or may be combined with adjacent lanes for a
>>> +  multi-lane protocol. The SerDes supports a variety of protocols, including up
>>> +  to 10G Ethernet, PCIe, SATA, and others. The specific protocols supported for
>>> +  each lane depend on the particular SoC.
>>> +
>>> +properties:
>>
>> Compatible goes first.
>>
>>> +  "#phy-cells":
>>> +    const: 2
>>> +    description: |
>>> +      The cells contain the following arguments.
>>> +
>>> +      - description: |
>>
>> Not a correct schema. What is this "- description" attached to? There is
>> no items here...
> 
> This is the same format as used by
> Documentation/devicetree/bindings/phy/xlnx,zynqmp-psgtr.yaml

I'll fix it.

> 
> How should the cells be documented?

Could be something like that:
Documentation/devicetree/bindings/phy/microchip,lan966x-serdes.yaml

> 
>>> +          The first lane in the group. Lanes are numbered based on the register
>>> +          offsets, not the I/O ports. This corresponds to the letter-based
>>> +          ("Lane A") naming scheme, and not the number-based ("Lane 0") naming
>>> +          scheme. On most SoCs, "Lane A" is "Lane 0", but not always.
>>> +        minimum: 0
>>> +        maximum: 7
>>> +      - description: |
>>> +          Last lane. For single-lane protocols, this should be the same as the
>>> +          first lane.
>>> +        minimum: 0
>>> +        maximum: 7
>>> +
>>> +  compatible:
>>> +    enum:
>>> +      - fsl,ls1046a-serdes-1
>>> +      - fsl,ls1046a-serdes-2
>>
>> Does not look like proper compatible and your explanation from commit
>> msg did not help me. What "1" and "2" stand for? Usually compatibles
>> cannot have some arbitrary properties encoded.
> 
> Each serdes has a different set of supported protocols for each lane. This is encoded
> in the driver data associated with the compatible

Implementation does not matter.

> , along with the appropriate values
> to plug into the protocol control registers. Because each serdes has a different set
> of supported protocols 

Another way is to express it with a property.

> and register configuration, 

What does it mean exactly? The same protocols have different programming
model on the instances?

> adding support for a new SoC will
> require adding the appropriate configuration to the driver, and adding a new compatible
> string. Although most of the driver is generic, this critical portion is shared only
> between closely-related SoCs (such as variants with differing numbers of cores).
> 

Again implementation - we do not talk here about driver, but the bindings.

> The 1 and 2 stand for the number of the SerDes on that SoC. e.g. the documentation will
> refer to SerDes1 and SerDes2.
>   
> So e.g. other compatibles might be
> 
> - fsl,ls1043a-serdes-1 # There's only one serdes on this SoC
> - fsl,t4042-serdes-1 # This SoC has four serdes
> - fsl,t4042-serdes-2
> - fsl,t4042-serdes-3
> - fsl,t4042-serdes-4

If the devices are really different - there is no common parts in the
programming model (registers) - then please find some descriptive
compatible. However if the programming model of common part is
consistent and the differences are only for different protocols (kind of
expected), this should be rather a property describing which protocols
are supported.


Best regards,
Krzysztof

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

* Re: [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-19 11:24       ` Krzysztof Kozlowski
@ 2022-06-19 15:53         ` Sean Anderson
  2022-06-20 10:54           ` Krzysztof Kozlowski
  0 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-19 15:53 UTC (permalink / raw)
  To: Krzysztof Kozlowski, David S . Miller, Jakub Kicinski,
	Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Kishon Vijay Abraham I, Krzysztof Kozlowski,
	Rob Herring, Vinod Koul, devicetree, linux-phy

On 6/19/22 7:24 AM, Krzysztof Kozlowski wrote:
> On 18/06/2022 05:38, Sean Anderson wrote:
>> Hi Krzysztof,
>>
>> On 6/17/22 9:15 PM, Krzysztof Kozlowski wrote:
>>> On 17/06/2022 13:32, Sean Anderson wrote:
>>>> This adds a binding for the SerDes module found on QorIQ processors. The
>>>> phy reference has two cells, one for the first lane and one for the
>>>> last. This should allow for good support of multi-lane protocols when
>>>> (if) they are added. There is no protocol option, because the driver is
>>>> designed to be able to completely reconfigure lanes at runtime.
>>>> Generally, the phy consumer can select the appropriate protocol using
>>>> set_mode. For the most part there is only one protocol controller
>>>> (consumer) per lane/protocol combination. The exception to this is the
>>>> B4860 processor, which has some lanes which can be connected to
>>>> multiple MACs. For that processor, I anticipate the easiest way to
>>>> resolve this will be to add an additional cell with a "protocol
>>>> controller instance" property.
>>>>
>>>> Each serdes has a unique set of supported protocols (and lanes). The
>>>> support matrix is stored in the driver and is selected based on the
>>>> compatible string. It is anticipated that a new compatible string will
>>>> need to be added for each serdes on each SoC that drivers support is
>>>> added for.
>>>>
>>>> There are two PLLs, each of which can be used as the master clock for
>>>> each lane. Each PLL has its own reference. For the moment they are
>>>> required, because it simplifies the driver implementation. Absent
>>>> reference clocks can be modeled by a fixed-clock with a rate of 0.
>>>>
>>>> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
>>>> ---
>>>>
>>>>    .../bindings/phy/fsl,qoriq-serdes.yaml        | 78 +++++++++++++++++++
>>>>    1 file changed, 78 insertions(+)
>>>>    create mode 100644 Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml b/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
>>>> new file mode 100644
>>>> index 000000000000..4b9c1fcdab10
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/phy/fsl,qoriq-serdes.yaml
>>>> @@ -0,0 +1,78 @@
>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>>> +%YAML 1.2
>>>> +---
>>>> +$id: http://devicetree.org/schemas/phy/fsl,qoriq-serdes.yaml#
>>>
>>> File name: fsl,ls1046a-serdes.yaml
>>
>> This is not appropriate, since this binding will be used for many QorIQ
>> devices, not just LS1046A.
> 
> This is the DT bindings convention and naming style, so why do you say
> it is not appropriate? If the new SoC at some point requires different
> binding what filename do you use? fsl,qoriq-serdes2.yaml? And then again
> fsl,qoriq-serdes3.yaml?

Correct. This serdes has been present in almost every QorIQ product over
a period of 10-15 years.

> Please follow DT bindings convention and name it after first compatible
> in the bindings.

As noted by Ioana, this is apparently a "lynx-10g" serdes, and will be
named appropriately.

>> The LS1046A is not even an "ur" device (first
>> model, etc.) but simply the one I have access to.
> 
> It does not matter that much if it is first in total. Use the first one
> from the documented compatibles.
> 
>>
>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>> +
>>>> +title: NXP QorIQ SerDes Device Tree Bindings
>>>
>>> s/Device Tree Bindings//
>>
>> OK
>>
>>>> +
>>>> +maintainers:
>>>> +  - Sean Anderson <sean.anderson@seco.com>
>>>> +
>>>> +description: |
>>>> +  This binding describes the SerDes devices found in NXP's QorIQ line of
>>>
>>> Describe the device, not the binding, so wording "This binding" is not
>>> appropriate.
>>
>> OK
>>
>>>> +  processors. The SerDes provides up to eight lanes. Each lane may be
>>>> +  configured individually, or may be combined with adjacent lanes for a
>>>> +  multi-lane protocol. The SerDes supports a variety of protocols, including up
>>>> +  to 10G Ethernet, PCIe, SATA, and others. The specific protocols supported for
>>>> +  each lane depend on the particular SoC.
>>>> +
>>>> +properties:
>>>
>>> Compatible goes first.
>>>
>>>> +  "#phy-cells":
>>>> +    const: 2
>>>> +    description: |
>>>> +      The cells contain the following arguments.
>>>> +
>>>> +      - description: |
>>>
>>> Not a correct schema. What is this "- description" attached to? There is
>>> no items here...
>>
>> This is the same format as used by
>> Documentation/devicetree/bindings/phy/xlnx,zynqmp-psgtr.yaml
> 
> I'll fix it.
> 
>>
>> How should the cells be documented?
> 
> Could be something like that:
> Documentation/devicetree/bindings/phy/microchip,lan966x-serdes.yaml
> 
>>
>>>> +          The first lane in the group. Lanes are numbered based on the register
>>>> +          offsets, not the I/O ports. This corresponds to the letter-based
>>>> +          ("Lane A") naming scheme, and not the number-based ("Lane 0") naming
>>>> +          scheme. On most SoCs, "Lane A" is "Lane 0", but not always.
>>>> +        minimum: 0
>>>> +        maximum: 7
>>>> +      - description: |
>>>> +          Last lane. For single-lane protocols, this should be the same as the
>>>> +          first lane.
>>>> +        minimum: 0
>>>> +        maximum: 7
>>>> +
>>>> +  compatible:
>>>> +    enum:
>>>> +      - fsl,ls1046a-serdes-1
>>>> +      - fsl,ls1046a-serdes-2
>>>
>>> Does not look like proper compatible and your explanation from commit
>>> msg did not help me. What "1" and "2" stand for? Usually compatibles
>>> cannot have some arbitrary properties encoded.
>>
>> Each serdes has a different set of supported protocols for each lane. This is encoded
>> in the driver data associated with the compatible
> 
> Implementation does not matter.

Of *course* implementation matters. Devicetree bindings do not happen in a vacuum. They
describe the hardware, but only in service to the implementation.

>> , along with the appropriate values
>> to plug into the protocol control registers. Because each serdes has a different set
>> of supported protocols
> 
> Another way is to express it with a property.
> 
>> and register configuration,
> 
> What does it mean exactly? The same protocols have different programming
> model on the instances?

(In the below paragraph, when I say "register" I mean "register or field within a
register")

Yes. Every serdes instance has a different way to program protocols into lanes. While
there is a little bit of orthogonality (the same registers are typically used for the
same protocols), each serdes is different. The values programmed into the registers are
unique to the serdes, and the lane which they apply to is also unique (e.g. the same
register may be used to program a different lane with a different protocol).

>> adding support for a new SoC will
>> require adding the appropriate configuration to the driver, and adding a new compatible
>> string. Although most of the driver is generic, this critical portion is shared only
>> between closely-related SoCs (such as variants with differing numbers of cores).
>>
> 
> Again implementation - we do not talk here about driver, but the bindings.
> 
>> The 1 and 2 stand for the number of the SerDes on that SoC. e.g. the documentation will
>> refer to SerDes1 and SerDes2.
>>    
>> So e.g. other compatibles might be
>>
>> - fsl,ls1043a-serdes-1 # There's only one serdes on this SoC
>> - fsl,t4042-serdes-1 # This SoC has four serdes
>> - fsl,t4042-serdes-2
>> - fsl,t4042-serdes-3
>> - fsl,t4042-serdes-4
> 
> If the devices are really different - there is no common parts in the
> programming model (registers) - then please find some descriptive
> compatible. However if the programming model of common part is
> consistent and the differences are only for different protocols (kind of
> expected), this should be rather a property describing which protocols
> are supported.
> 

I do not want to complicate the driver by attempting to encode such information in the
bindings. Storing the information in the driver is extremely common. Please refer to e.g.

- mvebu_comphy_cp110_modes in drivers/phy/marvell/phy-mvebu-cp110-comphy.c
- mvebu_a3700_comphy_modes in drivers/phy/marvell/phy-mvebu-a3700-comphy.c
- icm_matrix in drivers/phy/xilinx/phy-zynqmp.c
- samsung_usb2_phy_config in drivers/phy/samsung/
- qmp_phy_init_tbl in drivers/phy/qualcomm/phy-qcom-qmp.c

All of these drivers (and there are more)

- Use a driver-internal struct to encode information specific to different device models.
- Select that struct based on the compatible

The other thing is that while the LS1046A SerDes are fairly generic, other SerDes of this
type have particular restructions on the clocks. E.g. on some SoCs, certain protocols
cannot be used together (even if they would otherwise be legal), and some protocols must
use particular PLLs (whereas in general there is no such restriction). There are also
some register fields which are required to program on some SoCs, and which are reserved
on others.

There is, frankly, a large amount of variation between devices as implemented on different
SoCs. Especially because (AIUI) drivers must remain compatible with old devicetrees, I
think using a specific compatible string is especially appropriate here. It will give us
the ability to correct any implementation quirks as they are discovered (and I anticipate
that there will be) rather than having to determine everything up front.

--Sean

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

* Re: [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-19 15:53         ` Sean Anderson
@ 2022-06-20 10:54           ` Krzysztof Kozlowski
  2022-06-20 17:19             ` Sean Anderson
  0 siblings, 1 reply; 56+ messages in thread
From: Krzysztof Kozlowski @ 2022-06-20 10:54 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Kishon Vijay Abraham I, Krzysztof Kozlowski,
	Rob Herring, Vinod Koul, devicetree, linux-phy

On 19/06/2022 17:53, Sean Anderson wrote:
>>>
>>>>> +          The first lane in the group. Lanes are numbered based on the register
>>>>> +          offsets, not the I/O ports. This corresponds to the letter-based
>>>>> +          ("Lane A") naming scheme, and not the number-based ("Lane 0") naming
>>>>> +          scheme. On most SoCs, "Lane A" is "Lane 0", but not always.
>>>>> +        minimum: 0
>>>>> +        maximum: 7
>>>>> +      - description: |
>>>>> +          Last lane. For single-lane protocols, this should be the same as the
>>>>> +          first lane.
>>>>> +        minimum: 0
>>>>> +        maximum: 7
>>>>> +
>>>>> +  compatible:
>>>>> +    enum:
>>>>> +      - fsl,ls1046a-serdes-1
>>>>> +      - fsl,ls1046a-serdes-2
>>>>
>>>> Does not look like proper compatible and your explanation from commit
>>>> msg did not help me. What "1" and "2" stand for? Usually compatibles
>>>> cannot have some arbitrary properties encoded.
>>>
>>> Each serdes has a different set of supported protocols for each lane. This is encoded
>>> in the driver data associated with the compatible
>>
>> Implementation does not matter.
> 
> Of *course* implementation matters. Devicetree bindings do not happen in a vacuum. They
> describe the hardware, but only in service to the implementation.

This is so not true. Bindings do not service implementation. Bindings
happen in vacuum, because they are used by different implementations:
Linux, u-Boot, BSD and several other quite different systems.

Any references to implemention from the bindings is questionable,
although of course not always wrong.

Building bindings per specific implementation is as well usually not
correct.

> 
>>> , along with the appropriate values
>>> to plug into the protocol control registers. Because each serdes has a different set
>>> of supported protocols
>>
>> Another way is to express it with a property.
>>
>>> and register configuration,
>>
>> What does it mean exactly? The same protocols have different programming
>> model on the instances?
> 
> (In the below paragraph, when I say "register" I mean "register or field within a
> register")
> 
> Yes. Every serdes instance has a different way to program protocols into lanes. While
> there is a little bit of orthogonality (the same registers are typically used for the
> same protocols), each serdes is different. The values programmed into the registers are
> unique to the serdes, and the lane which they apply to is also unique (e.g. the same
> register may be used to program a different lane with a different protocol).

That's not answering the point here, but I'll respond to the later
paragraph.

> 
>>> adding support for a new SoC will
>>> require adding the appropriate configuration to the driver, and adding a new compatible
>>> string. Although most of the driver is generic, this critical portion is shared only
>>> between closely-related SoCs (such as variants with differing numbers of cores).
>>>
>>
>> Again implementation - we do not talk here about driver, but the bindings.
>>
>>> The 1 and 2 stand for the number of the SerDes on that SoC. e.g. the documentation will
>>> refer to SerDes1 and SerDes2.
>>>    
>>> So e.g. other compatibles might be
>>>
>>> - fsl,ls1043a-serdes-1 # There's only one serdes on this SoC
>>> - fsl,t4042-serdes-1 # This SoC has four serdes
>>> - fsl,t4042-serdes-2
>>> - fsl,t4042-serdes-3
>>> - fsl,t4042-serdes-4
>>
>> If the devices are really different - there is no common parts in the
>> programming model (registers) - then please find some descriptive
>> compatible. However if the programming model of common part is
>> consistent and the differences are only for different protocols (kind of
>> expected), this should be rather a property describing which protocols
>> are supported.
>>
> 
> I do not want to complicate the driver by attempting to encode such information in the
> bindings. Storing the information in the driver is extremely common. Please refer to e.g.

Yes, quirks are even more common, more flexible and are in general
recommended for more complicated cases. Yet you talk about driver
implementation, which I barely care.

> 
> - mvebu_comphy_cp110_modes in drivers/phy/marvell/phy-mvebu-cp110-comphy.c
> - mvebu_a3700_comphy_modes in drivers/phy/marvell/phy-mvebu-a3700-comphy.c
> - icm_matrix in drivers/phy/xilinx/phy-zynqmp.c
> - samsung_usb2_phy_config in drivers/phy/samsung/

This one is a good example - where do you see there compatibles with
arbitrary numbers attached?

> - qmp_phy_init_tbl in drivers/phy/qualcomm/phy-qcom-qmp.c
> 
> All of these drivers (and there are more)
> 
> - Use a driver-internal struct to encode information specific to different device models.
> - Select that struct based on the compatible

Driver implementation. You can do it in many different ways. Does not
matter for the bindings.

> 
> The other thing is that while the LS1046A SerDes are fairly generic, other SerDes of this
> type have particular restructions on the clocks. E.g. on some SoCs, certain protocols
> cannot be used together (even if they would otherwise be legal), and some protocols must
> use particular PLLs (whereas in general there is no such restriction). There are also
> some register fields which are required to program on some SoCs, and which are reserved
> on others.

Just to be clear, because you are quite unspecific here ("some
protocols") - we talk about the same protocol programmed on two of these
serdes (serdes-1 and serdes-2 how you call it). Does it use different
registers? Are some registers - for the same protocol - reserved in one
version?

> 
> There is, frankly, a large amount of variation between devices as implemented on different
> SoCs. 

This I don't get. You mean different SoCs have entirely different
Serdes? Sure, no problem. We talk here only about this SoC, this
serdes-1 and serdes-2.

> Especially because (AIUI) drivers must remain compatible with old devicetrees, I
> think using a specific compatible string is especially appropriate here. 

This argument does not make any sense in case of new bindings and new
drivers, unless you build on top of existing implementation. Anyway no
one asks you to break existing bindings...

> It will give us
> the ability to correct any implementation quirks as they are discovered (and I anticipate
> that there will be) rather than having to determine everything up front.

All the quirks can be also chosen by respective properties.

Anyway, "serdes-1" and "serdes-2" are not correct compatibles, so my NAK
stays. These might be separate compatibles, although that would require
proper naming and proper justification (as you did not answer my actual
questions about differences when using same protocols). Judging by the
bindings and your current description (implementation does not matter),
this also looks like a property.


Best regards,
Krzysztof

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

* Re: [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-20 10:54           ` Krzysztof Kozlowski
@ 2022-06-20 17:19             ` Sean Anderson
  2022-06-20 18:21               ` Krzysztof Kozlowski
  0 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-20 17:19 UTC (permalink / raw)
  To: Krzysztof Kozlowski, David S . Miller, Jakub Kicinski,
	Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Kishon Vijay Abraham I, Krzysztof Kozlowski,
	Rob Herring, Vinod Koul, devicetree, linux-phy



On 6/20/22 6:54 AM, Krzysztof Kozlowski wrote:
> On 19/06/2022 17:53, Sean Anderson wrote:
>>>>
>>>>>> +          The first lane in the group. Lanes are numbered based on the register
>>>>>> +          offsets, not the I/O ports. This corresponds to the letter-based
>>>>>> +          ("Lane A") naming scheme, and not the number-based ("Lane 0") naming
>>>>>> +          scheme. On most SoCs, "Lane A" is "Lane 0", but not always.
>>>>>> +        minimum: 0
>>>>>> +        maximum: 7
>>>>>> +      - description: |
>>>>>> +          Last lane. For single-lane protocols, this should be the same as the
>>>>>> +          first lane.
>>>>>> +        minimum: 0
>>>>>> +        maximum: 7
>>>>>> +
>>>>>> +  compatible:
>>>>>> +    enum:
>>>>>> +      - fsl,ls1046a-serdes-1
>>>>>> +      - fsl,ls1046a-serdes-2
>>>>>
>>>>> Does not look like proper compatible and your explanation from commit
>>>>> msg did not help me. What "1" and "2" stand for? Usually compatibles
>>>>> cannot have some arbitrary properties encoded.
>>>>
>>>> Each serdes has a different set of supported protocols for each lane. This is encoded
>>>> in the driver data associated with the compatible
>>>
>>> Implementation does not matter.
>> 
>> Of *course* implementation matters. Devicetree bindings do not happen in a vacuum. They
>> describe the hardware, but only in service to the implementation.
> 
> This is so not true. > Bindings do not service implementation. Bindings
> happen in vacuum

Where are all the bindings for hardware without drivers?

Why don't device trees describe the entire hardware before any drivers are written?

Actually, I have seen some device trees written like that (baked into the chip's ROM),
and they cannot be used because the bindings

- Do not fully describe the hardware (e.g. clocks, resets, interrupts, and other things)
- Do not describe the hardware in a compatible way (e.g. using different names for
  registers and clocks, or ordering fields differently).
- Contain typos and errors (since they were never used)

These same issues apply to any new binding documentation. Claiming that bindings happen
in a vacuum is de facto untrue, and would be unsound practice if it wasn't.

> because they are used by different implementations:
> Linux, u-Boot, BSD and several other quite different systems.

U-Boot doesn't use devicetree for this device (and if it did the port would likely be
based on the Linux driver). BSD doesn't support this hardware at all. We are the first
to create a driver for this device, so we get to choose the binding.

> Any references to implemention from the bindings is questionable,
> although of course not always wrong.
> 
> Building bindings per specific implementation is as well usually not
> correct.

Sure, but there are of course many ways to create bindings, even for the same hardware.
As an example, pinctrl bindings can be written like

pinctrl@cafebabe {
	uart-tx {
		function = "uart-tx";
		pins = "5";
	};
};

or

pinctrl@deadbeef {
	uart-tx {
		pinmux = <SOME_MACRO(5, UART_TX)>;
	};
};

or

pinctrl@d00dfeed {
	uart-tx {
		pinmux = <SOME_MACRO(5, FUNC3)>;
	};
};

and which one to use depends both on the structure of the hardware, as well as the
driver. These bindings require a different driver style under the hood, and using
the wrong binding can unnecessarily complicate the driver for no reason.

To further beat home the point, someone might use a "fixed-clock" to describe a clock
and then later change to a more detailed implementation. They could use "simple-pinctrl"
and then later move to a device-specific driver. 

If the devicetree author is smart, then they will create a binding like

clock {
	compatible = "vendor,my-clock", "fixed-clock";
	...
};

so that better support might be added in the future. In fact, that is *exactly* what I
am suggesting here.

>> 
>>>> , along with the appropriate values
>>>> to plug into the protocol control registers. Because each serdes has a different set
>>>> of supported protocols
>>>
>>> Another way is to express it with a property.
>>>
>>>> and register configuration,
>>>
>>> What does it mean exactly? The same protocols have different programming
>>> model on the instances?
>> 
>> (In the below paragraph, when I say "register" I mean "register or field within a
>> register")
>> 
>> Yes. Every serdes instance has a different way to program protocols into lanes. While
>> there is a little bit of orthogonality (the same registers are typically used for the
>> same protocols), each serdes is different. The values programmed into the registers are
>> unique to the serdes, and the lane which they apply to is also unique (e.g. the same
>> register may be used to program a different lane with a different protocol).
> 
> That's not answering the point here, but I'll respond to the later
> paragraph.
> 
>> 
>>>> adding support for a new SoC will
>>>> require adding the appropriate configuration to the driver, and adding a new compatible
>>>> string. Although most of the driver is generic, this critical portion is shared only
>>>> between closely-related SoCs (such as variants with differing numbers of cores).
>>>>
>>>
>>> Again implementation - we do not talk here about driver, but the bindings.
>>>
>>>> The 1 and 2 stand for the number of the SerDes on that SoC. e.g. the documentation will
>>>> refer to SerDes1 and SerDes2.
>>>>    
>>>> So e.g. other compatibles might be
>>>>
>>>> - fsl,ls1043a-serdes-1 # There's only one serdes on this SoC
>>>> - fsl,t4042-serdes-1 # This SoC has four serdes
>>>> - fsl,t4042-serdes-2
>>>> - fsl,t4042-serdes-3
>>>> - fsl,t4042-serdes-4
>>>
>>> If the devices are really different - there is no common parts in the
>>> programming model (registers) - then please find some descriptive
>>> compatible. However if the programming model of common part is
>>> consistent and the differences are only for different protocols (kind of
>>> expected), this should be rather a property describing which protocols
>>> are supported.
>>>
>> 
>> I do not want to complicate the driver by attempting to encode such information in the
>> bindings. Storing the information in the driver is extremely common. Please refer to e.g.
> 
> Yes, quirks are even more common, more flexible and are in general
> recommended for more complicated cases. Yet you talk about driver
> implementation, which I barely care.
> 
>> 
>> - mvebu_comphy_cp110_modes in drivers/phy/marvell/phy-mvebu-cp110-comphy.c
>> - mvebu_a3700_comphy_modes in drivers/phy/marvell/phy-mvebu-a3700-comphy.c
>> - icm_matrix in drivers/phy/xilinx/phy-zynqmp.c
>> - samsung_usb2_phy_config in drivers/phy/samsung/
> 
> This one is a good example - where do you see there compatibles with
> arbitrary numbers attached?

samsung_usb2_phy_of_match in drivers/phy/samsung/phy-samsung-usb2.c

There is a different compatible for each SoC variant. Each compatible selects a struct
containing

- A list of phys, each with custom power on and off functions
- A function which converts a rate to an arbitrary value to program into a register

This is further documented in Documentation/driver-api/phy/samsung-usb2.rst

>> - qmp_phy_init_tbl in drivers/phy/qualcomm/phy-qcom-qmp.c
>> 
>> All of these drivers (and there are more)
>> 
>> - Use a driver-internal struct to encode information specific to different device models.
>> - Select that struct based on the compatible
> 
> Driver implementation. You can do it in many different ways. Does not
> matter for the bindings.

And because this both describes the hardware and is convenient to the implementation,
I have chosen this way.

>> 
>> The other thing is that while the LS1046A SerDes are fairly generic, other SerDes of this
>> type have particular restructions on the clocks. E.g. on some SoCs, certain protocols
>> cannot be used together (even if they would otherwise be legal), and some protocols must
>> use particular PLLs (whereas in general there is no such restriction). There are also
>> some register fields which are required to program on some SoCs, and which are reserved
>> on others.
> 
> Just to be clear, because you are quite unspecific here ("some
> protocols") - we talk about the same protocol programmed on two of these
> serdes (serdes-1 and serdes-2 how you call it). Does it use different
> registers?

Yes.

> Are some registers - for the same protocol - reserved in one version?

Yes.

For example, I excerpt part of the documentation for PCCR2 on the T4240:

> XFIa Configuration:
> XFIA_CFG Default value set by RCW configuration.
> This field must be 0 for SerDes 3 & 4
> All settings not shown are reserved
> 
> 00 Disabled
> 01 x1 on Lane 3 to FM2 MAC 9

And here is part of the documentation for PCCR2 on the LS1046A:

> SATAa Configuration
> All others reserved
> NOTE: This field is not supported in every instance. The following table includes only
>       supported registers.
> Field supported in	Field not supported in
> SerDes1_PCCR2		—
> —			SerDes2_PCCR2
> 
> 000b - Disabled
> 001b - x1 on Lane 3 (SerDes #2 only)

And here is part of the documentation for PCCRB on the LS1046A:

> XFIa Configuration
> All others reserved Default value set by RCW configuration.
> 
> 000b - Disabled
> 010b - x1 on Lane 1 to XGMIIa (Serdes #1 only)
You may notice that

- For some SerDes on the same SoC, these fields are reserved
- Between different SoCs, different protocols may be configured in different registers
- The same registers may be used for different protocols in different SoCs (though
  generally there are several general layouts)
- Fields have particular values which must be programmed

In addition, the documentation also says

> Reserved registers and fields must be preserved on writes.

All of these combined issues make it so that we need detailed, serdes-specific
configuration. The easiest way to store this configuration is in the driver. This
is consistent with *many* existing phy implementations. I would like to write a
standard phy driver, not one twisted by unusual device tree requirements.

>> 
>> There is, frankly, a large amount of variation between devices as implemented on different
>> SoCs. 
> 
> This I don't get. You mean different SoCs have entirely different
> Serdes? Sure, no problem. We talk here only about this SoC, this
> serdes-1 and serdes-2.
> 
>> Especially because (AIUI) drivers must remain compatible with old devicetrees, I
>> think using a specific compatible string is especially appropriate here. 
> 
> This argument does not make any sense in case of new bindings and new
> drivers, unless you build on top of existing implementation. Anyway no
> one asks you to break existing bindings...

When there is a bug in the bindings how do you fix it? If I were to follow your suggested method, it would be difficult to determine the particular devices

>> It will give us
>> the ability to correct any implementation quirks as they are discovered (and I anticipate
>> that there will be) rather than having to determine everything up front.
> 
> All the quirks can be also chosen by respective properties.

Quirks are *exactly* the sort of implementation-specific details that you were opposed to above.

> Anyway, "serdes-1" and "serdes-2" are not correct compatibles,

The compatibles suggested were "fsl,ls1046-serdes-1" and -2. As noted above, these are separate
devices which, while having many similarities, have different register layouts and protocol
support. They are *not* 100% compatible with each other. Would you require that clock drivers
for different SoCs use the same compatibles just because they had the same registers, even though
the clocks themselves had different functions and hierarchy?

--Sean

> so my NAK
> stays. These might be separate compatibles, although that would require
> proper naming and proper justification (as you did not answer my actual
> questions about differences when using same protocols). Judging by the
> bindings and your current description (implementation does not matter),
> this also looks like a property.
> 
> 
> Best regards,
> Krzysztof
> 

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

* Re: [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-20 17:19             ` Sean Anderson
@ 2022-06-20 18:21               ` Krzysztof Kozlowski
  2022-06-20 18:51                 ` Sean Anderson
  0 siblings, 1 reply; 56+ messages in thread
From: Krzysztof Kozlowski @ 2022-06-20 18:21 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Kishon Vijay Abraham I, Krzysztof Kozlowski,
	Rob Herring, Vinod Koul, devicetree, linux-phy

On 20/06/2022 19:19, Sean Anderson wrote:
> 
> 
> On 6/20/22 6:54 AM, Krzysztof Kozlowski wrote:
>> On 19/06/2022 17:53, Sean Anderson wrote:
>>>>>
>>>>>>> +          The first lane in the group. Lanes are numbered based on the register
>>>>>>> +          offsets, not the I/O ports. This corresponds to the letter-based
>>>>>>> +          ("Lane A") naming scheme, and not the number-based ("Lane 0") naming
>>>>>>> +          scheme. On most SoCs, "Lane A" is "Lane 0", but not always.
>>>>>>> +        minimum: 0
>>>>>>> +        maximum: 7
>>>>>>> +      - description: |
>>>>>>> +          Last lane. For single-lane protocols, this should be the same as the
>>>>>>> +          first lane.
>>>>>>> +        minimum: 0
>>>>>>> +        maximum: 7
>>>>>>> +
>>>>>>> +  compatible:
>>>>>>> +    enum:
>>>>>>> +      - fsl,ls1046a-serdes-1
>>>>>>> +      - fsl,ls1046a-serdes-2
>>>>>>
>>>>>> Does not look like proper compatible and your explanation from commit
>>>>>> msg did not help me. What "1" and "2" stand for? Usually compatibles
>>>>>> cannot have some arbitrary properties encoded.
>>>>>
>>>>> Each serdes has a different set of supported protocols for each lane. This is encoded
>>>>> in the driver data associated with the compatible
>>>>
>>>> Implementation does not matter.
>>>
>>> Of *course* implementation matters. Devicetree bindings do not happen in a vacuum. They
>>> describe the hardware, but only in service to the implementation.
>>
>> This is so not true. > Bindings do not service implementation. Bindings
>> happen in vacuum
> 
> Where are all the bindings for hardware without drivers?
> 
> Why don't device trees describe the entire hardware before any drivers are written?
> 
> Actually, I have seen some device trees written like that (baked into the chip's ROM),
> and they cannot be used because the bindings
> 
> - Do not fully describe the hardware (e.g. clocks, resets, interrupts, and other things)
> - Do not describe the hardware in a compatible way (e.g. using different names for
>   registers and clocks, or ordering fields differently).
> - Contain typos and errors (since they were never used)
> 
> These same issues apply to any new binding documentation. Claiming that bindings happen
> in a vacuum is de facto untrue, and would be unsound practice if it wasn't.
> 
>> because they are used by different implementations:
>> Linux, u-Boot, BSD and several other quite different systems.
> 
> U-Boot doesn't use devicetree for this device (and if it did the port would likely be
> based on the Linux driver). BSD doesn't support this hardware at all. We are the first
> to create a driver for this device, so we get to choose the binding.

You choose the binding in respect to the guidelines. You cannot choose
some random weirdness just because you are first. It does not matter
that there are no other implementations in that way - you must choose
reasonable bindings.

> 
>> Any references to implemention from the bindings is questionable,
>> although of course not always wrong.
>>
>> Building bindings per specific implementation is as well usually not
>> correct.
> 
> Sure, but there are of course many ways to create bindings, even for the same hardware.
> As an example, pinctrl bindings can be written like
> 
> pinctrl@cafebabe {
> 	uart-tx {
> 		function = "uart-tx";
> 		pins = "5";
> 	};
> };
> 
> or
> 
> pinctrl@deadbeef {
> 	uart-tx {
> 		pinmux = <SOME_MACRO(5, UART_TX)>;
> 	};
> };
> 
> or
> 
> pinctrl@d00dfeed {
> 	uart-tx {
> 		pinmux = <SOME_MACRO(5, FUNC3)>;
> 	};
> };
> 
> and which one to use depends both on the structure of the hardware, as well as the
> driver. These bindings require a different driver style under the hood, and using
> the wrong binding can unnecessarily complicate the driver for no reason.
> 
> To further beat home the point, someone might use a "fixed-clock" to describe a clock
> and then later change to a more detailed implementation. They could use "simple-pinctrl"
> and then later move to a device-specific driver. 
> 
> If the devicetree author is smart, then they will create a binding like
> 
> clock {
> 	compatible = "vendor,my-clock", "fixed-clock";
> 	...
> };
> 
> so that better support might be added in the future. In fact, that is *exactly* what I
> am suggesting here.
> 
>>>
>>>>> , along with the appropriate values
>>>>> to plug into the protocol control registers. Because each serdes has a different set
>>>>> of supported protocols
>>>>
>>>> Another way is to express it with a property.
>>>>
>>>>> and register configuration,
>>>>
>>>> What does it mean exactly? The same protocols have different programming
>>>> model on the instances?
>>>
>>> (In the below paragraph, when I say "register" I mean "register or field within a
>>> register")
>>>
>>> Yes. Every serdes instance has a different way to program protocols into lanes. While
>>> there is a little bit of orthogonality (the same registers are typically used for the
>>> same protocols), each serdes is different. The values programmed into the registers are
>>> unique to the serdes, and the lane which they apply to is also unique (e.g. the same
>>> register may be used to program a different lane with a different protocol).
>>
>> That's not answering the point here, but I'll respond to the later
>> paragraph.
>>
>>>
>>>>> adding support for a new SoC will
>>>>> require adding the appropriate configuration to the driver, and adding a new compatible
>>>>> string. Although most of the driver is generic, this critical portion is shared only
>>>>> between closely-related SoCs (such as variants with differing numbers of cores).
>>>>>
>>>>
>>>> Again implementation - we do not talk here about driver, but the bindings.
>>>>
>>>>> The 1 and 2 stand for the number of the SerDes on that SoC. e.g. the documentation will
>>>>> refer to SerDes1 and SerDes2.
>>>>>    
>>>>> So e.g. other compatibles might be
>>>>>
>>>>> - fsl,ls1043a-serdes-1 # There's only one serdes on this SoC
>>>>> - fsl,t4042-serdes-1 # This SoC has four serdes
>>>>> - fsl,t4042-serdes-2
>>>>> - fsl,t4042-serdes-3
>>>>> - fsl,t4042-serdes-4
>>>>
>>>> If the devices are really different - there is no common parts in the
>>>> programming model (registers) - then please find some descriptive
>>>> compatible. However if the programming model of common part is
>>>> consistent and the differences are only for different protocols (kind of
>>>> expected), this should be rather a property describing which protocols
>>>> are supported.
>>>>
>>>
>>> I do not want to complicate the driver by attempting to encode such information in the
>>> bindings. Storing the information in the driver is extremely common. Please refer to e.g.
>>
>> Yes, quirks are even more common, more flexible and are in general
>> recommended for more complicated cases. Yet you talk about driver
>> implementation, which I barely care.
>>
>>>
>>> - mvebu_comphy_cp110_modes in drivers/phy/marvell/phy-mvebu-cp110-comphy.c
>>> - mvebu_a3700_comphy_modes in drivers/phy/marvell/phy-mvebu-a3700-comphy.c
>>> - icm_matrix in drivers/phy/xilinx/phy-zynqmp.c
>>> - samsung_usb2_phy_config in drivers/phy/samsung/
>>
>> This one is a good example - where do you see there compatibles with
>> arbitrary numbers attached?
> 
> samsung_usb2_phy_of_match in drivers/phy/samsung/phy-samsung-usb2.c
> 
> There is a different compatible for each SoC variant. Each compatible selects a struct
> containing
> 
> - A list of phys, each with custom power on and off functions
> - A function which converts a rate to an arbitrary value to program into a register
> 
> This is further documented in Documentation/driver-api/phy/samsung-usb2.rst

Exactly, please follow this approach. Compatible is per different
device, e.g. different SoC variant. Of course you could have different
devices on same SoC, but "1" and "2" are not different devices.

> 
>>> - qmp_phy_init_tbl in drivers/phy/qualcomm/phy-qcom-qmp.c
>>>
>>> All of these drivers (and there are more)
>>>
>>> - Use a driver-internal struct to encode information specific to different device models.
>>> - Select that struct based on the compatible
>>
>> Driver implementation. You can do it in many different ways. Does not
>> matter for the bindings.
> 
> And because this both describes the hardware and is convenient to the implementation,
> I have chosen this way.
> 
>>>
>>> The other thing is that while the LS1046A SerDes are fairly generic, other SerDes of this
>>> type have particular restructions on the clocks. E.g. on some SoCs, certain protocols
>>> cannot be used together (even if they would otherwise be legal), and some protocols must
>>> use particular PLLs (whereas in general there is no such restriction). There are also
>>> some register fields which are required to program on some SoCs, and which are reserved
>>> on others.
>>
>> Just to be clear, because you are quite unspecific here ("some
>> protocols") - we talk about the same protocol programmed on two of these
>> serdes (serdes-1 and serdes-2 how you call it). Does it use different
>> registers?
> 
> Yes.
> 
>> Are some registers - for the same protocol - reserved in one version?
> 
> Yes.
> 
> For example, I excerpt part of the documentation for PCCR2 on the T4240:
> 
>> XFIa Configuration:
>> XFIA_CFG Default value set by RCW configuration.
>> This field must be 0 for SerDes 3 & 4
>> All settings not shown are reserved
>>
>> 00 Disabled
>> 01 x1 on Lane 3 to FM2 MAC 9
> 
> And here is part of the documentation for PCCR2 on the LS1046A:
> 
>> SATAa Configuration
>> All others reserved
>> NOTE: This field is not supported in every instance. The following table includes only
>>       supported registers.
>> Field supported in	Field not supported in
>> SerDes1_PCCR2		—
>> —			SerDes2_PCCR2
>>
>> 000b - Disabled
>> 001b - x1 on Lane 3 (SerDes #2 only)
> 
> And here is part of the documentation for PCCRB on the LS1046A:
> 
>> XFIa Configuration
>> All others reserved Default value set by RCW configuration.
>>
>> 000b - Disabled
>> 010b - x1 on Lane 1 to XGMIIa (Serdes #1 only)
> You may notice that
> 
> - For some SerDes on the same SoC, these fields are reserved

That all sounds like quite different devices, which indeed usually is
described with different compatibles. Still "xxx-1" and "xxx-2" are not
valid compatibles. You need to come with some more reasonable name
describing them. Maybe the block has revision or different model/vendor.

> - Between different SoCs, different protocols may be configured in different registers
> - The same registers may be used for different protocols in different SoCs (though
>   generally there are several general layouts)

Different SoCs give you different compatibles, so problem is solved and
that's not exactly argument for this case.

> - Fields have particular values which must be programmed
> 
> In addition, the documentation also says
> 
>> Reserved registers and fields must be preserved on writes.
> 
> All of these combined issues make it so that we need detailed, serdes-specific
> configuration. The easiest way to store this configuration is in the driver. This
> is consistent with *many* existing phy implementations. I would like to write a
> standard phy driver, not one twisted by unusual device tree requirements.

Sure.

> 
>>>
>>> There is, frankly, a large amount of variation between devices as implemented on different
>>> SoCs. 
>>
>> This I don't get. You mean different SoCs have entirely different
>> Serdes? Sure, no problem. We talk here only about this SoC, this
>> serdes-1 and serdes-2.
>>
>>> Especially because (AIUI) drivers must remain compatible with old devicetrees, I
>>> think using a specific compatible string is especially appropriate here. 
>>
>> This argument does not make any sense in case of new bindings and new
>> drivers, unless you build on top of existing implementation. Anyway no
>> one asks you to break existing bindings...
> 
> When there is a bug in the bindings how do you fix it? If I were to follow your suggested method, it would be difficult to determine the particular devices
> 
>>> It will give us
>>> the ability to correct any implementation quirks as they are discovered (and I anticipate
>>> that there will be) rather than having to determine everything up front.
>>
>> All the quirks can be also chosen by respective properties.
> 
> Quirks are *exactly* the sort of implementation-specific details that you were opposed to above.
> 
>> Anyway, "serdes-1" and "serdes-2" are not correct compatibles,
> 
> The compatibles suggested were "fsl,ls1046-serdes-1" and -2. As noted above, these are separate
> devices which, while having many similarities, have different register layouts and protocol
> support. They are *not* 100% compatible with each other. Would you require that clock drivers
> for different SoCs use the same compatibles just because they had the same registers, even though
> the clocks themselves had different functions and hierarchy?

You miss the point. Clock controllers on same SoC have different names
used in compatibles. We do not describe them as "vendor,aa-clk-1" and
"vendor,aa-clk-2".

Come with proper naming and entire discussion might be not valid
(although with not perfect naming Rob might come with questions). I
cannot propose the name because I don't know these hardware blocks and I
do not have access to datasheet.

Other way, if any reasonable naming is not possible, could be also to
describe the meaning of "-1" suffix, e.g. that it does not mean some
index but a variant from specification.

> 
> --Sean
> 
>> so my NAK
>> stays. These might be separate compatibles, although that would require
>> proper naming and proper justification (as you did not answer my actual
>> questions about differences when using same protocols). Judging by the
>> bindings and your current description (implementation does not matter),
>> this also looks like a property.


Best regards,
Krzysztof

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

* Re: [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-20 18:21               ` Krzysztof Kozlowski
@ 2022-06-20 18:51                 ` Sean Anderson
  2022-06-21  7:12                   ` Krzysztof Kozlowski
  0 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-20 18:51 UTC (permalink / raw)
  To: Krzysztof Kozlowski, David S . Miller, Jakub Kicinski,
	Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Kishon Vijay Abraham I, Krzysztof Kozlowski,
	Rob Herring, Vinod Koul, devicetree, linux-phy, Ioana Ciornei

On 6/20/22 2:21 PM, Krzysztof Kozlowski wrote:
>>>> - samsung_usb2_phy_config in drivers/phy/samsung/
>>>
>>> This one is a good example - where do you see there compatibles with
>>> arbitrary numbers attached?
>> 
>> samsung_usb2_phy_of_match in drivers/phy/samsung/phy-samsung-usb2.c
>> 
>> There is a different compatible for each SoC variant. Each compatible selects a struct
>> containing
>> 
>> - A list of phys, each with custom power on and off functions
>> - A function which converts a rate to an arbitrary value to program into a register
>> 
>> This is further documented in Documentation/driver-api/phy/samsung-usb2.rst
> 
> Exactly, please follow this approach. Compatible is per different
> device, e.g. different SoC variant. Of course you could have different
> devices on same SoC, but "1" and "2" are not different devices.

(in this case they are)

>> 
>>>> - qmp_phy_init_tbl in drivers/phy/qualcomm/phy-qcom-qmp.c
>>>>
>>>> All of these drivers (and there are more)
>>>>
>>>> - Use a driver-internal struct to encode information specific to different device models.
>>>> - Select that struct based on the compatible
>>>
>>> Driver implementation. You can do it in many different ways. Does not
>>> matter for the bindings.
>> 
>> And because this both describes the hardware and is convenient to the implementation,
>> I have chosen this way.
>> 
>>>>
>>>> The other thing is that while the LS1046A SerDes are fairly generic, other SerDes of this
>>>> type have particular restructions on the clocks. E.g. on some SoCs, certain protocols
>>>> cannot be used together (even if they would otherwise be legal), and some protocols must
>>>> use particular PLLs (whereas in general there is no such restriction). There are also
>>>> some register fields which are required to program on some SoCs, and which are reserved
>>>> on others.
>>>
>>> Just to be clear, because you are quite unspecific here ("some
>>> protocols") - we talk about the same protocol programmed on two of these
>>> serdes (serdes-1 and serdes-2 how you call it). Does it use different
>>> registers?
>> 
>> Yes.
>> 
>>> Are some registers - for the same protocol - reserved in one version?
>> 
>> Yes.
>> 
>> For example, I excerpt part of the documentation for PCCR2 on the T4240:
>> 
>>> XFIa Configuration:
>>> XFIA_CFG Default value set by RCW configuration.
>>> This field must be 0 for SerDes 3 & 4
>>> All settings not shown are reserved
>>>
>>> 00 Disabled
>>> 01 x1 on Lane 3 to FM2 MAC 9
>> 
>> And here is part of the documentation for PCCR2 on the LS1046A:
>> 
>>> SATAa Configuration
>>> All others reserved
>>> NOTE: This field is not supported in every instance. The following table includes only
>>>       supported registers.
>>> Field supported in	Field not supported in
>>> SerDes1_PCCR2		—
>>> —			SerDes2_PCCR2
>>>
>>> 000b - Disabled
>>> 001b - x1 on Lane 3 (SerDes #2 only)
>> 
>> And here is part of the documentation for PCCRB on the LS1046A:
>> 
>>> XFIa Configuration
>>> All others reserved Default value set by RCW configuration.
>>>
>>> 000b - Disabled
>>> 010b - x1 on Lane 1 to XGMIIa (Serdes #1 only)
>> You may notice that
>> 
>> - For some SerDes on the same SoC, these fields are reserved
> 
> That all sounds like quite different devices, which indeed usually is
> described with different compatibles. Still "xxx-1" and "xxx-2" are not
> valid compatibles. You need to come with some more reasonable name
> describing them. Maybe the block has revision or different model/vendor.

There is none AFAIK. Maybe someone from NXP can comment (since there are many
undocumented registers).

>> - Between different SoCs, different protocols may be configured in different registers
>> - The same registers may be used for different protocols in different SoCs (though
>>   generally there are several general layouts)
> 
> Different SoCs give you different compatibles, so problem is solved and
> that's not exactly argument for this case.
> 
>> - Fields have particular values which must be programmed
>> 
>> In addition, the documentation also says
>> 
>>> Reserved registers and fields must be preserved on writes.
>> 
>> All of these combined issues make it so that we need detailed, serdes-specific
>> configuration. The easiest way to store this configuration is in the driver. This
>> is consistent with *many* existing phy implementations. I would like to write a
>> standard phy driver, not one twisted by unusual device tree requirements.
> 
> Sure.
> 
>> 
>>>>
>>>> There is, frankly, a large amount of variation between devices as implemented on different
>>>> SoCs. 
>>>
>>> This I don't get. You mean different SoCs have entirely different
>>> Serdes? Sure, no problem. We talk here only about this SoC, this
>>> serdes-1 and serdes-2.
>>>
>>>> Especially because (AIUI) drivers must remain compatible with old devicetrees, I
>>>> think using a specific compatible string is especially appropriate here. 
>>>
>>> This argument does not make any sense in case of new bindings and new
>>> drivers, unless you build on top of existing implementation. Anyway no
>>> one asks you to break existing bindings...
>> 
>> When there is a bug in the bindings how do you fix it? If I were to follow your suggested method, it would be difficult to determine the particular devices
>> 
>>>> It will give us
>>>> the ability to correct any implementation quirks as they are discovered (and I anticipate
>>>> that there will be) rather than having to determine everything up front.
>>>
>>> All the quirks can be also chosen by respective properties.
>> 
>> Quirks are *exactly* the sort of implementation-specific details that you were opposed to above.
>> 
>>> Anyway, "serdes-1" and "serdes-2" are not correct compatibles,
>> 
>> The compatibles suggested were "fsl,ls1046-serdes-1" and -2. As noted above, these are separate
>> devices which, while having many similarities, have different register layouts and protocol
>> support. They are *not* 100% compatible with each other. Would you require that clock drivers
>> for different SoCs use the same compatibles just because they had the same registers, even though
>> the clocks themselves had different functions and hierarchy?
> 
> You miss the point. Clock controllers on same SoC have different names
> used in compatibles. We do not describe them as "vendor,aa-clk-1" and
> "vendor,aa-clk-2".
> 
> Come with proper naming and entire discussion might be not valid
> (although with not perfect naming Rob might come with questions). I
> cannot propose the name because I don't know these hardware blocks and I
> do not have access to datasheet.
> 
> Other way, if any reasonable naming is not possible, could be also to
> describe the meaning of "-1" suffix, e.g. that it does not mean some
> index but a variant from specification.

The documentation refers to these devices as "SerDes1", "SerDes2", etc.

Wold you prefer something like

serdes0: phy@1ea0000 {
	compatible = "fsl,ls1046a-serdes";
	variant = <0>;
};

?

--Sean

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

* Re: [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver
  2022-06-18 15:52       ` Sean Anderson
@ 2022-06-20 18:53         ` Sean Anderson
  0 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-20 18:53 UTC (permalink / raw)
  To: Ioana Ciornei, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Jonathan Corbet, Kishon Vijay Abraham I,
	Krzysztof Kozlowski, Rob Herring, Vinod Koul, devicetree,
	linux-phy



On 6/18/22 11:52 AM, Sean Anderson wrote:
> Hi Ioana,
> 
> On 6/18/22 8:39 AM, Ioana Ciornei wrote:
>>>> Subject: [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver
>>>>
>>
>> Sorry for the previous HTML formatted email...
>>
>>>
>>> Hi Sean,
>>>
>>> I am very much interested in giving this driver a go on other SoCs as well
>>> but at the moment I am in vacation until mid next week.
> 
> Please let me know your results. I have documented how to add support for
> additional SoCs, so hopefully it should be fairly straightforward.
> 
>>>> This adds support for the "SerDes" devices found on various NXP QorIQ SoCs.
>>>> There may be up to four SerDes devices on each SoC, each supporting up to
>>>> eight lanes. Protocol support for each SerDes is highly heterogeneous, with
>>>> each SoC typically having a totally different selection of supported
>>>> protocols for each lane. Additionally, the SerDes devices on each SoC also
>>>> have differing support. One SerDes will typically support Ethernet on most
>>>> lanes, while the other will typically support PCIe on most lanes.
>>>>
>>>> There is wide hardware support for this SerDes. I have not done extensive
>>>> digging, but it seems to be used on almost every QorIQ device, including
>>>> the AMP and Layerscape series. Because each SoC typically has specific
>>>> instructions and exceptions for its SerDes, I have limited the initial
>>>> scope of this module to just the LS1046A. Additionally, I have only added
>>>> support for Ethernet protocols. There is not a great need for dynamic
>>>> reconfiguration for other protocols (SATA and PCIe handle rate changes in
>>>> hardware), so support for them may never be added.>
>>>> Nevertheless, I have tried to provide an obvious path for adding support
>>>> for other SoCs as well as other protocols. SATA just needs support for
>>>> configuring LNmSSCR0. PCIe may need to configure the equalization
>>>> registers. It also uses multiple lanes. I have tried to write the driver
>>>> with multi-lane support in mind, so there should not need to be any large
>>>> changes. Although there are 6 protocols supported, I have only tested SGMII
>>>> and XFI. The rest have been implemented as described in the datasheet.
>>>>
>>>> The PLLs are modeled as clocks proper. This lets us take advantage of the
>>>> existing clock infrastructure. I have not given the same treatment to the
>>>> lane "clocks" (dividers) because they need to be programmed in-concert with
>>>> the rest of the lane settings. One tricky thing is that the VCO (pll) rate
>>>> exceeds 2^32 (maxing out at around 5GHz). This will be a problem on 32-bit
>>>> platforms, since clock rates are stored as unsigned longs. To work around
>>>> this, the pll clock rate is generally treated in units of kHz.>
>>>> The PLLs are configured rather interestingly. Instead of the usual direct
>>>> programming of the appropriate divisors, the input and output clock rates
>>>> are selected directly. Generally, the only restriction is that the input
>>>> and output must be integer multiples of each other. This suggests some kind
>>>> of internal look-up table. The datasheets generally list out the supported
>>>> combinations explicitly, and not all input/output combinations are
>>>> documented. I'm not sure if this is due to lack of support, or due to an
>>>> oversight. If this becomes an issue, then some combinations can be
>>>> blacklisted (or whitelisted). This may also be necessary for other SoCs
>>>> which have more stringent clock requirements.
>>>
>>>
>>> I didn't get a change to go through the driver like I would like, but are you
>>> changing the PLL's rate at runtime?
> 
> Yes.
> 
>>> Do you take into consideration that a PLL might still be used by a PCIe or SATA
>>> lane (which is not described in the DTS) and deny its rate reconfiguration
>>> if this happens?
> 
> Yes.
> 
> When the device is probed, we go through the PCCRs and reserve any lane which is in
> use for a protocol we don't support (PCIe, SATA). We also get both PLL's rates
> exclusively and mark them as enabled.
> 
>>> I am asking this because when I added support for the Lynx 28G SerDes block what
>>> I did in order to support rate change depending of the plugged SFP module was
>>> just to change the PLL used by the lane, not the PLL rate itself.
>>> This is because I was afraid of causing more harm then needed for all the
>>> non-Ethernet lanes.
> 
> Yes. Since There is not much need for dynamic reconfiguration for other protocols,
> I suspect that non-ethernet support will not be added soon (or perhaps ever).
> 
>>>>
>>>> The general API call list for this PHY is documented under the driver-api
>>>> docs. I think this is rather standard, except that most driverts configure
>>>> the mode (protocol) at xlate-time. Unlike some other phys where e.g. PCIe
>>>> x4 will use 4 separate phys all configured for PCIe, this driver uses one
>>>> phy configured to use 4 lanes. This is because while the individual lanes
>>>> may be configured individually, the protocol selection acts on all lanes at
>>>> once. Additionally, the order which lanes should be configured in is
>>>> specified by the datasheet.  To coordinate this, lanes are reserved in
>>>> phy_init, and released in phy_exit.
>>>>
>>>> When getting a phy, if a phy already exists for those lanes, it is reused.
>>>> This is to make things like QSGMII work. Four MACs will all want to ensure
>>>> that the lane is configured properly, and we need to ensure they can all
>>>> call phy_init, etc. There is refcounting for phy_init and phy_power_on, so
>>>> the phy will only be powered on once. However, there is no refcounting for
>>>> phy_set_mode. A "rogue" MAC could set the mode to something non-QSGMII and
>>>> break the other MACs. Perhaps there is an opportunity for future
>>>> enhancement here.
>>>>
>>>> This driver was written with reference to the LS1046A reference manual.
>>>> However, it was informed by reference manuals for all processors with
>>>> MEMACs, especially the T4240 (which appears to have a "maxed-out"
>>>> configuration).
>>>>
>>>> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
>>>> ---
>>>> This appears to be the same underlying hardware as the Lynx 28G phy
>>>> added in 8f73b37cf3fb ("phy: add support for the Layerscape SerDes
>>>> 28G").
>>>
>>> The SerDes block used on L1046A (and a lot of other SoCs) is not the same
>>> one as the Lynx 28G that I submitted. The Lynx 28G block is only included
>>> on the LX2160A SoC and its variants.
> 
> OK. I looked over it quickly and it seemed to share many of the same registers.

I looked at the LX2160ARM today and it seems like the 28g phy is mostly a superset
of the 10g phy. With some careful attention to detail, I think these drivers could
be merged. At the very least, I think it should be possible to create some helper
functions for programming the common registers.

--Sean

>>> The SerDes block that you are adding a driver for is the Lynx 10G SerDes,
>>> which is why I would suggest renaming it to phy-fsl-lynx-10g.c.
> 
> Ah, thanks. Is this documented anywhere?
> 
> --Sean
> 

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

* Re: [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding
  2022-06-20 18:51                 ` Sean Anderson
@ 2022-06-21  7:12                   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 56+ messages in thread
From: Krzysztof Kozlowski @ 2022-06-21  7:12 UTC (permalink / raw)
  To: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur, netdev
  Cc: linux-kernel, linux-arm-kernel, Paolo Abeni, Russell King,
	Eric Dumazet, Kishon Vijay Abraham I, Krzysztof Kozlowski,
	Rob Herring, Vinod Koul, devicetree, linux-phy, Ioana Ciornei

On 20/06/2022 20:51, Sean Anderson wrote:
> On 6/20/22 2:21 PM, Krzysztof Kozlowski wrote:
>>>>> - samsung_usb2_phy_config in drivers/phy/samsung/
>>>>
>>>> This one is a good example - where do you see there compatibles with
>>>> arbitrary numbers attached?
>>>
>>> samsung_usb2_phy_of_match in drivers/phy/samsung/phy-samsung-usb2.c
>>>
>>> There is a different compatible for each SoC variant. Each compatible selects a struct
>>> containing
>>>
>>> - A list of phys, each with custom power on and off functions
>>> - A function which converts a rate to an arbitrary value to program into a register
>>>
>>> This is further documented in Documentation/driver-api/phy/samsung-usb2.rst
>>
>> Exactly, please follow this approach. Compatible is per different
>> device, e.g. different SoC variant. Of course you could have different
>> devices on same SoC, but "1" and "2" are not different devices.
> 
> (in this case they are)

In a meaning of descriptive compatible - it's not.

>>>
>>> - For some SerDes on the same SoC, these fields are reserved
>>
>> That all sounds like quite different devices, which indeed usually is
>> described with different compatibles. Still "xxx-1" and "xxx-2" are not
>> valid compatibles. You need to come with some more reasonable name
>> describing them. Maybe the block has revision or different model/vendor.
> 
> There is none AFAIK. Maybe someone from NXP can comment (since there are many
> undocumented registers).

Maybe it's also possible to invent some reasonable name based on
protocols supported? If nothing comes then please add a one-liner
comment explaining logic behind 1/2 suffix.

>>> The compatibles suggested were "fsl,ls1046-serdes-1" and -2. As noted above, these are separate
>>> devices which, while having many similarities, have different register layouts and protocol
>>> support. They are *not* 100% compatible with each other. Would you require that clock drivers
>>> for different SoCs use the same compatibles just because they had the same registers, even though
>>> the clocks themselves had different functions and hierarchy?
>>
>> You miss the point. Clock controllers on same SoC have different names
>> used in compatibles. We do not describe them as "vendor,aa-clk-1" and
>> "vendor,aa-clk-2".
>>
>> Come with proper naming and entire discussion might be not valid
>> (although with not perfect naming Rob might come with questions). I
>> cannot propose the name because I don't know these hardware blocks and I
>> do not have access to datasheet.
>>
>> Other way, if any reasonable naming is not possible, could be also to
>> describe the meaning of "-1" suffix, e.g. that it does not mean some
>> index but a variant from specification.
> 
> The documentation refers to these devices as "SerDes1", "SerDes2", etc.
> 
> Wold you prefer something like
> 
> serdes0: phy@1ea0000 {
> 	compatible = "fsl,ls1046a-serdes";
> 	variant = <0>;
> };

No, it's the same problem, just embeds compatible in different property.

Best regards,
Krzysztof

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

* Re: [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink
  2022-06-18 15:58         ` Sean Anderson
@ 2022-06-23 22:39           ` Sean Anderson
  2022-06-24  0:24             ` Russell King (Oracle)
  0 siblings, 1 reply; 56+ messages in thread
From: Sean Anderson @ 2022-06-23 22:39 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev,
	linux-kernel, linux-arm-kernel, Paolo Abeni, Eric Dumazet

Hi Russell,

On 6/18/22 11:58 AM, Sean Anderson wrote:
> Hi Russell,
> 
> On 6/18/22 4:22 AM, Russell King (Oracle) wrote:
>> On Fri, Jun 17, 2022 at 08:45:38PM -0400, Sean Anderson wrote:
>>> Hi Russell,
>>>
>>> Thanks for the quick response.
>>> ...
>>> Yes, I've been using the debug prints in phylink extensively as part of
>>> debugging :)
>>>
>>> In this case, I added a debug statement to phylink_resolve printing out
>>> cur_link_state, link_state.link, and pl->phy_state.link. I could see that
>>> the phy link state was up and the mac (pcs) state was down. By inspecting
>>> the PCS's registers, I determined that this was because AN had not completed
>>> (in particular, the link was up in BMSR). I believe that forcing in-band-status
>>> (by setting ovr_an_inband) shouldn't be necessary, but I was unable to get a link
>>> up on any interface without it. In particular, the pre-phylink implementation
>>> disabled PCS AN only for fixed links (which you can see in patch 23).
>>
>> I notice that prior to patch 23, the advertisment register was set to
>> 0x4001, but in phylink_mii_c22_pcs_encode_advertisement() we set it to
>> 0x0001 (bit 14 being the acknowledge bit from the PCS to the PHY, which
>> is normally managed by hardware.
>>
>> It may be worth testing whether setting bit 14 changes the behaviour.
> 
> Thanks for the tip. I'll try that out on Monday.

Well, I was playing around with this some more, and I found that I could enable
it if I set one of the 10G lanes to SGMII. Not sure what's going on there. It's
possible one of the lanes is mismatched, but I'm still looking into it.

---

How is rate adaptation in the phy supposed to work? One of the 10G interfaces on
the RDB is hooked up to an AQR113 which can adapt rates below 10G to XFI using
pause frames. This is nice and all, but the problem is that phylink_get_linkmodes
sees that we're using PHY_INTERFACE_MODE_10GKR and doesn't add any of the lower
link speeds (just MAC_10000). This results in ethtool output of

Settings for eth6:
	Supported ports: [  ]
	Supported link modes:   10000baseT/Full
	                        10000baseKX4/Full
	                        10000baseKR/Full
	Supported pause frame use: Symmetric Receive-only
	Supports auto-negotiation: Yes
	Supported FEC modes: Not reported
	Advertised link modes:  10000baseT/Full
	                        10000baseKX4/Full
	                        10000baseKR/Full
	Advertised pause frame use: Symmetric Receive-only
	Advertised auto-negotiation: Yes
	Advertised FEC modes: Not reported
	Link partner advertised link modes:  10baseT/Half 10baseT/Full
	                                     100baseT/Half 100baseT/Full
	Link partner advertised pause frame use: Symmetric
	Link partner advertised auto-negotiation: Yes
	Link partner advertised FEC modes: Not reported
	Speed: Unknown!
	Duplex: Unknown! (255)
	Auto-negotiation: on
	Port: MII
	PHYAD: 0
	Transceiver: external
        Current message level: 0x00002037 (8247)
                               drv probe link ifdown ifup hw
	Link detected: yes

The speed and duplex are "Unknown!" because the negotiated link mode (100Base-TX)
doesn't intersect with the advertised link modes (10000Base-T etc). This is
currently using genphy; does there need to be driver support for this sort of thing?
Should the correct speed even be reported here? The MAC and PCS still need to be
configured for XFI.

Another problem is that the rate adaptation is supposed to happen with pause frames.
Unfortunately, pause frames are disabled:

Pause parameters for eth6:
Autonegotiate:	on
RX:		off
TX:		off
RX negotiated: on
TX negotiated: on

Maybe this is because phylink_mii_c45_pcs_get_state doesn't check for pause modes?
The far end link partner of course doesn't necessarily support pause frames. I tried
this with managed = "phy" and "in-band-status" and it didn't seem to make a difference.

--Sean

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

* Re: [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink
  2022-06-23 22:39           ` Sean Anderson
@ 2022-06-24  0:24             ` Russell King (Oracle)
  2022-06-27 15:17               ` Sean Anderson
  0 siblings, 1 reply; 56+ messages in thread
From: Russell King (Oracle) @ 2022-06-24  0:24 UTC (permalink / raw)
  To: Sean Anderson
  Cc: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev,
	linux-kernel, linux-arm-kernel, Paolo Abeni, Eric Dumazet

On Thu, Jun 23, 2022 at 06:39:08PM -0400, Sean Anderson wrote:
> Hi Russell,
> 
> On 6/18/22 11:58 AM, Sean Anderson wrote:
> > Hi Russell,
> > 
> > On 6/18/22 4:22 AM, Russell King (Oracle) wrote:
> >> On Fri, Jun 17, 2022 at 08:45:38PM -0400, Sean Anderson wrote:
> >>> Hi Russell,
> >>>
> >>> Thanks for the quick response.
> >>> ...
> >>> Yes, I've been using the debug prints in phylink extensively as part of
> >>> debugging :)
> >>>
> >>> In this case, I added a debug statement to phylink_resolve printing out
> >>> cur_link_state, link_state.link, and pl->phy_state.link. I could see that
> >>> the phy link state was up and the mac (pcs) state was down. By inspecting
> >>> the PCS's registers, I determined that this was because AN had not completed
> >>> (in particular, the link was up in BMSR). I believe that forcing in-band-status
> >>> (by setting ovr_an_inband) shouldn't be necessary, but I was unable to get a link
> >>> up on any interface without it. In particular, the pre-phylink implementation
> >>> disabled PCS AN only for fixed links (which you can see in patch 23).
> >>
> >> I notice that prior to patch 23, the advertisment register was set to
> >> 0x4001, but in phylink_mii_c22_pcs_encode_advertisement() we set it to
> >> 0x0001 (bit 14 being the acknowledge bit from the PCS to the PHY, which
> >> is normally managed by hardware.
> >>
> >> It may be worth testing whether setting bit 14 changes the behaviour.
> > 
> > Thanks for the tip. I'll try that out on Monday.
> 
> Well, I was playing around with this some more, and I found that I could enable
> it if I set one of the 10G lanes to SGMII. Not sure what's going on there. It's
> possible one of the lanes is mismatched, but I'm still looking into it.
> 
> ---
> 
> How is rate adaptation in the phy supposed to work? One of the 10G interfaces on
> the RDB is hooked up to an AQR113 which can adapt rates below 10G to XFI using
> pause frames.

Rate adaption support isn't something that phylink officially supports.
It can be bodged around (and some drivers do) but that's the official
line - there is no code in phylink to make it work.

For example, if you have a PHY that's doing rate adaption, and the PHY
reports what has been negotiated on the media side. That gets reported
back to the PCS and MAC. The only way these blocks can tell that there's
something going on is if they say "hey, but the link to the PHY is
operating at 10G and the media speed is 100M, so something fishy is
going on, the PHY must be doing rate adaption."

That's the bottom line to this - phylink doesn't yet support rate
adaption by any of the blocks - mainly because there is no way for
any of those blocks to indicate that they're doing rate adaption.

The implementation of phylink_generic_validate() assumes there is no
rate adaption (as per the current design of phylink).

The reason phylink_generic_validate() has come into existence recently
is to (1) get rid of the numerous almost identical but buggy
implementations of the validate() method, and (2) to eventually allow
me to get rid of the validate() method. The validate() method is not
very well suited to systems with rate adaption - as validate() stands,
every MAC today that _could_ be connected with something that does rate
adaption needs to have special handling in that method when that is
true - that clearly isn't a good idea when it's dependent on the
properties of the devices towards the media from the MAC.

Ocelot does make rate adaption work by doing exactly this - it has its
own validate() method that returns all the link modes that it wishes
the system to support, and it ignores some of what phylink communicates
via the link_up() callbacks such as rx_pause. This means this MAC driver
wouldn't behave correctly as a system if rate adaption wasn't present.


Now, the thing about rate adaption is there are several different ways
to do it - and Marvell 88x3310 illustrates them both, because this PHY
supports rate adaption but depending on whether the PHY has MACSEC
hardware support or not depende on its behaviour:

- If no MACSEC, then the PHY requires that the MAC paces the rate at
  which packets are sent, otherwise the PHYs FIFOs will overflow.
  Therefore, the MAC must know: (1) the speed of the media side, and
  (2) that the PHY requires this behaviour. Marvell even go as far as
  stating that the way to achieve this is to extend the IPG in the MACs
  settings.

- If MACSEC, then the PHY sends pause frames back to the MAC to rate
  limit the packet rate from the MAC. Therefore, the MAC must accept
  pause frames to throttle the transmit rate whether or not pause
  frames were negotiated on the media side.

So, doing this right, you need knowledge of the rate adaption
implementation - there isn't a "generic" solution to this. It isn't
just a case of "allow all speeds at the media side at or below PHY
interface speed" although that is part of it. (More on this below.)

> This is nice and all, but the problem is that phylink_get_linkmodes
> sees that we're using PHY_INTERFACE_MODE_10GKR and doesn't add any
> of the lower link speeds (just MAC_10000).

Do you really have a 10GBASE-KR link - a backplane link? This has
negotiation embedded in it. Or do you have a link that is using the
10GBASE-R protocol? (Please don't use PHY_INTERFACE_MODE_10GKR unless
you really have a 10GBASE-KR link as defined by 802.3).

> This results in ethtool output of
> 
> Settings for eth6:
> 	Supported ports: [  ]
> 	Supported link modes:   10000baseT/Full
> 	                        10000baseKX4/Full
> 	                        10000baseKR/Full
> 	Supported pause frame use: Symmetric Receive-only
> 	Supports auto-negotiation: Yes
> 	Supported FEC modes: Not reported
> 	Advertised link modes:  10000baseT/Full
> 	                        10000baseKX4/Full
> 	                        10000baseKR/Full
> 	Advertised pause frame use: Symmetric Receive-only
> 	Advertised auto-negotiation: Yes
> 	Advertised FEC modes: Not reported
> 	Link partner advertised link modes:  10baseT/Half 10baseT/Full
> 	                                     100baseT/Half 100baseT/Full
> 	Link partner advertised pause frame use: Symmetric
> 	Link partner advertised auto-negotiation: Yes
> 	Link partner advertised FEC modes: Not reported
> 	Speed: Unknown!
> 	Duplex: Unknown! (255)
> 	Auto-negotiation: on
> 	Port: MII
> 	PHYAD: 0
> 	Transceiver: external
>         Current message level: 0x00002037 (8247)
>                                drv probe link ifdown ifup hw
> 	Link detected: yes
> 
> The speed and duplex are "Unknown!" because the negotiated link mode (100Base-TX)
> doesn't intersect with the advertised link modes (10000Base-T etc). This is
> currently using genphy; does there need to be driver support for this sort of thing?

Without knowing whether this is a clause 22 or clause 45 PHY, I'd just
be guessing, but...

genphy's C45 support is rudimentary and should not be used.
genphy's C22 support is better for basic control of PHYs but should not
be used if there's a more specific driver.

If this is a C22 PHY, I'm surprised that it managed to link with its
partner - we should have cleared anything but the 10000M modes in the
PHY which should have caused the media side autonegotiation to fail.

However, with the Ocelot-style workaround I mentioned above, that would
allow the 100M speeds to be advertised, and phylib would then be able
to resolve them to the appropriate speed/duplex. I don't condone doing
that though, I'd prefer a proper solution to this problem.

> Should the correct speed even be reported here? The MAC and PCS still need to be
> configured for XFI.
> 
> Another problem is that the rate adaptation is supposed to happen with pause frames.
> Unfortunately, pause frames are disabled:
> 
> Pause parameters for eth6:
> Autonegotiate:	on
> RX:		off
> TX:		off
> RX negotiated: on
> TX negotiated: on

I think you're misreading that - don't worry, I don't think you're the
only one.

"Autonegotiate" is the value of ethtool's pauseparam "autoneg" setting
which determines whether the resutl of autonegotiation is used or
whether manual settings are used.

"RX" and "TX" are the manual settings, which will force pause frame
reception and transmission gating when "Autonegotiate" is off. These
can be read-modify-written (and are by ethtool) so it's important
that they return what was previously configured, not what the hardware
is doing. See do_spause() in the ethtool source code.

"RX negotiated" and "TX negotiated" are ethtool's own derivation from
our and link-partner advertisements and in no way reflect what the
hardware is actually doing. These reflect what was negotiated on the
media between the PHYs.

See dump_pause() in the ethtool source code for the function that
produces the output you quoted above.

Phylink's "Link is Up" message gives the details for the link - the
speed and duplex will be the media side of the link (which is what gets
passed in all the link_up() methods). The pause settings come from the
media side negotiation if pause autoneg is enabled, otherwise they come
from the pauseparam forced modes. I think this should only ever report
the media-negotiated settings.

If we need support for rate adaption with pause frames, then you are
right that we need the MAC to be open to receive those frames, and
right now, as I said above, there is no support in phylink at present
to make that happen. I'm not saying there shouldn't be, I'm just saying
that's how it is today.

In order to do this, we would need to have some way of knowing that:
(a) the PHY is a rate adapting PHY (which means it must not use genphy.)
(b) the PHY is will send pause frames towards the MAC to pace it.

This would need to be added to phylib, and then phylink can query
phylib for that information and, when telling the MAC that the link
is up, also enable rx_pause.

The same is true at the PCS level - we don't have any way to know if
a PCS is doing rate adaption, so until we have a way to know that,
phylink can't enable rx_pause.

There is one final issue that needs to be considered - what if the
PHY is a rate adapting PHY which sends pause frames, but it has been
coupled with a MAC that doesn't have support to act on those pause
frames? Do we print a warning? Do we refuse to bring the link up?
Do we fall back to requiring the MAC to increase the IPG? What if the
MAC isn't capable of increasing the IPG? How do we tell the MAC to
increase the IPG, another flag in its link_up() method?

> Maybe this is because phylink_mii_c45_pcs_get_state doesn't check for pause modes?

With a 10GBASE-R PCS, there is no in-band status on the link, and so
there is no communication of pause frame negotiation status to the
PCS - meaning, there is no way to read it from the PCS.

Let me be clear about this: this is a shortcoming of phylink, but
phylink had to start somewhere, and all the hardware I have does not
support rate adaption.

I'd like this problem to get solved - I have some experimental patches
that allow a PCS to say "hey, I'm doing rate adaption, don't bother
with the MAC validation" but I get the feeling that's not really
sufficient.

Anyway, I'm afraid it's very late here, so I can't put any more
thought into this tonight, but I hope the above is at least helpful
and gives some ideas what needs to be done to solve this.

Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

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

* Re: [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink
  2022-06-24  0:24             ` Russell King (Oracle)
@ 2022-06-27 15:17               ` Sean Anderson
  0 siblings, 0 replies; 56+ messages in thread
From: Sean Anderson @ 2022-06-27 15:17 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: David S . Miller, Jakub Kicinski, Madalin Bucur, netdev,
	linux-kernel, linux-arm-kernel, Paolo Abeni, Eric Dumazet



On 6/23/22 8:24 PM, Russell King (Oracle) wrote:
> On Thu, Jun 23, 2022 at 06:39:08PM -0400, Sean Anderson wrote:
>> Hi Russell,
>> 
>> On 6/18/22 11:58 AM, Sean Anderson wrote:
>> > Hi Russell,
>> > 
>> > On 6/18/22 4:22 AM, Russell King (Oracle) wrote:
>> >> On Fri, Jun 17, 2022 at 08:45:38PM -0400, Sean Anderson wrote:
>> >>> Hi Russell,
>> >>>
>> >>> Thanks for the quick response.
>> >>> ...
>> >>> Yes, I've been using the debug prints in phylink extensively as part of
>> >>> debugging :)
>> >>>
>> >>> In this case, I added a debug statement to phylink_resolve printing out
>> >>> cur_link_state, link_state.link, and pl->phy_state.link. I could see that
>> >>> the phy link state was up and the mac (pcs) state was down. By inspecting
>> >>> the PCS's registers, I determined that this was because AN had not completed
>> >>> (in particular, the link was up in BMSR). I believe that forcing in-band-status
>> >>> (by setting ovr_an_inband) shouldn't be necessary, but I was unable to get a link
>> >>> up on any interface without it. In particular, the pre-phylink implementation
>> >>> disabled PCS AN only for fixed links (which you can see in patch 23).
>> >>
>> >> I notice that prior to patch 23, the advertisment register was set to
>> >> 0x4001, but in phylink_mii_c22_pcs_encode_advertisement() we set it to
>> >> 0x0001 (bit 14 being the acknowledge bit from the PCS to the PHY, which
>> >> is normally managed by hardware.
>> >>
>> >> It may be worth testing whether setting bit 14 changes the behaviour.
>> > 
>> > Thanks for the tip. I'll try that out on Monday.
>> 
>> Well, I was playing around with this some more, and I found that I could enable
>> it if I set one of the 10G lanes to SGMII. Not sure what's going on there. It's
>> possible one of the lanes is mismatched, but I'm still looking into it.
>> 
>> ---
>> 
>> How is rate adaptation in the phy supposed to work? One of the 10G interfaces on
>> the RDB is hooked up to an AQR113 which can adapt rates below 10G to XFI using
>> pause frames.
> 
> Rate adaption support isn't something that phylink officially supports.
> It can be bodged around (and some drivers do) but that's the official
> line - there is no code in phylink to make it work.

Ah, that's unfortunate. I removed some Aquantia-specific code, but I may
have to add it back...

> For example, if you have a PHY that's doing rate adaption, and the PHY
> reports what has been negotiated on the media side. That gets reported
> back to the PCS and MAC. The only way these blocks can tell that there's
> something going on is if they say "hey, but the link to the PHY is
> operating at 10G and the media speed is 100M, so something fishy is
> going on, the PHY must be doing rate adaption."
> 
> That's the bottom line to this - phylink doesn't yet support rate
> adaption by any of the blocks - mainly because there is no way for
> any of those blocks to indicate that they're doing rate adaption.
> 
> The implementation of phylink_generic_validate() assumes there is no
> rate adaption (as per the current design of phylink).
> 
> The reason phylink_generic_validate() has come into existence recently
> is to (1) get rid of the numerous almost identical but buggy
> implementations of the validate() method, and (2) to eventually allow
> me to get rid of the validate() method. The validate() method is not
> very well suited to systems with rate adaption - as validate() stands,
> every MAC today that _could_ be connected with something that does rate
> adaption needs to have special handling in that method when that is
> true - that clearly isn't a good idea when it's dependent on the
> properties of the devices towards the media from the MAC.
> 
> Ocelot does make rate adaption work by doing exactly this - it has its
> own validate() method that returns all the link modes that it wishes
> the system to support, and it ignores some of what phylink communicates
> via the link_up() callbacks such as rx_pause. This means this MAC driver
> wouldn't behave correctly as a system if rate adaption wasn't present.
> 
> 
> Now, the thing about rate adaption is there are several different ways
> to do it - and Marvell 88x3310 illustrates them both, because this PHY
> supports rate adaption but depending on whether the PHY has MACSEC
> hardware support or not depende on its behaviour:
> 
> - If no MACSEC, then the PHY requires that the MAC paces the rate at
>   which packets are sent, otherwise the PHYs FIFOs will overflow.
>   Therefore, the MAC must know: (1) the speed of the media side, and
>   (2) that the PHY requires this behaviour. Marvell even go as far as
>   stating that the way to achieve this is to extend the IPG in the MACs
>   settings.
> 
> - If MACSEC, then the PHY sends pause frames back to the MAC to rate
>   limit the packet rate from the MAC. Therefore, the MAC must accept
>   pause frames to throttle the transmit rate whether or not pause
>   frames were negotiated on the media side.
> 
> So, doing this right, you need knowledge of the rate adaption
> implementation - there isn't a "generic" solution to this. It isn't
> just a case of "allow all speeds at the media side at or below PHY
> interface speed" although that is part of it. (More on this below.)



>> This is nice and all, but the problem is that phylink_get_linkmodes
>> sees that we're using PHY_INTERFACE_MODE_10GKR and doesn't add any
>> of the lower link speeds (just MAC_10000).
> 
> Do you really have a 10GBASE-KR link - a backplane link? This has
> negotiation embedded in it. Or do you have a link that is using the
> 10GBASE-R protocol? (Please don't use PHY_INTERFACE_MODE_10GKR unless
> you really have a 10GBASE-KR link as defined by 802.3).

 Sorry, that was a typo.

>> This results in ethtool output of
>> 
>> Settings for eth6:
>> 	Supported ports: [  ]
>> 	Supported link modes:   10000baseT/Full
>> 	                        10000baseKX4/Full
>> 	                        10000baseKR/Full
>> 	Supported pause frame use: Symmetric Receive-only
>> 	Supports auto-negotiation: Yes
>> 	Supported FEC modes: Not reported
>> 	Advertised link modes:  10000baseT/Full
>> 	                        10000baseKX4/Full
>> 	                        10000baseKR/Full
>> 	Advertised pause frame use: Symmetric Receive-only
>> 	Advertised auto-negotiation: Yes
>> 	Advertised FEC modes: Not reported
>> 	Link partner advertised link modes:  10baseT/Half 10baseT/Full
>> 	                                     100baseT/Half 100baseT/Full
>> 	Link partner advertised pause frame use: Symmetric
>> 	Link partner advertised auto-negotiation: Yes
>> 	Link partner advertised FEC modes: Not reported
>> 	Speed: Unknown!
>> 	Duplex: Unknown! (255)
>> 	Auto-negotiation: on
>> 	Port: MII
>> 	PHYAD: 0
>> 	Transceiver: external
>>         Current message level: 0x00002037 (8247)
>>                                drv probe link ifdown ifup hw
>> 	Link detected: yes
>> 
>> The speed and duplex are "Unknown!" because the negotiated link mode (100Base-TX)
>> doesn't intersect with the advertised link modes (10000Base-T etc). This is
>> currently using genphy; does there need to be driver support for this sort of thing?
> 
> Without knowing whether this is a clause 22 or clause 45 PHY, I'd just
> be guessing, but...

It's a c45 phy.

> genphy's C45 support is rudimentary and should not be used.

Fun. TIL

> genphy's C22 support is better for basic control of PHYs but should not
> be used if there's a more specific driver.
> 
> If this is a C22 PHY, I'm surprised that it managed to link with its
> partner - we should have cleared anything but the 10000M modes in the
> PHY which should have caused the media side autonegotiation to fail.

I looked into this further, and it seems like the phy has an "Autonegotiation
Vendor Provisioning" register. In this register there is a "User Provided
Autonegotiation Data" field which defaults to 0. This causes "the PHY [to]
construct the correct autonegotiation words based on the provisioned values."
AKA the programmed advertisement is ignored. This is very convenient for me
because otherwise the link would not have come up :)

> However, with the Ocelot-style workaround I mentioned above, that would
> allow the 100M speeds to be advertised, and phylib would then be able
> to resolve them to the appropriate speed/duplex. I don't condone doing
> that though, I'd prefer a proper solution to this problem.
> 
>> Should the correct speed even be reported here? The MAC and PCS still need to be
>> configured for XFI.
>> 
>> Another problem is that the rate adaptation is supposed to happen with pause frames.
>> Unfortunately, pause frames are disabled:
>> 
>> Pause parameters for eth6:
>> Autonegotiate:	on
>> RX:		off
>> TX:		off
>> RX negotiated: on
>> TX negotiated: on
> 
> I think you're misreading that - don't worry, I don't think you're the
> only one.
> 
> "Autonegotiate" is the value of ethtool's pauseparam "autoneg" setting
> which determines whether the resutl of autonegotiation is used or
> whether manual settings are used.
> 
> "RX" and "TX" are the manual settings, which will force pause frame
> reception and transmission gating when "Autonegotiate" is off. These
> can be read-modify-written (and are by ethtool) so it's important
> that they return what was previously configured, not what the hardware
> is doing. See do_spause() in the ethtool source code.

Ah, I missed that these were from link_config and not link_status.

> "RX negotiated" and "TX negotiated" are ethtool's own derivation from
> our and link-partner advertisements and in no way reflect what the
> hardware is actually doing. These reflect what was negotiated on the
> media between the PHYs.
> 
> See dump_pause() in the ethtool source code for the function that
> produces the output you quoted above.
> 
> Phylink's "Link is Up" message gives the details for the link - the
> speed and duplex will be the media side of the link (which is what gets
> passed in all the link_up() methods). The pause settings come from the
> media side negotiation if pause autoneg is enabled, otherwise they come
> from the pauseparam forced modes. I think this should only ever report
> the media-negotiated settings.

[    8.029403] fsl_dpaa_mac 1af0000.ethernet eth6: Link is Up - 10Gbps/Full - flow control off

So the pause parameters are still off.

> If we need support for rate adaption with pause frames, then you are
> right that we need the MAC to be open to receive those frames, and
> right now, as I said above, there is no support in phylink at present
> to make that happen. I'm not saying there shouldn't be, I'm just saying
> that's how it is today.
> 
> In order to do this, we would need to have some way of knowing that:
> (a) the PHY is a rate adapting PHY (which means it must not use genphy.)
> (b) the PHY is will send pause frames towards the MAC to pace it.
> 
> This would need to be added to phylib, and then phylink can query
> phylib for that information and, when telling the MAC that the link
> is up, also enable rx_pause.
> 
> The same is true at the PCS level - we don't have any way to know if
> a PCS is doing rate adaption, so until we have a way to know that,
> phylink can't enable rx_pause.
> 
> There is one final issue that needs to be considered - what if the
> PHY is a rate adapting PHY which sends pause frames, but it has been
> coupled with a MAC that doesn't have support to act on those pause
> frames? Do we print a warning? Do we refuse to bring the link up?
> Do we fall back to requiring the MAC to increase the IPG? What if the
> MAC isn't capable of increasing the IPG? How do we tell the MAC to
> increase the IPG, another flag in its link_up() method?

I'd say that failing to bring the link up would probably be the most
reasonable thing to do in most cases. The IPG would need to be increased
to seriously unusual levels for correct adaptation. DPAA can't have an IPG
over 252 bytes, and I imagine that that's a fairly common restriction (though
since you bring it up as an option, there probably exists a MAC supporting the
10 KiB IPGs necessary for 1G over 10G).

>> Maybe this is because phylink_mii_c45_pcs_get_state doesn't check for pause modes?
> 
> With a 10GBASE-R PCS, there is no in-band status on the link, and so
> there is no communication of pause frame negotiation status to the
> PCS - meaning, there is no way to read it from the PCS.

Yup. I tried enabling autonegotiation in the PCS but got nothing.

> Let me be clear about this: this is a shortcoming of phylink, but
> phylink had to start somewhere, and all the hardware I have does not
> support rate adaption.
> 
> I'd like this problem to get solved - I have some experimental patches
> that allow a PCS to say "hey, I'm doing rate adaption, don't bother
> with the MAC validation" but I get the feeling that's not really
> sufficient.
> 
> Anyway, I'm afraid it's very late here, so I can't put any more
> thought into this tonight, but I hope the above is at least helpful
> and gives some ideas what needs to be done to solve this.

I really appreciate it. This has cleared things up for me.

--Sean

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

* Re: [PATCH net-next 02/28] dt-bindings: net: fman: Add additional interface properties
  2022-06-19 10:33       ` Krzysztof Kozlowski
@ 2022-06-27 23:05         ` Rob Herring
  0 siblings, 0 replies; 56+ messages in thread
From: Rob Herring @ 2022-06-27 23:05 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Sean Anderson, David S . Miller, Jakub Kicinski, Madalin Bucur,
	netdev, linux-kernel, linux-arm-kernel, Paolo Abeni,
	Russell King, Eric Dumazet, Krzysztof Kozlowski, devicetree

On Sun, Jun 19, 2022 at 12:33:22PM +0200, Krzysztof Kozlowski wrote:
> On 18/06/2022 17:55, Sean Anderson wrote:
> > Hi Krzysztof,
> > 
> > On 6/17/22 9:16 PM, Krzysztof Kozlowski wrote:
> >> On 17/06/2022 13:32, Sean Anderson wrote:
> >>> At the moment, MEMACs are configured almost completely based on the
> >>> phy-connection-type. That is, if the phy interface is RGMII, it assumed
> >>> that RGMII is supported. For some interfaces, it is assumed that the
> >>> RCW/bootloader has set up the SerDes properly. The actual link state is
> >>> never reported.
> >>>
> >>> To address these shortcomings, the driver will need additional
> >>> information. First, it needs to know how to access the PCS/PMAs (in
> >>> order to configure them and get the link status). The SGMII PCS/PMA is
> >>> the only currently-described PCS/PMA. Add the XFI and QSGMII PCS/PMAs as
> >>> well. The XFI (and 1GBase-KR) PCS/PMA is a c45 "phy" which sits on the
> >>> same MDIO bus as SGMII PCS/PMA. By default they will have conflicting
> >>> addresses, but they are also not enabled at the same time by default.
> >>> Therefore, we can let the default address for the XFI PCS/PMA be the
> >>> same as for SGMII. This will allow for backwards-compatibility.
> >>>
> >>> QSGMII, however, cannot work with the current binding. This is because
> >>> the QSGMII PCS/PMAs are only present on one MAC's MDIO bus. At the
> >>> moment this is worked around by having every MAC write to the PCS/PMA
> >>> addresses (without checking if they are present). This only works if
> >>> each MAC has the same configuration, and only if we don't need to know
> >>> the status. Because the QSGMII PCS/PMA will typically be located on a
> >>> different MDIO bus than the MAC's SGMII PCS/PMA, there is no fallback
> >>> for the QSGMII PCS/PMA.
> >>>
> >>> MEMACs (across all SoCs) support the following protocols:
> >>>
> >>> - MII
> >>> - RGMII
> >>> - SGMII, 1000Base-X, and 1000Base-KX
> >>> - 2500Base-X (aka 2.5G SGMII)
> >>> - QSGMII
> >>> - 10GBase-R (aka XFI) and 10GBase-KR
> >>> - XAUI and HiGig
> >>>
> >>> Each line documents a set of orthogonal protocols (e.g. XAUI is
> >>> supported if and only if HiGig is supported). Additionally,
> >>>
> >>> - XAUI implies support for 10GBase-R
> >>> - 10GBase-R is supported if and only if RGMII is not supported
> >>> - 2500Base-X implies support for 1000Base-X
> >>> - MII implies support for RGMII
> >>>
> >>> To switch between different protocols, we must reconfigure the SerDes.
> >>> This is done by using the standard phys property. We can also use it to
> >>> validate whether different protocols are supported (e.g. using
> >>> phy_validate). This will work for serial protocols, but not RGMII or
> >>> MII. Additionally, we still need to be compatible when there is no
> >>> SerDes.
> >>>
> >>> While we can detect 10G support by examining the port speed (as set by
> >>> fsl,fman-10g-port), we cannot determine support for any of the other
> >>> protocols based on the existing binding. In fact, the binding works
> >>> against us in some respects, because pcsphy-handle is required even if
> >>> there is no possible PCS/PMA for that MAC. To allow for backwards-
> >>> compatibility, we use a boolean-style property for RGMII (instead of
> >>> presence/absence-style). When the property for RGMII is missing, we will
> >>> assume that it is supported. The exception is MII, since no existing
> >>> device trees use it (as far as I could tell).
> >>>
> >>> Unfortunately, QSGMII support will be broken for old device trees. There
> >>> is nothing we can do about this because of the PCS/PMA situation (as
> >>> described above).
> >>>
> >>> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
> >>
> >> Thanks for the patch but you add too many new properties. The file
> >> should be converted to YAML/DT schema first.
> > 
> > Perhaps. However, conversion to yaml is a non-trivial task, especially for
> > a complicated binding such as this one. I am more than happy to rework this
> > patch to be based on a yaml conversion, but I do not have the bandwidth to
> > do so myself.
> 
> I understand. Although since 2020  - since when we expect the bindings
> to be in YAML - this file grew by 6 properties, because each person
> extends it instead of converting. Each person uses the same excuse...
> 
> You add here 5 more, so it would be 11 new properties in total.
> 
> > 
> > If you have any comments on the binding changes themselves, that would be
> > much appreciated.
> 
> Maybe Rob will ack it, but for me the change is too big to be accepted
> in TXT, so no from me.

Above my threshold for not first converting too. Really, I'm pretty 
close to saying no .txt file changes at all. Maybe compatible string 
updates only, people should be rewarded for not changing their h/w.

Rob

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

end of thread, other threads:[~2022-06-27 23:05 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-17 20:32 [PATCH net-next 00/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 01/28] dt-bindings: phy: Add QorIQ SerDes binding Sean Anderson
2022-06-17 23:27   ` Rob Herring
2022-06-18  1:15   ` Krzysztof Kozlowski
2022-06-18  3:38     ` Sean Anderson
2022-06-19 11:24       ` Krzysztof Kozlowski
2022-06-19 15:53         ` Sean Anderson
2022-06-20 10:54           ` Krzysztof Kozlowski
2022-06-20 17:19             ` Sean Anderson
2022-06-20 18:21               ` Krzysztof Kozlowski
2022-06-20 18:51                 ` Sean Anderson
2022-06-21  7:12                   ` Krzysztof Kozlowski
2022-06-17 20:32 ` [PATCH net-next 02/28] dt-bindings: net: fman: Add additional interface properties Sean Anderson
2022-06-18  1:16   ` Krzysztof Kozlowski
2022-06-18 15:55     ` Sean Anderson
2022-06-19 10:33       ` Krzysztof Kozlowski
2022-06-27 23:05         ` Rob Herring
2022-06-17 20:32 ` [PATCH net-next 03/28] phy: fsl: Add QorIQ SerDes driver Sean Anderson
2022-06-18  3:02   ` kernel test robot
     [not found]   ` <GV1PR04MB905598703F5E9A0989662EFDE0AE9@GV1PR04MB9055.eurprd04.prod.outlook.com>
2022-06-18 12:39     ` Ioana Ciornei
2022-06-18 15:52       ` Sean Anderson
2022-06-20 18:53         ` Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 04/28] net: fman: Convert to SPDX identifiers Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 05/28] net: fman: Don't pass comm_mode to enable/disable Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 06/28] net: fman: Store en/disable in mac_device instead of mac_priv_s Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 07/28] net: fman: dtsec: Always gracefully stop/start Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 08/28] net: fman: Get PCS node in per-mac init Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 09/28] net: fman: Store initialization function in match data Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 10/28] net: fman: Move struct dev to mac_device Sean Anderson
2022-06-18  3:57   ` kernel test robot
2022-06-17 20:32 ` [PATCH net-next 11/28] net: fman: Configure fixed link in memac_initialization Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 12/28] net: fman: Export/rename some common functions Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 13/28] net: fman: memac: Use params instead of priv for max_speed Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 14/28] net: fman: Move initialization to mac-specific files Sean Anderson
2022-06-17 20:32 ` [PATCH net-next 15/28] net: fman: Mark mac methods static Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 16/28] net: fman: Inline several functions into initialization Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 17/28] net: fman: Remove internal_phy_node from params Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 18/28] net: fman: Map the base address once Sean Anderson
2022-06-18  2:01   ` kernel test robot
2022-06-17 20:33 ` [PATCH net-next 19/28] net: fman: Pass params directly to mac init Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 20/28] net: fman: Use mac_dev for some params Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 21/28] net: fman: Clean up error handling Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 22/28] net: fman: memac: Add serdes support Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 23/28] net: fman: memac: Use lynx pcs driver Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 24/28] net: dpaa: Use mac_dev variable in dpaa_netdev_init Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 25/28] [RFC] net: dpaa: Convert to phylink Sean Anderson
2022-06-17 22:01   ` Russell King (Oracle)
2022-06-18  0:45     ` Sean Anderson
2022-06-18  8:22       ` Russell King (Oracle)
2022-06-18 15:58         ` Sean Anderson
2022-06-23 22:39           ` Sean Anderson
2022-06-24  0:24             ` Russell King (Oracle)
2022-06-27 15:17               ` Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 26/28] arm64: dts: ls1046ardb: Add serdes bindings Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 27/28] arm64: dts: ls1046a: Add SerDes bindings Sean Anderson
2022-06-17 20:33 ` [PATCH net-next 28/28] arm64: dts: ls1046a: Specify which MACs support RGMII Sean Anderson

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