Commit 5cacb2c7 authored by David S. Miller's avatar David S. Miller

Merge branch 'dpaa-phylink'

Sean Anderson says:

====================
net: dpaa: Convert to phylink

This series converts the DPAA driver to phylink.

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.

All mac drivers have now been converted. I would greatly appreciate if
anyone has T-series or P-series boards they can test/debug this series
on. I only have an LS1046ARDB. Everything but QSGMII should work without
breakage; QSGMII needs patches 7 and 8. For this reason, the last 4
patches in this series should be applied together (and should not go
through separate trees).

Changes in v7:
- provide phylink_validate_mask_caps() helper
- Fix oops if memac_pcs_create returned -EPROBE_DEFER
- Fix using pcs-names instead of pcs-handle-names
- Fix not checking for -ENODATA when looking for sgmii pcs
- Fix 81-character line
- Simplify memac_validate with phylink_validate_mask_caps

Changes in v6:
- Remove unnecessary $ref from renesas,rzn1-a5psw
- Remove unnecessary type from pcs-handle-names
- Add maxItems to pcs-handle
- Fix 81-character line
- Fix uninitialized variable in dtsec_mac_config

Changes in v5:
- Add Lynx PCS binding

Changes in v4:
- Use pcs-handle-names instead of pcs-names, as discussed
- Don't fail if phy support was not compiled in
- Split off rate adaptation series
- Split off DPAA "preparation" series
- Split off Lynx 10G support
- t208x: Mark MAC1 and MAC2 as 10G
- Add XFI PCS for t208x MAC1/MAC2

Changes in v3:
- Expand pcs-handle to an array
- Add vendor prefix 'fsl,' to rgmii and mii properties.
- Set maxItems for pcs-names
- Remove phy-* properties from example because dt-schema complains and I
  can't be bothered to figure out how to make it work.
- Add pcs-handle as a preferred version of pcsphy-handle
- Deprecate pcsphy-handle
- Remove mii/rmii properties
- Put the PCS mdiodev only after we are done with it (since the PCS
  does not perform a get itself).
- Remove _return label from memac_initialization in favor of returning
  directly
- Fix grabbing the default PCS not checking for -ENODATA from
  of_property_match_string
- Set DTSEC_ECNTRL_R100M in dtsec_link_up instead of dtsec_mac_config
- Remove rmii/mii properties
- Replace 1000Base... with 1000BASE... to match IEEE capitalization
- Add compatibles for QSGMII PCSs
- Split arm and powerpcs dts updates

Changes in v2:
- Better document how we select which PCS to use in the default case
- Move PCS_LYNX dependency to fman Kconfig
- Remove unused variable slow_10g_if
- Restrict valid link modes based on the phy interface. This is easier
  to set up, and mostly captures what I intended to do the first time.
  We now have a custom validate which restricts half-duplex for some SoCs
  for RGMII, but generally just uses the default phylink validate.
- Configure the SerDes in enable/disable
- Properly implement all ethtool ops and ioctls. These were mostly
  stubbed out just enough to compile last time.
- Convert 10GEC and dTSEC as well
- Fix capitalization of mEMAC in commit messages
- Add nodes for QSGMII PCSs
- Add nodes for QSGMII PCSs
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 88a2b3cb 4e748b1b
......@@ -74,10 +74,10 @@ properties:
properties:
pcs-handle:
maxItems: 1
description:
phandle pointing to a PCS sub-node compatible with
renesas,rzn1-miic.yaml#
$ref: /schemas/types.yaml#/definitions/phandle
unevaluatedProperties: false
......
......@@ -108,11 +108,17 @@ properties:
$ref: "#/properties/phy-connection-type"
pcs-handle:
$ref: /schemas/types.yaml#/definitions/phandle
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
maxItems: 1
description:
Specifies a reference to a node representing a PCS PHY device on a MDIO
bus to link with an external PHY (phy-handle) if exists.
pcs-handle-names:
description:
The name of each PCS in pcs-handle.
phy-handle:
$ref: /schemas/types.yaml#/definitions/phandle
description:
......@@ -216,6 +222,9 @@ properties:
required:
- speed
dependencies:
pcs-handle-names: [pcs-handle]
allOf:
- if:
properties:
......
......@@ -85,9 +85,39 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle
description: A reference to the IEEE1588 timer
phys:
description: A reference to the SerDes lane(s)
maxItems: 1
phy-names:
items:
- const: serdes
pcsphy-handle:
$ref: /schemas/types.yaml#/definitions/phandle
description: A reference to the PCS (typically found on the SerDes)
$ref: /schemas/types.yaml#/definitions/phandle-array
minItems: 1
maxItems: 3
deprecated: true
description: See pcs-handle.
pcs-handle:
minItems: 1
maxItems: 3
description: |
A reference to the various PCSs (typically found on the SerDes). If
pcs-handle-names is absent, and phy-connection-type is "xgmii", then the first
reference will be assumed to be for "xfi". Otherwise, if pcs-handle-names is
absent, then the first reference will be assumed to be for "sgmii".
pcs-handle-names:
minItems: 1
maxItems: 3
items:
enum:
- sgmii
- qsgmii
- xfi
description: The type of each PCS in pcsphy-handle.
tbi-handle:
$ref: /schemas/types.yaml#/definitions/phandle
......@@ -100,6 +130,10 @@ required:
- fsl,fman-ports
- ptp-timer
dependencies:
pcs-handle-names:
- pcs-handle
allOf:
- $ref: ethernet-controller.yaml#
- if:
......@@ -110,14 +144,6 @@ allOf:
then:
required:
- tbi-handle
- if:
properties:
compatible:
contains:
const: fsl,fman-memac
then:
required:
- pcsphy-handle
unevaluatedProperties: false
......@@ -138,8 +164,9 @@ examples:
reg = <0xe8000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x0c &fman0_tx_0x2c>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy4>;
phy-handle = <&sgmii_phy1>;
phy-connection-type = "sgmii";
pcs-handle = <&pcsphy4>, <&qsgmiib_pcs1>;
pcs-handle-names = "sgmii", "qsgmii";
phys = <&serdes1 1>;
phy-names = "serdes";
};
...
......@@ -31,7 +31,7 @@ properties:
phy-mode: true
pcs-handle:
$ref: /schemas/types.yaml#/definitions/phandle
maxItems: 1
description:
A reference to a node representing a PCS PHY device found on
the internal MDIO bus.
......
......@@ -320,8 +320,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
......
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/pcs/fsl,lynx-pcs.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP Lynx PCS
maintainers:
- Ioana Ciornei <ioana.ciornei@nxp.com>
description: |
NXP Lynx 10G and 28G SerDes have Ethernet PCS devices which can be used as
protocol controllers. They are accessible over the Ethernet interface's MDIO
bus.
properties:
compatible:
const: fsl,lynx-pcs
reg:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
qsgmii_pcs1: ethernet-pcs@1 {
compatible = "fsl,lynx-pcs";
reg = <1>;
};
};
......@@ -24,9 +24,12 @@ &fman0 {
/* these aliases provide the FMan ports mapping */
enet0: ethernet@e0000 {
pcs-handle-names = "qsgmii";
};
enet1: ethernet@e2000 {
pcsphy-handle = <&pcsphy1>, <&qsgmiib_pcs1>;
pcs-handle-names = "sgmii", "qsgmii";
};
enet2: ethernet@e4000 {
......@@ -36,11 +39,32 @@ enet3: ethernet@e6000 {
};
enet4: ethernet@e8000 {
pcsphy-handle = <&pcsphy4>, <&qsgmiib_pcs2>;
pcs-handle-names = "sgmii", "qsgmii";
};
enet5: ethernet@ea000 {
pcsphy-handle = <&pcsphy5>, <&qsgmiib_pcs3>;
pcs-handle-names = "sgmii", "qsgmii";
};
enet6: ethernet@f0000 {
};
mdio@e1000 {
qsgmiib_pcs1: ethernet-pcs@1 {
compatible = "fsl,lynx-pcs";
reg = <0x1>;
};
qsgmiib_pcs2: ethernet-pcs@2 {
compatible = "fsl,lynx-pcs";
reg = <0x2>;
};
qsgmiib_pcs3: ethernet-pcs@3 {
compatible = "fsl,lynx-pcs";
reg = <0x3>;
};
};
};
......@@ -23,6 +23,8 @@ &soc {
&fman0 {
/* these aliases provide the FMan ports mapping */
enet0: ethernet@e0000 {
pcsphy-handle = <&qsgmiib_pcs3>;
pcs-handle-names = "qsgmii";
};
enet1: ethernet@e2000 {
......@@ -35,14 +37,37 @@ enet3: ethernet@e6000 {
};
enet4: ethernet@e8000 {
pcsphy-handle = <&pcsphy4>, <&qsgmiib_pcs1>;
pcs-handle-names = "sgmii", "qsgmii";
};
enet5: ethernet@ea000 {
pcsphy-handle = <&pcsphy5>, <&pcsphy5>;
pcs-handle-names = "sgmii", "qsgmii";
};
enet6: ethernet@f0000 {
};
enet7: ethernet@f2000 {
pcsphy-handle = <&pcsphy7>, <&qsgmiib_pcs2>, <&pcsphy7>;
pcs-handle-names = "sgmii", "qsgmii", "xfi";
};
mdio@eb000 {
qsgmiib_pcs1: ethernet-pcs@1 {
compatible = "fsl,lynx-pcs";
reg = <0x1>;
};
qsgmiib_pcs2: ethernet-pcs@2 {
compatible = "fsl,lynx-pcs";
reg = <0x2>;
};
qsgmiib_pcs3: ethernet-pcs@3 {
compatible = "fsl,lynx-pcs";
reg = <0x3>;
};
};
};
......@@ -55,7 +55,8 @@ ethernet@e0000 {
reg = <0xe0000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x08 &fman0_tx_0x28>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy0>;
pcsphy-handle = <&pcsphy0>, <&pcsphy0>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e1000 {
......
......@@ -52,7 +52,15 @@ ethernet@f0000 {
compatible = "fsl,fman-memac";
reg = <0xf0000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x10 &fman0_tx_0x30>;
pcsphy-handle = <&pcsphy6>;
pcsphy-handle = <&pcsphy6>, <&qsgmiib_pcs2>, <&pcsphy6>;
pcs-handle-names = "sgmii", "qsgmii", "xfi";
};
mdio@e9000 {
qsgmiib_pcs2: ethernet-pcs@2 {
compatible = "fsl,lynx-pcs";
reg = <2>;
};
};
mdio@f1000 {
......
......@@ -55,7 +55,15 @@ ethernet@e2000 {
reg = <0xe2000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x09 &fman0_tx_0x29>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy1>;
pcsphy-handle = <&pcsphy1>, <&qsgmiia_pcs1>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e1000 {
qsgmiia_pcs1: ethernet-pcs@1 {
compatible = "fsl,lynx-pcs";
reg = <1>;
};
};
mdio@e3000 {
......
......@@ -52,7 +52,15 @@ ethernet@f2000 {
compatible = "fsl,fman-memac";
reg = <0xf2000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x11 &fman0_tx_0x31>;
pcsphy-handle = <&pcsphy7>;
pcsphy-handle = <&pcsphy7>, <&qsgmiib_pcs3>, <&pcsphy7>;
pcs-handle-names = "sgmii", "qsgmii", "xfi";
};
mdio@e9000 {
qsgmiib_pcs3: ethernet-pcs@3 {
compatible = "fsl,lynx-pcs";
reg = <3>;
};
};
mdio@f3000 {
......
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
/*
* QorIQ FMan v3 10g port #2 device tree stub [ controller @ offset 0x400000 ]
*
* Copyright 2022 Sean Anderson <sean.anderson@seco.com>
* Copyright 2012 - 2015 Freescale Semiconductor Inc.
*/
fman@400000 {
fman0_rx_0x08: port@88000 {
cell-index = <0x8>;
compatible = "fsl,fman-v3-port-rx";
reg = <0x88000 0x1000>;
fsl,fman-10g-port;
};
fman0_tx_0x28: port@a8000 {
cell-index = <0x28>;
compatible = "fsl,fman-v3-port-tx";
reg = <0xa8000 0x1000>;
fsl,fman-10g-port;
};
ethernet@e0000 {
cell-index = <0>;
compatible = "fsl,fman-memac";
reg = <0xe0000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x08 &fman0_tx_0x28>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy0>, <&pcsphy0>;
pcs-handle-names = "sgmii", "xfi";
};
mdio@e1000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xe1000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
pcsphy0: ethernet-phy@0 {
reg = <0x0>;
};
};
};
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
/*
* QorIQ FMan v3 10g port #3 device tree stub [ controller @ offset 0x400000 ]
*
* Copyright 2022 Sean Anderson <sean.anderson@seco.com>
* Copyright 2012 - 2015 Freescale Semiconductor Inc.
*/
fman@400000 {
fman0_rx_0x09: port@89000 {
cell-index = <0x9>;
compatible = "fsl,fman-v3-port-rx";
reg = <0x89000 0x1000>;
fsl,fman-10g-port;
};
fman0_tx_0x29: port@a9000 {
cell-index = <0x29>;
compatible = "fsl,fman-v3-port-tx";
reg = <0xa9000 0x1000>;
fsl,fman-10g-port;
};
ethernet@e2000 {
cell-index = <1>;
compatible = "fsl,fman-memac";
reg = <0xe2000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x09 &fman0_tx_0x29>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy1>, <&pcsphy1>;
pcs-handle-names = "sgmii", "xfi";
};
mdio@e3000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xe3000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
pcsphy1: ethernet-phy@0 {
reg = <0x0>;
};
};
};
......@@ -51,7 +51,8 @@ ethernet@e0000 {
reg = <0xe0000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x08 &fman0_tx_0x28>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy0>;
pcsphy-handle = <&pcsphy0>, <&pcsphy0>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e1000 {
......
......@@ -51,7 +51,15 @@ ethernet@e2000 {
reg = <0xe2000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x09 &fman0_tx_0x29>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy1>;
pcsphy-handle = <&pcsphy1>, <&qsgmiia_pcs1>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e1000 {
qsgmiia_pcs1: ethernet-pcs@1 {
compatible = "fsl,lynx-pcs";
reg = <1>;
};
};
mdio@e3000 {
......
......@@ -51,7 +51,15 @@ ethernet@e4000 {
reg = <0xe4000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x0a &fman0_tx_0x2a>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy2>;
pcsphy-handle = <&pcsphy2>, <&qsgmiia_pcs2>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e1000 {
qsgmiia_pcs2: ethernet-pcs@2 {
compatible = "fsl,lynx-pcs";
reg = <2>;
};
};
mdio@e5000 {
......
......@@ -51,7 +51,15 @@ ethernet@e6000 {
reg = <0xe6000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x0b &fman0_tx_0x2b>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy3>;
pcsphy-handle = <&pcsphy3>, <&qsgmiia_pcs3>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e1000 {
qsgmiia_pcs3: ethernet-pcs@3 {
compatible = "fsl,lynx-pcs";
reg = <3>;
};
};
mdio@e7000 {
......
......@@ -51,7 +51,8 @@ ethernet@e8000 {
reg = <0xe8000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x0c &fman0_tx_0x2c>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy4>;
pcsphy-handle = <&pcsphy4>, <&pcsphy4>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e9000 {
......
......@@ -51,7 +51,15 @@ ethernet@ea000 {
reg = <0xea000 0x1000>;
fsl,fman-ports = <&fman0_rx_0x0d &fman0_tx_0x2d>;
ptp-timer = <&ptp_timer0>;
pcsphy-handle = <&pcsphy5>;
pcsphy-handle = <&pcsphy5>, <&qsgmiib_pcs1>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e9000 {
qsgmiib_pcs1: ethernet-pcs@1 {
compatible = "fsl,lynx-pcs";
reg = <1>;
};
};
mdio@eb000 {
......
......@@ -52,7 +52,15 @@ ethernet@f0000 {
compatible = "fsl,fman-memac";
reg = <0xf0000 0x1000>;
fsl,fman-ports = <&fman1_rx_0x10 &fman1_tx_0x30>;
pcsphy-handle = <&pcsphy14>;
pcsphy-handle = <&pcsphy14>, <&qsgmiid_pcs2>, <&pcsphy14>;
pcs-handle-names = "sgmii", "qsgmii", "xfi";
};
mdio@e9000 {
qsgmiid_pcs2: ethernet-pcs@2 {
compatible = "fsl,lynx-pcs";
reg = <2>;
};
};
mdio@f1000 {
......
......@@ -52,7 +52,15 @@ ethernet@f2000 {
compatible = "fsl,fman-memac";
reg = <0xf2000 0x1000>;
fsl,fman-ports = <&fman1_rx_0x11 &fman1_tx_0x31>;
pcsphy-handle = <&pcsphy15>;
pcsphy-handle = <&pcsphy15>, <&qsgmiid_pcs3>, <&pcsphy15>;
pcs-handle-names = "sgmii", "qsgmii", "xfi";
};
mdio@e9000 {
qsgmiid_pcs3: ethernet-pcs@3 {
compatible = "fsl,lynx-pcs";
reg = <3>;
};
};
mdio@f3000 {
......
......@@ -51,7 +51,8 @@ ethernet@e0000 {
reg = <0xe0000 0x1000>;
fsl,fman-ports = <&fman1_rx_0x08 &fman1_tx_0x28>;
ptp-timer = <&ptp_timer1>;
pcsphy-handle = <&pcsphy8>;
pcsphy-handle = <&pcsphy8>, <&pcsphy8>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e1000 {
......
......@@ -51,7 +51,15 @@ ethernet@e2000 {
reg = <0xe2000 0x1000>;
fsl,fman-ports = <&fman1_rx_0x09 &fman1_tx_0x29>;
ptp-timer = <&ptp_timer1>;
pcsphy-handle = <&pcsphy9>;
pcsphy-handle = <&pcsphy9>, <&qsgmiic_pcs1>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e1000 {
qsgmiic_pcs1: ethernet-pcs@1 {
compatible = "fsl,lynx-pcs";
reg = <1>;
};
};
mdio@e3000 {
......
......@@ -51,7 +51,15 @@ ethernet@e4000 {
reg = <0xe4000 0x1000>;
fsl,fman-ports = <&fman1_rx_0x0a &fman1_tx_0x2a>;
ptp-timer = <&ptp_timer1>;
pcsphy-handle = <&pcsphy10>;
pcsphy-handle = <&pcsphy10>, <&qsgmiic_pcs2>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e1000 {
qsgmiic_pcs2: ethernet-pcs@2 {
compatible = "fsl,lynx-pcs";
reg = <2>;
};
};
mdio@e5000 {
......
......@@ -51,7 +51,15 @@ ethernet@e6000 {
reg = <0xe6000 0x1000>;
fsl,fman-ports = <&fman1_rx_0x0b &fman1_tx_0x2b>;
ptp-timer = <&ptp_timer1>;
pcsphy-handle = <&pcsphy11>;
pcsphy-handle = <&pcsphy11>, <&qsgmiic_pcs3>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e1000 {
qsgmiic_pcs3: ethernet-pcs@3 {
compatible = "fsl,lynx-pcs";
reg = <3>;
};
};
mdio@e7000 {
......
......@@ -51,7 +51,8 @@ ethernet@e8000 {
reg = <0xe8000 0x1000>;
fsl,fman-ports = <&fman1_rx_0x0c &fman1_tx_0x2c>;
ptp-timer = <&ptp_timer1>;
pcsphy-handle = <&pcsphy12>;
pcsphy-handle = <&pcsphy12>, <&pcsphy12>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e9000 {
......
......@@ -51,7 +51,15 @@ ethernet@ea000 {
reg = <0xea000 0x1000>;
fsl,fman-ports = <&fman1_rx_0x0d &fman1_tx_0x2d>;
ptp-timer = <&ptp_timer1>;
pcsphy-handle = <&pcsphy13>;
pcsphy-handle = <&pcsphy13>, <&qsgmiid_pcs1>;
pcs-handle-names = "sgmii", "qsgmii";
};
mdio@e9000 {
qsgmiid_pcs1: ethernet-pcs@1 {
compatible = "fsl,lynx-pcs";
reg = <1>;
};
};
mdio@eb000 {
......
......@@ -609,8 +609,8 @@ usb1: usb@211000 {
/include/ "qoriq-bman1.dtsi"
/include/ "qoriq-fman3-0.dtsi"
/include/ "qoriq-fman3-0-1g-0.dtsi"
/include/ "qoriq-fman3-0-1g-1.dtsi"
/include/ "qoriq-fman3-0-10g-2.dtsi"
/include/ "qoriq-fman3-0-10g-3.dtsi"
/include/ "qoriq-fman3-0-1g-2.dtsi"
/include/ "qoriq-fman3-0-1g-3.dtsi"
/include/ "qoriq-fman3-0-1g-4.dtsi"
......
......@@ -2,8 +2,8 @@
menuconfig FSL_DPAA_ETH
tristate "DPAA Ethernet"
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.
......
......@@ -264,8 +264,19 @@ 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);
mac_dev->net_dev = net_dev;
/* 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->update_speed = dpaa_eth_cgr_set_speed;
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);
......@@ -273,6 +284,7 @@ static int dpaa_netdev_init(struct net_device *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;
}
......@@ -294,8 +306,7 @@ static int dpaa_stop(struct net_device *net_dev)
*/
msleep(200);
if (mac_dev->phy_dev)
phy_stop(mac_dev->phy_dev);
phylink_stop(mac_dev->phylink);
mac_dev->disable(mac_dev->fman_mac);
for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
......@@ -304,8 +315,7 @@ static int dpaa_stop(struct net_device *net_dev)
err = error;
}
if (net_dev->phydev)
phy_disconnect(net_dev->phydev);
phylink_disconnect_phy(mac_dev->phylink);
net_dev->phydev = NULL;
msleep(200);
......@@ -833,10 +843,10 @@ static int dpaa_eth_cgr_init(struct dpaa_priv *priv)
/* Set different thresholds based on the configured MAC speed.
* This may turn suboptimal if the MAC is reconfigured at another
* speed, so MACs must call dpaa_eth_cgr_set_speed in their adjust_link
* speed, so MACs must call dpaa_eth_cgr_set_speed in their link_up
* callback.
*/
if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full)
if (priv->mac_dev->phylink_config.mac_capabilities & MAC_10000FD)
cs_th = DPAA_CS_THRESHOLD_10G;
else
cs_th = DPAA_CS_THRESHOLD_1G;
......@@ -865,7 +875,7 @@ static int dpaa_eth_cgr_init(struct dpaa_priv *priv)
static void dpaa_eth_cgr_set_speed(struct mac_device *mac_dev, int speed)
{
struct net_device *net_dev = mac_dev->net_dev;
struct net_device *net_dev = to_net_dev(mac_dev->phylink_config.dev);
struct dpaa_priv *priv = netdev_priv(net_dev);
struct qm_mcc_initcgr opts = { };
u32 cs_th;
......@@ -2904,58 +2914,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
#define PHY_VEND_AQUANTIA2 0x31c31c00
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;
u32 phy_vendor;
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;
}
phy_vendor = phy_dev->drv->phy_id & GENMASK(31, 10);
/* Unless the PHY is capable of rate adaptation */
if (mac_dev->phy_if != PHY_INTERFACE_MODE_XGMII ||
(phy_vendor != PHY_VEND_AQUANTIA &&
phy_vendor != PHY_VEND_AQUANTIA2)) {
/* 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;
......@@ -2966,7 +2924,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;
......@@ -2981,7 +2940,7 @@ static int dpaa_open(struct net_device *net_dev)
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);
......@@ -2990,6 +2949,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);
......@@ -3145,10 +3105,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)
......@@ -3551,6 +3513,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);
......
......@@ -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;
phy_ethtool_ksettings_get(net_dev->phydev, cmd);
struct dpaa_priv *priv = netdev_priv(net_dev);
struct mac_device *mac_dev = priv->mac_dev;
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;
if (!net_dev->phydev)
return -ENODEV;
struct dpaa_priv *priv = netdev_priv(net_dev);
struct mac_device *mac_dev = priv->mac_dev;
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,
......@@ -99,80 +91,28 @@ static void dpaa_set_msglevel(struct net_device *net_dev,
static int dpaa_nway_reset(struct net_device *net_dev)
{
int err;
if (!net_dev->phydev)
return -ENODEV;
err = 0;
if (net_dev->phydev->autoneg) {
err = phy_start_aneg(net_dev->phydev);
if (err < 0)
netdev_err(net_dev, "phy_start_aneg() = %d\n",
err);
}
struct dpaa_priv *priv = netdev_priv(net_dev);
struct mac_device *mac_dev = priv->mac_dev;
return err;
return phylink_ethtool_nway_reset(mac_dev->phylink);
}
static void dpaa_get_pauseparam(struct net_device *net_dev,
struct ethtool_pauseparam *epause)
{
struct mac_device *mac_dev;
struct dpaa_priv *priv;
struct dpaa_priv *priv = netdev_priv(net_dev);
struct mac_device *mac_dev = priv->mac_dev;
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;
phylink_ethtool_get_pauseparam(mac_dev->phylink, epause);
}
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);
struct dpaa_priv *priv = netdev_priv(net_dev);
struct mac_device *mac_dev = priv->mac_dev;
return err;
return phylink_ethtool_set_pauseparam(mac_dev->phylink, epause);
}
static int dpaa_get_sset_count(struct net_device *net_dev, int type)
......
......@@ -3,7 +3,9 @@ config FSL_FMAN
tristate "FMan support"
depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST
select GENERIC_ALLOCATOR
select PHYLIB
select PHYLINK
select PCS
select PCS_LYNX
select CRC32
default n
help
......
......@@ -170,20 +170,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 {
......
......@@ -13,6 +13,7 @@
#include <linux/bitrev.h>
#include <linux/io.h>
#include <linux/crc32.h>
#include <linux/netdevice.h>
/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */
#define TGEC_TX_IPG_LENGTH_MASK 0x000003ff
......@@ -243,10 +244,6 @@ static int init(struct tgec_regs __iomem *regs, struct tgec_cfg *cfg,
static int check_init_parameters(struct fman_mac *tgec)
{
if (tgec->max_speed < SPEED_10000) {
pr_err("10G MAC driver only support 10G speed\n");
return -EINVAL;
}
if (!tgec->exception_cb) {
pr_err("uninitialized exception_cb\n");
return -EINVAL;
......@@ -384,40 +381,13 @@ static void free_init_resources(struct fman_mac *tgec)
tgec->unicast_addr_hash = NULL;
}
static bool is_init_done(struct tgec_cfg *cfg)
{
/* Checks if tGEC driver parameters were initialized */
if (!cfg)
return true;
return false;
}
static int tgec_enable(struct fman_mac *tgec)
{
struct tgec_regs __iomem *regs = tgec->regs;
u32 tmp;
if (!is_init_done(tgec->cfg))
return -EINVAL;
tmp = ioread32be(&regs->command_config);
tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN;
iowrite32be(tmp, &regs->command_config);
return 0;
}
static void tgec_disable(struct fman_mac *tgec)
{
struct tgec_regs __iomem *regs = tgec->regs;
u32 tmp;
WARN_ON_ONCE(!is_init_done(tgec->cfg));
tmp = ioread32be(&regs->command_config);
tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN);
iowrite32be(tmp, &regs->command_config);
}
static int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val)
......@@ -425,9 +395,6 @@ static int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val)
struct tgec_regs __iomem *regs = tgec->regs;
u32 tmp;
if (!is_init_done(tgec->cfg))
return -EINVAL;
tmp = ioread32be(&regs->command_config);
if (new_val)
tmp |= CMD_CFG_PROMIS_EN;
......@@ -444,9 +411,6 @@ static int tgec_set_tx_pause_frames(struct fman_mac *tgec,
{
struct tgec_regs __iomem *regs = tgec->regs;
if (!is_init_done(tgec->cfg))
return -EINVAL;
iowrite32be((u32)pause_time, &regs->pause_quant);
return 0;
......@@ -457,9 +421,6 @@ static int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en)
struct tgec_regs __iomem *regs = tgec->regs;
u32 tmp;
if (!is_init_done(tgec->cfg))
return -EINVAL;
tmp = ioread32be(&regs->command_config);
if (!en)
tmp |= CMD_CFG_PAUSE_IGNORE;
......@@ -470,12 +431,53 @@ static int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en)
return 0;
}
static void tgec_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
}
static void tgec_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 *tgec = mac_dev->fman_mac;
struct tgec_regs __iomem *regs = tgec->regs;
u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE :
FSL_FM_PAUSE_TIME_DISABLE;
u32 tmp;
tgec_set_tx_pause_frames(tgec, 0, pause_time, 0);
tgec_accept_rx_pause_frames(tgec, rx_pause);
mac_dev->update_speed(mac_dev, speed);
tmp = ioread32be(&regs->command_config);
tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN;
iowrite32be(tmp, &regs->command_config);
}
static void tgec_link_down(struct phylink_config *config, unsigned int mode,
phy_interface_t interface)
{
struct fman_mac *tgec = fman_config_to_mac(config)->fman_mac;
struct tgec_regs __iomem *regs = tgec->regs;
u32 tmp;
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 tgec_mac_ops = {
.validate = phylink_generic_validate,
.mac_config = tgec_mac_config,
.mac_link_up = tgec_link_up,
.mac_link_down = tgec_link_down,
};
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;
tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr);
set_mac_address(tgec->regs, (const u8 *)(*p_enet_addr));
......@@ -490,9 +492,6 @@ static int tgec_add_hash_mac_address(struct fman_mac *tgec,
u32 crc = 0xFFFFFFFF, hash;
u64 addr;
if (!is_init_done(tgec->cfg))
return -EINVAL;
addr = ENET_ADDR_TO_UINT64(*eth_addr);
if (!(addr & GROUP_ADDRESS)) {
......@@ -525,9 +524,6 @@ static int tgec_set_allmulti(struct fman_mac *tgec, bool enable)
u32 entry;
struct tgec_regs __iomem *regs = tgec->regs;
if (!is_init_done(tgec->cfg))
return -EINVAL;
if (enable) {
for (entry = 0; entry < TGEC_HASH_TABLE_SIZE; entry++)
iowrite32be(entry | TGEC_HASH_MCAST_EN,
......@@ -548,9 +544,6 @@ static int tgec_set_tstamp(struct fman_mac *tgec, bool enable)
struct tgec_regs __iomem *regs = tgec->regs;
u32 tmp;
if (!is_init_done(tgec->cfg))
return -EINVAL;
tmp = ioread32be(&regs->command_config);
if (enable)
......@@ -572,9 +565,6 @@ static int tgec_del_hash_mac_address(struct fman_mac *tgec,
u32 crc = 0xFFFFFFFF, hash;
u64 addr;
if (!is_init_done(tgec->cfg))
return -EINVAL;
addr = ((*(u64 *)eth_addr) >> 16);
/* CRC calculation */
......@@ -601,22 +591,12 @@ static int tgec_del_hash_mac_address(struct fman_mac *tgec,
return 0;
}
static void tgec_adjust_link(struct mac_device *mac_dev)
{
struct phy_device *phy_dev = mac_dev->phy_dev;
mac_dev->update_speed(mac_dev, phy_dev->speed);
}
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;
if (!is_init_done(tgec->cfg))
return -EINVAL;
bit_mask = get_exception_flag(exception);
if (bit_mask) {
if (enable)
......@@ -641,9 +621,6 @@ static int tgec_init(struct fman_mac *tgec)
enet_addr_t eth_addr;
int err;
if (is_init_done(tgec->cfg))
return -EINVAL;
if (DEFAULT_RESET_ON_INIT &&
(fman_reset_mac(tgec->fm, tgec->mac_id) != 0)) {
pr_err("Can't reset MAC!\n");
......@@ -753,7 +730,6 @@ static struct fman_mac *tgec_config(struct mac_device *mac_dev,
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 |
TGEC_IMASK_REM_FAULT |
......@@ -788,17 +764,15 @@ int tgec_initialization(struct mac_device *mac_dev,
int err;
struct fman_mac *tgec;
mac_dev->phylink_ops = &tgec_mac_ops;
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 = tgec_adjust_link;
mac_dev->enable = tgec_enable;
mac_dev->disable = tgec_disable;
......@@ -808,6 +782,19 @@ int tgec_initialization(struct mac_device *mac_dev,
goto _return;
}
/* 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
* XAUI, so just convert it for them.
*/
if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII)
mac_dev->phy_if = PHY_INTERFACE_MODE_XAUI;
__set_bit(PHY_INTERFACE_MODE_XAUI,
mac_dev->phylink_config.supported_interfaces);
mac_dev->phylink_config.mac_capabilities =
MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10000FD;
tgec = mac_dev->fman_mac;
tgec->cfg->max_frame_length = fman_get_max_frm();
err = tgec_init(tgec);
......
......@@ -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>
......@@ -93,130 +94,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)
{
......@@ -296,6 +175,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;
......@@ -424,57 +304,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;
......
......@@ -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,32 +25,22 @@ 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;
struct net_device *net_dev;
bool autoneg_pause;
bool rx_pause_req;
bool tx_pause_req;
bool rx_pause_active;
bool tx_pause_active;
bool promisc;
bool allmulti;
const struct phylink_mac_ops *phylink_ops;
int (*enable)(struct fman_mac *mac_dev);
void (*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);
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,
......@@ -63,6 +54,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;
......
......@@ -562,32 +562,49 @@ unsigned long phylink_get_capabilities(phy_interface_t interface,
EXPORT_SYMBOL_GPL(phylink_get_capabilities);
/**
* phylink_generic_validate() - generic validate() callback implementation
* @config: a pointer to a &struct phylink_config.
* phylink_validate_mask_caps() - Restrict link modes based on caps
* @supported: ethtool bitmask for supported link modes.
* @state: a pointer to a &struct phylink_link_state.
* @state: an (optional) pointer to a &struct phylink_link_state.
* @mac_capabilities: bitmask of MAC capabilities
*
* Generic implementation of the validate() callback that MAC drivers can
* use when they pass the range of supported interfaces and MAC capabilities.
* This makes use of phylink_get_linkmodes().
* Calculate the supported link modes based on @mac_capabilities, and restrict
* @supported and @state based on that. Use this function if your capabiliies
* aren't constant, such as if they vary depending on the interface.
*/
void phylink_generic_validate(struct phylink_config *config,
unsigned long *supported,
struct phylink_link_state *state)
void phylink_validate_mask_caps(unsigned long *supported,
struct phylink_link_state *state,
unsigned long mac_capabilities)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
unsigned long caps;
phylink_set_port_modes(mask);
phylink_set(mask, Autoneg);
caps = phylink_get_capabilities(state->interface,
config->mac_capabilities,
caps = phylink_get_capabilities(state->interface, mac_capabilities,
state->rate_matching);
phylink_caps_to_linkmodes(mask, caps);
linkmode_and(supported, supported, mask);
if (state)
linkmode_and(state->advertising, state->advertising, mask);
}
EXPORT_SYMBOL_GPL(phylink_validate_mask_caps);
/**
* phylink_generic_validate() - generic validate() callback implementation
* @config: a pointer to a &struct phylink_config.
* @supported: ethtool bitmask for supported link modes.
* @state: a pointer to a &struct phylink_link_state.
*
* Generic implementation of the validate() callback that MAC drivers can
* use when they pass the range of supported interfaces and MAC capabilities.
*/
void phylink_generic_validate(struct phylink_config *config,
unsigned long *supported,
struct phylink_link_state *state)
{
phylink_validate_mask_caps(supported, state, config->mac_capabilities);
}
EXPORT_SYMBOL_GPL(phylink_generic_validate);
static int phylink_validate_mac_and_pcs(struct phylink *pl,
......
......@@ -556,6 +556,9 @@ void phylink_caps_to_linkmodes(unsigned long *linkmodes, unsigned long caps);
unsigned long phylink_get_capabilities(phy_interface_t interface,
unsigned long mac_capabilities,
int rate_matching);
void phylink_validate_mask_caps(unsigned long *supported,
struct phylink_link_state *state,
unsigned long caps);
void phylink_generic_validate(struct phylink_config *config,
unsigned long *supported,
struct phylink_link_state *state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment