* [net-next PATCH v15 01/12] dt-bindings: nvmem: Document support for Airoha AN8855 Switch EFUSE
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
2025-06-26 21:23 ` [net-next PATCH v15 02/12] dt-bindings: net: Document support for Airoha AN8855 Switch PBUS MDIO Christian Marangi
` (10 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Document support for Airoha AN8855 Switch EFUSE used to calibrate
internal PHYs and store additional configuration info.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
.../bindings/nvmem/airoha,an8855-efuse.yaml | 123 ++++++++++++++++++
1 file changed, 123 insertions(+)
create mode 100644 Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
diff --git a/Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml b/Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
new file mode 100644
index 000000000000..9802d9ea2176
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/airoha,an8855-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Switch EFUSE
+
+maintainers:
+ - Christian Marangi <ansuelsmth@gmail.com>
+
+description:
+ Airoha AN8855 EFUSE used to calibrate internal PHYs and store additional
+ configuration info.
+
+$ref: nvmem.yaml#
+
+properties:
+ compatible:
+ const: airoha,an8855-efuse
+
+ '#nvmem-cell-cells':
+ const: 0
+
+required:
+ - compatible
+ - '#nvmem-cell-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ efuse {
+ compatible = "airoha,an8855-efuse";
+
+ #nvmem-cell-cells = <0>;
+
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ shift_sel_port0_tx_a: shift-sel-port0-tx-a@c {
+ reg = <0xc 0x4>;
+ };
+
+ shift_sel_port0_tx_b: shift-sel-port0-tx-b@10 {
+ reg = <0x10 0x4>;
+ };
+
+ shift_sel_port0_tx_c: shift-sel-port0-tx-c@14 {
+ reg = <0x14 0x4>;
+ };
+
+ shift_sel_port0_tx_d: shift-sel-port0-tx-d@18 {
+ reg = <0x18 0x4>;
+ };
+
+ shift_sel_port1_tx_a: shift-sel-port1-tx-a@1c {
+ reg = <0x1c 0x4>;
+ };
+
+ shift_sel_port1_tx_b: shift-sel-port1-tx-b@20 {
+ reg = <0x20 0x4>;
+ };
+
+ shift_sel_port1_tx_c: shift-sel-port1-tx-c@24 {
+ reg = <0x24 0x4>;
+ };
+
+ shift_sel_port1_tx_d: shift-sel-port1-tx-d@28 {
+ reg = <0x28 0x4>;
+ };
+
+ shift_sel_port2_tx_a: shift-sel-port2-tx-a@2c {
+ reg = <0x2c 0x4>;
+ };
+
+ shift_sel_port2_tx_b: shift-sel-port2-tx-b@30 {
+ reg = <0x30 0x4>;
+ };
+
+ shift_sel_port2_tx_c: shift-sel-port2-tx-c@34 {
+ reg = <0x34 0x4>;
+ };
+
+ shift_sel_port2_tx_d: shift-sel-port2-tx-d@38 {
+ reg = <0x38 0x4>;
+ };
+
+ shift_sel_port3_tx_a: shift-sel-port3-tx-a@4c {
+ reg = <0x4c 0x4>;
+ };
+
+ shift_sel_port3_tx_b: shift-sel-port3-tx-b@50 {
+ reg = <0x50 0x4>;
+ };
+
+ shift_sel_port3_tx_c: shift-sel-port3-tx-c@54 {
+ reg = <0x54 0x4>;
+ };
+
+ shift_sel_port3_tx_d: shift-sel-port3-tx-d@58 {
+ reg = <0x58 0x4>;
+ };
+
+ shift_sel_port4_tx_a: shift-sel-port4-tx-a@5c {
+ reg = <0x5c 0x4>;
+ };
+
+ shift_sel_port4_tx_b: shift-sel-port4-tx-b@60 {
+ reg = <0x60 0x4>;
+ };
+
+ shift_sel_port4_tx_c: shift-sel-port4-tx-c@64 {
+ reg = <0x64 0x4>;
+ };
+
+ shift_sel_port4_tx_d: shift-sel-port4-tx-d@68 {
+ reg = <0x68 0x4>;
+ };
+ };
+ };
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [net-next PATCH v15 02/12] dt-bindings: net: Document support for Airoha AN8855 Switch PBUS MDIO
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
2025-06-26 21:23 ` [net-next PATCH v15 01/12] dt-bindings: nvmem: Document support for Airoha AN8855 Switch EFUSE Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
2025-06-27 21:44 ` Rob Herring (Arm)
2025-06-26 21:23 ` [net-next PATCH v15 03/12] dt-bindings: net: dsa: Document support for Airoha AN8855 DSA Switch Christian Marangi
` (9 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Document support for Airoha AN8855 PBUS MDIO. Airoha AN8855 Switch
expose a way to access internal PHYs via Switch register.
This is named internally PBUS and does the function of an MDIO bus
for the internal PHYs.
It does support a maximum of 5 PHYs (matching the number of port
the Switch support)
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
.../bindings/net/airoha,an8855-mdio.yaml | 57 +++++++++++++++++++
1 file changed, 57 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
diff --git a/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml b/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
new file mode 100644
index 000000000000..c873103d2b66
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/airoha,an8855-mdio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 PBUS MDIO
+
+maintainers:
+ - Christian Marangi <ansuelsmth@gmail.com>
+
+description:
+ Airoha AN8855 Switch expose a way to access internal PHYs via
+ Switch register. This is named internally PBUS and does the function
+ of an MDIO bus for the internal PHYs.
+
+ It does support a maximum of 5 PHYs (matching the number of port
+ the Switch support)
+
+$ref: /schemas/net/mdio.yaml#
+
+properties:
+ compatible:
+ const: airoha,an8855-mdio
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ mdio {
+ compatible = "airoha,an8855-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ internal_phy1: phy@1 {
+ reg = <1>;
+ };
+
+ internal_phy2: phy@2 {
+ reg = <2>;
+ };
+
+ internal_phy3: phy@3 {
+ reg = <3>;
+ };
+
+ internal_phy4: phy@4 {
+ reg = <4>;
+ };
+
+ internal_phy5: phy@5 {
+ reg = <5>;
+ };
+ };
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [net-next PATCH v15 02/12] dt-bindings: net: Document support for Airoha AN8855 Switch PBUS MDIO
2025-06-26 21:23 ` [net-next PATCH v15 02/12] dt-bindings: net: Document support for Airoha AN8855 Switch PBUS MDIO Christian Marangi
@ 2025-06-27 21:44 ` Rob Herring (Arm)
0 siblings, 0 replies; 18+ messages in thread
From: Rob Herring (Arm) @ 2025-06-27 21:44 UTC (permalink / raw)
To: Christian Marangi
Cc: linux-mediatek, Russell King, Conor Dooley, Sean Wang,
Krzysztof Kozlowski, Lee Jones, Matthias Brugger, Jakub Kicinski,
devicetree, Paolo Abeni, linux-kernel, linux-arm-kernel,
Eric Dumazet, DENG Qingfang, Daniel Golle, Simon Horman,
Srinivas Kandagatla, Andrew Lunn, Vladimir Oltean, netdev,
Heiner Kallweit, Chester A. Unal, AngeloGioacchino Del Regno,
David S. Miller
On Thu, 26 Jun 2025 23:23:01 +0200, Christian Marangi wrote:
> Document support for Airoha AN8855 PBUS MDIO. Airoha AN8855 Switch
> expose a way to access internal PHYs via Switch register.
> This is named internally PBUS and does the function of an MDIO bus
> for the internal PHYs.
>
> It does support a maximum of 5 PHYs (matching the number of port
> the Switch support)
>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> ---
> .../bindings/net/airoha,an8855-mdio.yaml | 57 +++++++++++++++++++
> 1 file changed, 57 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [net-next PATCH v15 03/12] dt-bindings: net: dsa: Document support for Airoha AN8855 DSA Switch
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
2025-06-26 21:23 ` [net-next PATCH v15 01/12] dt-bindings: nvmem: Document support for Airoha AN8855 Switch EFUSE Christian Marangi
2025-06-26 21:23 ` [net-next PATCH v15 02/12] dt-bindings: net: Document support for Airoha AN8855 Switch PBUS MDIO Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
2025-06-27 21:46 ` Rob Herring
2025-06-26 21:23 ` [net-next PATCH v15 04/12] dt-bindings: net: Document support for AN8855 Switch Internal PHY Christian Marangi
` (8 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Document support for Airoha AN8855 5-port Gigabit Switch.
It does expose the 5 Internal PHYs on the MDIO bus and each port
can access the Switch register space by configurting the PHY page.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
.../net/dsa/airoha,an8855-switch.yaml | 86 +++++++++++++++++++
1 file changed, 86 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
diff --git a/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
new file mode 100644
index 000000000000..fbb9219fadae
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/dsa/airoha,an8855-switch.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Gigabit Switch
+
+maintainers:
+ - Christian Marangi <ansuelsmth@gmail.com>
+
+description: >
+ Airoha AN8855 is a 5-port Gigabit Switch.
+
+ It does expose the 5 Internal PHYs on the MDIO bus and each port
+ can access the Switch register space by configurting the PHY page.
+
+$ref: dsa.yaml#/$defs/ethernet-ports
+
+properties:
+ compatible:
+ const: airoha,an8855-switch
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ ethernet-switch {
+ compatible = "airoha,an8855-switch";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "lan1";
+ phy-mode = "internal";
+ phy-handle = <&internal_phy1>;
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "lan2";
+ phy-mode = "internal";
+ phy-handle = <&internal_phy2>;
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "lan3";
+ phy-mode = "internal";
+ phy-handle = <&internal_phy3>;
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan4";
+ phy-mode = "internal";
+ phy-handle = <&internal_phy4>;
+ };
+
+ port@4 {
+ reg = <4>;
+ label = "wan";
+ phy-mode = "internal";
+ phy-handle = <&internal_phy5>;
+ };
+
+ port@5 {
+ reg = <5>;
+ label = "cpu";
+ ethernet = <&gmac0>;
+ phy-mode = "2500base-x";
+
+ fixed-link {
+ speed = <2500>;
+ full-duplex;
+ pause;
+ };
+ };
+ };
+ };
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [net-next PATCH v15 03/12] dt-bindings: net: dsa: Document support for Airoha AN8855 DSA Switch
2025-06-26 21:23 ` [net-next PATCH v15 03/12] dt-bindings: net: dsa: Document support for Airoha AN8855 DSA Switch Christian Marangi
@ 2025-06-27 21:46 ` Rob Herring
0 siblings, 0 replies; 18+ messages in thread
From: Rob Herring @ 2025-06-27 21:46 UTC (permalink / raw)
To: Christian Marangi
Cc: Lee Jones, Krzysztof Kozlowski, Conor Dooley, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Vladimir Oltean, Srinivas Kandagatla, Heiner Kallweit,
Russell King, Chester A. Unal, Daniel Golle, DENG Qingfang,
Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
On Thu, Jun 26, 2025 at 11:23:02PM +0200, Christian Marangi wrote:
> Document support for Airoha AN8855 5-port Gigabit Switch.
>
> It does expose the 5 Internal PHYs on the MDIO bus and each port
> can access the Switch register space by configurting the PHY page.
>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> ---
> .../net/dsa/airoha,an8855-switch.yaml | 86 +++++++++++++++++++
> 1 file changed, 86 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
>
> diff --git a/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> new file mode 100644
> index 000000000000..fbb9219fadae
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> @@ -0,0 +1,86 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/dsa/airoha,an8855-switch.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN8855 Gigabit Switch
> +
> +maintainers:
> + - Christian Marangi <ansuelsmth@gmail.com>
> +
> +description: >
> + Airoha AN8855 is a 5-port Gigabit Switch.
> +
> + It does expose the 5 Internal PHYs on the MDIO bus and each port
> + can access the Switch register space by configurting the PHY page.
> +
> +$ref: dsa.yaml#/$defs/ethernet-ports
> +
> +properties:
> + compatible:
> + const: airoha,an8855-switch
> +
> +required:
> + - compatible
> +
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + ethernet-switch {
> + compatible = "airoha,an8855-switch";
> +
> + ports {
ethernet-ports is preferred.
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
And ethernet-port@0
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [net-next PATCH v15 04/12] dt-bindings: net: Document support for AN8855 Switch Internal PHY
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
` (2 preceding siblings ...)
2025-06-26 21:23 ` [net-next PATCH v15 03/12] dt-bindings: net: dsa: Document support for Airoha AN8855 DSA Switch Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
2025-06-26 21:23 ` [net-next PATCH v15 05/12] dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC Christian Marangi
` (7 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Document support for AN8855 Switch Internal PHY.
Airoha AN8855 is a 5-port Gigabit Switch that expose the Internal
PHYs on the MDIO bus.
Each PHY might need to be calibrated to correctly work with the
use of the eFUSE provided by the Switch SoC. This can be enabled by
defining in the PHY node the NVMEM cell properties.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
.../bindings/net/airoha,an8855-phy.yaml | 83 +++++++++++++++++++
1 file changed, 83 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
diff --git a/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml b/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
new file mode 100644
index 000000000000..d2f86116badf
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Switch Internal PHY
+
+maintainers:
+ - Christian Marangi <ansuelsmth@gmail.com>
+
+description: >
+ Airoha AN8855 is a 5-port Gigabit Switch that expose the Internal
+ PHYs on the MDIO bus.
+
+ Each PHY might need to be calibrated to correctly work with the
+ use of the eFUSE provided by the Switch SoC.
+
+allOf:
+ - $ref: ethernet-phy.yaml#
+
+select:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - ethernet-phy-idc0ff.0410
+ required:
+ - compatible
+
+properties:
+ reg:
+ maxItems: 1
+
+ nvmem-cells:
+ items:
+ - description: phandle to SoC eFUSE tx_a
+ - description: phandle to SoC eFUSE tx_b
+ - description: phandle to SoC eFUSE tx_c
+ - description: phandle to SoC eFUSE tx_d
+
+ nvmem-cell-names:
+ items:
+ - const: tx_a
+ - const: tx_b
+ - const: tx_c
+ - const: tx_d
+
+required:
+ - compatible
+ - reg
+
+dependentRequired:
+ nvmem-cells: [ nvmem-cell-names ]
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet-phy@1 {
+ compatible = "ethernet-phy-idc0ff.0410",
+ "ethernet-phy-ieee802.3-c45";
+
+ reg = <1>;
+ };
+
+ ethernet-phy@2 {
+ compatible = "ethernet-phy-idc0ff.0410",
+ "ethernet-phy-ieee802.3-c45";
+
+ reg = <2>;
+
+ nvmem-cells = <&shift_sel_port0_tx_a>,
+ <&shift_sel_port0_tx_b>,
+ <&shift_sel_port0_tx_c>,
+ <&shift_sel_port0_tx_d>;
+ nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
+ };
+ };
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [net-next PATCH v15 05/12] dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
` (3 preceding siblings ...)
2025-06-26 21:23 ` [net-next PATCH v15 04/12] dt-bindings: net: Document support for AN8855 Switch Internal PHY Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
2025-06-27 21:48 ` Rob Herring
2025-06-26 21:23 ` [net-next PATCH v15 06/12] net: mdio: Add Airoha AN8855 Switch MDIO PBUS Christian Marangi
` (6 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Document support for Airoha AN8855 Switch SoC. This SoC expose various
peripherals like an Ethernet Switch, a NVMEM provider and Ethernet PHYs.
It does also support i2c and timers but those are not currently
supported/used.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
.../bindings/mfd/airoha,an8855.yaml | 175 ++++++++++++++++++
1 file changed, 175 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
diff --git a/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
new file mode 100644
index 000000000000..a683db4f41d1
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
@@ -0,0 +1,175 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/airoha,an8855.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Switch SoC
+
+maintainers:
+ - Christian Marangi <ansuelsmth@gmail.com>
+
+description: >
+ Airoha AN8855 Switch is a SoC that expose various peripherals like an
+ Ethernet Switch, a NVMEM provider and Ethernet PHYs.
+
+ It does also support i2c and timers but those are not currently
+ supported/used.
+
+properties:
+ compatible:
+ const: airoha,an8855
+
+ reg:
+ maxItems: 1
+
+ reset-gpios: true
+
+ efuse:
+ type: object
+ $ref: /schemas/nvmem/airoha,an8855-efuse.yaml
+ description: EFUSE exposed by the Airoha AN8855 SoC
+
+ ethernet-switch:
+ type: object
+ $ref: /schemas/net/dsa/airoha,an8855-switch.yaml
+ description: Switch exposed by the Airoha AN8855 SoC
+
+ mdio:
+ type: object
+ $ref: /schemas/net/airoha,an8855-mdio.yaml
+ description: MDIO exposed by the Airoha AN8855 SoC
+
+required:
+ - compatible
+ - reg
+ - mdio
+ - ethernet-switch
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ soc@1 {
+ compatible = "airoha,an8855";
+ reg = <1>;
+
+ reset-gpios = <&pio 39 0>;
+
+ efuse {
+ compatible = "airoha,an8855-efuse";
+
+ #nvmem-cell-cells = <0>;
+
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ shift_sel_port0_tx_a: shift-sel-port0-tx-a@c {
+ reg = <0xc 0x4>;
+ };
+
+ shift_sel_port0_tx_b: shift-sel-port0-tx-b@10 {
+ reg = <0x10 0x4>;
+ };
+
+ shift_sel_port0_tx_c: shift-sel-port0-tx-c@14 {
+ reg = <0x14 0x4>;
+ };
+
+ shift_sel_port0_tx_d: shift-sel-port0-tx-d@18 {
+ reg = <0x18 0x4>;
+ };
+
+ shift_sel_port1_tx_a: shift-sel-port1-tx-a@1c {
+ reg = <0x1c 0x4>;
+ };
+
+ shift_sel_port1_tx_b: shift-sel-port1-tx-b@20 {
+ reg = <0x20 0x4>;
+ };
+
+ shift_sel_port1_tx_c: shift-sel-port1-tx-c@24 {
+ reg = <0x24 0x4>;
+ };
+
+ shift_sel_port1_tx_d: shift-sel-port1-tx-d@28 {
+ reg = <0x28 0x4>;
+ };
+ };
+ };
+
+ ethernet-switch {
+ compatible = "airoha,an8855-switch";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "lan1";
+ phy-mode = "internal";
+ phy-handle = <&internal_phy1>;
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "lan2";
+ phy-mode = "internal";
+ phy-handle = <&internal_phy2>;
+ };
+
+ port@5 {
+ reg = <5>;
+ label = "cpu";
+ ethernet = <&gmac0>;
+ phy-mode = "2500base-x";
+
+ fixed-link {
+ speed = <2500>;
+ full-duplex;
+ pause;
+ };
+ };
+ };
+ };
+
+ mdio {
+ compatible = "airoha,an8855-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ internal_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-idc0ff.0410",
+ "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+
+ nvmem-cells = <&shift_sel_port0_tx_a>,
+ <&shift_sel_port0_tx_b>,
+ <&shift_sel_port0_tx_c>,
+ <&shift_sel_port0_tx_d>;
+ nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
+ };
+
+ internal_phy2: ethernet-phy@2 {
+ compatible = "ethernet-phy-idc0ff.0410",
+ "ethernet-phy-ieee802.3-c22";
+ reg = <2>;
+
+ nvmem-cells = <&shift_sel_port1_tx_a>,
+ <&shift_sel_port1_tx_b>,
+ <&shift_sel_port1_tx_c>,
+ <&shift_sel_port1_tx_d>;
+ nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
+ };
+ };
+ };
+ };
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [net-next PATCH v15 05/12] dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC
2025-06-26 21:23 ` [net-next PATCH v15 05/12] dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC Christian Marangi
@ 2025-06-27 21:48 ` Rob Herring
2025-06-28 0:36 ` Christian Marangi
0 siblings, 1 reply; 18+ messages in thread
From: Rob Herring @ 2025-06-27 21:48 UTC (permalink / raw)
To: Christian Marangi
Cc: Lee Jones, Krzysztof Kozlowski, Conor Dooley, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Vladimir Oltean, Srinivas Kandagatla, Heiner Kallweit,
Russell King, Chester A. Unal, Daniel Golle, DENG Qingfang,
Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
On Thu, Jun 26, 2025 at 11:23:04PM +0200, Christian Marangi wrote:
> Document support for Airoha AN8855 Switch SoC. This SoC expose various
> peripherals like an Ethernet Switch, a NVMEM provider and Ethernet PHYs.
>
> It does also support i2c and timers but those are not currently
> supported/used.
>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> ---
> .../bindings/mfd/airoha,an8855.yaml | 175 ++++++++++++++++++
> 1 file changed, 175 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
>
> diff --git a/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
> new file mode 100644
> index 000000000000..a683db4f41d1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
> @@ -0,0 +1,175 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/airoha,an8855.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN8855 Switch SoC
> +
> +maintainers:
> + - Christian Marangi <ansuelsmth@gmail.com>
> +
> +description: >
> + Airoha AN8855 Switch is a SoC that expose various peripherals like an
> + Ethernet Switch, a NVMEM provider and Ethernet PHYs.
> +
> + It does also support i2c and timers but those are not currently
> + supported/used.
> +
> +properties:
> + compatible:
> + const: airoha,an8855
> +
> + reg:
> + maxItems: 1
> +
> + reset-gpios: true
> +
> + efuse:
> + type: object
> + $ref: /schemas/nvmem/airoha,an8855-efuse.yaml
> + description: EFUSE exposed by the Airoha AN8855 SoC
> +
> + ethernet-switch:
> + type: object
> + $ref: /schemas/net/dsa/airoha,an8855-switch.yaml
> + description: Switch exposed by the Airoha AN8855 SoC
> +
> + mdio:
> + type: object
> + $ref: /schemas/net/airoha,an8855-mdio.yaml
> + description: MDIO exposed by the Airoha AN8855 SoC
> +
> +required:
> + - compatible
> + - reg
> + - mdio
> + - ethernet-switch
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/gpio/gpio.h>
> +
> + mdio {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + soc@1 {
> + compatible = "airoha,an8855";
> + reg = <1>;
> +
> + reset-gpios = <&pio 39 0>;
> +
> + efuse {
> + compatible = "airoha,an8855-efuse";
> +
> + #nvmem-cell-cells = <0>;
> +
> + nvmem-layout {
> + compatible = "fixed-layout";
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + shift_sel_port0_tx_a: shift-sel-port0-tx-a@c {
> + reg = <0xc 0x4>;
> + };
> +
> + shift_sel_port0_tx_b: shift-sel-port0-tx-b@10 {
> + reg = <0x10 0x4>;
> + };
> +
> + shift_sel_port0_tx_c: shift-sel-port0-tx-c@14 {
> + reg = <0x14 0x4>;
> + };
> +
> + shift_sel_port0_tx_d: shift-sel-port0-tx-d@18 {
> + reg = <0x18 0x4>;
> + };
> +
> + shift_sel_port1_tx_a: shift-sel-port1-tx-a@1c {
> + reg = <0x1c 0x4>;
> + };
> +
> + shift_sel_port1_tx_b: shift-sel-port1-tx-b@20 {
> + reg = <0x20 0x4>;
> + };
> +
> + shift_sel_port1_tx_c: shift-sel-port1-tx-c@24 {
> + reg = <0x24 0x4>;
> + };
> +
> + shift_sel_port1_tx_d: shift-sel-port1-tx-d@28 {
> + reg = <0x28 0x4>;
> + };
> + };
> + };
> +
> + ethernet-switch {
> + compatible = "airoha,an8855-switch";
> +
> + ports {
Same comment here.
Why do we need 2 examples of the same thing? Isn't this 1 complete
example here enough?
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Rob
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [net-next PATCH v15 05/12] dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC
2025-06-27 21:48 ` Rob Herring
@ 2025-06-28 0:36 ` Christian Marangi
0 siblings, 0 replies; 18+ messages in thread
From: Christian Marangi @ 2025-06-28 0:36 UTC (permalink / raw)
To: Rob Herring
Cc: Lee Jones, Krzysztof Kozlowski, Conor Dooley, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Vladimir Oltean, Srinivas Kandagatla, Heiner Kallweit,
Russell King, Chester A. Unal, Daniel Golle, DENG Qingfang,
Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
On Fri, Jun 27, 2025 at 04:48:21PM -0500, Rob Herring wrote:
> On Thu, Jun 26, 2025 at 11:23:04PM +0200, Christian Marangi wrote:
> > Document support for Airoha AN8855 Switch SoC. This SoC expose various
> > peripherals like an Ethernet Switch, a NVMEM provider and Ethernet PHYs.
> >
> > It does also support i2c and timers but those are not currently
> > supported/used.
> >
> > Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> > ---
> > .../bindings/mfd/airoha,an8855.yaml | 175 ++++++++++++++++++
> > 1 file changed, 175 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
> > new file mode 100644
> > index 000000000000..a683db4f41d1
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
> > @@ -0,0 +1,175 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/mfd/airoha,an8855.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Airoha AN8855 Switch SoC
> > +
> > +maintainers:
> > + - Christian Marangi <ansuelsmth@gmail.com>
> > +
> > +description: >
> > + Airoha AN8855 Switch is a SoC that expose various peripherals like an
> > + Ethernet Switch, a NVMEM provider and Ethernet PHYs.
> > +
> > + It does also support i2c and timers but those are not currently
> > + supported/used.
> > +
> > +properties:
> > + compatible:
> > + const: airoha,an8855
> > +
> > + reg:
> > + maxItems: 1
> > +
> > + reset-gpios: true
> > +
> > + efuse:
> > + type: object
> > + $ref: /schemas/nvmem/airoha,an8855-efuse.yaml
> > + description: EFUSE exposed by the Airoha AN8855 SoC
> > +
> > + ethernet-switch:
> > + type: object
> > + $ref: /schemas/net/dsa/airoha,an8855-switch.yaml
> > + description: Switch exposed by the Airoha AN8855 SoC
> > +
> > + mdio:
> > + type: object
> > + $ref: /schemas/net/airoha,an8855-mdio.yaml
> > + description: MDIO exposed by the Airoha AN8855 SoC
> > +
> > +required:
> > + - compatible
> > + - reg
> > + - mdio
> > + - ethernet-switch
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > + - |
> > + #include <dt-bindings/gpio/gpio.h>
> > +
> > + mdio {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > +
> > + soc@1 {
> > + compatible = "airoha,an8855";
> > + reg = <1>;
> > +
> > + reset-gpios = <&pio 39 0>;
> > +
> > + efuse {
> > + compatible = "airoha,an8855-efuse";
> > +
> > + #nvmem-cell-cells = <0>;
> > +
> > + nvmem-layout {
> > + compatible = "fixed-layout";
> > + #address-cells = <1>;
> > + #size-cells = <1>;
> > +
> > + shift_sel_port0_tx_a: shift-sel-port0-tx-a@c {
> > + reg = <0xc 0x4>;
> > + };
> > +
> > + shift_sel_port0_tx_b: shift-sel-port0-tx-b@10 {
> > + reg = <0x10 0x4>;
> > + };
> > +
> > + shift_sel_port0_tx_c: shift-sel-port0-tx-c@14 {
> > + reg = <0x14 0x4>;
> > + };
> > +
> > + shift_sel_port0_tx_d: shift-sel-port0-tx-d@18 {
> > + reg = <0x18 0x4>;
> > + };
> > +
> > + shift_sel_port1_tx_a: shift-sel-port1-tx-a@1c {
> > + reg = <0x1c 0x4>;
> > + };
> > +
> > + shift_sel_port1_tx_b: shift-sel-port1-tx-b@20 {
> > + reg = <0x20 0x4>;
> > + };
> > +
> > + shift_sel_port1_tx_c: shift-sel-port1-tx-c@24 {
> > + reg = <0x24 0x4>;
> > + };
> > +
> > + shift_sel_port1_tx_d: shift-sel-port1-tx-d@28 {
> > + reg = <0x28 0x4>;
> > + };
> > + };
> > + };
> > +
> > + ethernet-switch {
> > + compatible = "airoha,an8855-switch";
> > +
> > + ports {
>
> Same comment here.
>
> Why do we need 2 examples of the same thing? Isn't this 1 complete
> example here enough?
>
Do you prefer if I drop example from every other schema and keep only
this?
And with this change is it ok to keep the review tag?
--
Ansuel
^ permalink raw reply [flat|nested] 18+ messages in thread
* [net-next PATCH v15 06/12] net: mdio: Add Airoha AN8855 Switch MDIO PBUS
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
` (4 preceding siblings ...)
2025-06-26 21:23 ` [net-next PATCH v15 05/12] dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
2025-06-26 21:23 ` [net-next PATCH v15 07/12] nvmem: an8855: Add support for Airoha AN8855 Switch EFUSE Christian Marangi
` (5 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Add Airoha AN8855 MDIO PBUS driver that permits to access the internal
Gigabit PHY from the Switch register.
This have the benefits of exposing direct access to CL45 address and
Vendor MDIO pages via specific Switch registers.
Additional info are present in a long explaination in the MDIO driver
and also finding from Reverse-Engineering the implementation.
This requires the upper Switch MFD to be probed and init to actually
work as it does make use of regmap.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/mdio/Kconfig | 10 ++
drivers/net/mdio/Makefile | 1 +
drivers/net/mdio/mdio-an8855.c | 262 +++++++++++++++++++++++++++++++++
include/linux/dsa/an8855.h | 18 +++
4 files changed, 291 insertions(+)
create mode 100644 drivers/net/mdio/mdio-an8855.c
create mode 100644 include/linux/dsa/an8855.h
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
index 7db40aaa079d..7f8f0b5caa42 100644
--- a/drivers/net/mdio/Kconfig
+++ b/drivers/net/mdio/Kconfig
@@ -42,6 +42,16 @@ config MDIO_XGENE
This module provides a driver for the MDIO busses found in the
APM X-Gene SoC's.
+config MDIO_AN8855
+ tristate "Airoha AN8855 Switch MDIO bus controller"
+ depends on MFD_AIROHA_AN8855
+ depends on OF_MDIO
+ select MDIO_REGMAP
+ help
+ This module provides a driver for the Airoha AN8855 Switch
+ that requires a MDIO passtrough as switch address is shared
+ with the internal PHYs and requires additional page handling.
+
config MDIO_ASPEED
tristate "ASPEED MDIO bus controller"
depends on ARCH_ASPEED || COMPILE_TEST
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
index c23778e73890..2b9edddf3911 100644
--- a/drivers/net/mdio/Makefile
+++ b/drivers/net/mdio/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_ACPI_MDIO) += acpi_mdio.o
obj-$(CONFIG_FWNODE_MDIO) += fwnode_mdio.o
obj-$(CONFIG_OF_MDIO) += of_mdio.o
+obj-$(CONFIG_MDIO_AN8855) += mdio-an8855.o
obj-$(CONFIG_MDIO_ASPEED) += mdio-aspeed.o
obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o
obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o
diff --git a/drivers/net/mdio/mdio-an8855.c b/drivers/net/mdio/mdio-an8855.c
new file mode 100644
index 000000000000..990cf683b470
--- /dev/null
+++ b/drivers/net/mdio/mdio-an8855.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * MDIO PBUS driver for Airoha AN8855 Switch
+ *
+ * Author: Christian Marangi <ansuelsmth@gmail.com>
+ *
+ */
+
+#include <linux/dsa/an8855.h>
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* AN8855 permit to access the internal GPHY via the PBUS
+ * interface.
+ *
+ * Some piece of this comes from Reverse-Enginnering
+ * by applying the value on the Switch and observing
+ * it by reading the raw value on the MDIO BUS.
+ *
+ * The CL22 address are shifted by 4 left
+ * The CL44 address need to be multiplied by 4 (and
+ * no shift)
+ *
+ * The GPHY have additional configuration (like auto
+ * downshift) at PAGE 1 in the EXT register.
+ * It was discovered that it's possible to access
+ * PAGE x address by increasing them by 2 on setting
+ * the value in the related mask.
+ * The PHY have these custom/vendor register
+ * always starting at 0x10.
+ * From MDIO bus, for address 0x0 to 0xf, PHY
+ * always report PAGE 0 values.
+ * From PBUS, on setting the PAGE value, 0x0 to 0xf
+ * always report 0.
+ *
+ * (it can also be notice that PBUS does NOT change the
+ * page on accessing these custom/vendor register)
+ *
+ * Comparison examples:
+ * (PORT 0 PAGE 1) | (PORT 0 PAGE 2)
+ * PBUS ADDR VALUE MDIO | PBUS ADDR VALUE MDIO
+ * 0xa0803000: 0x00000000 0x1840 | 0xa0804000: 0x00000000 0x1840
+ * 0xa0803010: 0x00000000 0x7949 | 0xa0804010: 0x00000000 0x7949
+ * 0xa0803020: 0x00000000 0xc0ff | 0xa0804020: 0x00000000 0xc0ff
+ * 0xa0803030: 0x00000000 0x0410 | 0xa0804030: 0x00000000 0x0410
+ * 0xa0803040: 0x00000000 0x0de1 | 0xa0804040: 0x00000000 0x0de1
+ * 0xa0803050: 0x00000000 0x0000 | 0xa0804050: 0x00000000 0x0000
+ * 0xa0803060: 0x00000000 0x0004 | 0xa0804060: 0x00000000 0x0004
+ * 0xa0803070: 0x00000000 0x2001 | 0xa0804070: 0x00000000 0x2001
+ * 0xa0803080: 0x00000000 0x0000 | 0xa0804080: 0x00000000 0x0000
+ * 0xa0803090: 0x00000000 0x0200 | 0xa0804090: 0x00000000 0x0200
+ * 0xa08030a0: 0x00000000 0x4000 | 0xa08040a0: 0x00000000 0x4000
+ * 0xa08030b0: 0x00000000 0x0000 | 0xa08040b0: 0x00000000 0x0000
+ * 0xa08030c0: 0x00000000 0x0000 | 0xa08040c0: 0x00000000 0x0000
+ * 0xa08030d0: 0x00000000 0x0000 | 0xa08040d0: 0x00000000 0x0000
+ * 0xa08030e0: 0x00000000 0x0000 | 0xa08040e0: 0x00000000 0x0000
+ * 0xa08030f0: 0x00000000 0x2000 | 0xa08040f0: 0x00000000 0x2000
+ * 0xa0803100: 0x00000000 0x0000 | 0xa0804100: 0x00000000 0x0000
+ * 0xa0803110: 0x00000000 0x0000 | 0xa0804110: 0x0000030f 0x030f
+ * 0xa0803120: 0x00000000 0x0000 | 0xa0804120: 0x00000000 0x0000
+ * 0xa0803130: 0x00000030 0x0030 | 0xa0804130: 0x00000000 0x0000
+ * 0xa0803140: 0x00003a14 0x3a14 | 0xa0804140: 0x00000000 0x0000
+ * 0xa0803150: 0x00000101 0x0101 | 0xa0804150: 0x00000000 0x0000
+ * 0xa0803160: 0x00000001 0x0001 | 0xa0804160: 0x00000000 0x0000
+ * 0xa0803170: 0x00000800 0x0800 | 0xa0804170: 0x000001ff 0x01ff
+ * 0xa0803180: 0x00000000 0x0000 | 0xa0804180: 0x0000ff1f 0xff1f
+ * 0xa0803190: 0x0000001f 0x001f | 0xa0804190: 0x000083ff 0x83ff
+ * 0xa08031a0: 0x00000000 0x0000 | 0xa08041a0: 0x00000000 0x0000
+ * 0xa08031b0: 0x00000000 0x0000 | 0xa08041b0: 0x00000000 0x0000
+ * 0xa08031c0: 0x00003001 0x3001 | 0xa08041c0: 0x00000000 0x0000
+ * 0xa08031d0: 0x00000000 0x0000 | 0xa08041d0: 0x00000000 0x0000
+ * 0xa08031e0: 0x00000000 0x0000 | 0xa08041e0: 0x00000000 0x0000
+ * 0xa08031f0: 0x00000000 0x0001 | 0xa08041f0: 0x00000000 0x0002
+ *
+ * Using the PBUS permits to have consistent access
+ * to Switch and PHY without having to relay on checking
+ * pages.
+ *
+ * It does also permit to cut on CL45 access and PAGE1
+ * access as the PBUS expose direct register for them.
+ *
+ * The base address is 0xa0800000 and can be seen as
+ * bitmap to derive each specific address.
+ *
+ * Example:
+ * PORT 1 ADDR 0x2 --> 0xa1800020
+ * ^ ^
+ * | ADDR
+ * PORT
+ * PORT 2 DEVAD 1 ADDR 0x2 --> 0xa2840008
+ * ^ ^ ^
+ * | | ADDR (*4)
+ * | DEVAD
+ * PORT
+ * PORT 3 PAGE 1 ADDR 0x14 --> 0xa3803140
+ * ^ ^^^
+ * | |ADDR
+ * | PAGE (+2)
+ * PORT
+ *
+ * It's worth mention that trying to read more than the
+ * expected PHY address cause the PBUS to ""crash"" and
+ * the Switch to lock out (requiring a reset).
+ * Validation of the port value is put to prevent this
+ * problem.
+ */
+
+struct an8855_mdio_priv {
+ struct regmap *regmap;
+ u32 base_addr;
+ u8 next_page;
+};
+
+static int an8855_mdio_read(struct mii_bus *bus, int addr, int regnum)
+{
+ struct an8855_mdio_priv *priv = bus->priv;
+ u32 pbus_addr = AN8855_GPHY_ACCESS;
+ u32 port = addr - priv->base_addr;
+ u32 val;
+ int ret;
+
+ /* Signal invalid address for mdio tools */
+ if (port >= AN8855_NUM_PHY_PORT)
+ return 0xffff;
+
+ pbus_addr |= FIELD_PREP(AN8855_GPHY_PORT, port);
+ pbus_addr |= FIELD_PREP(AN8855_CL22_ADDR, regnum);
+ if (priv->next_page)
+ pbus_addr |= FIELD_PREP(AN8855_PAGE_SELECT,
+ priv->next_page + 2);
+
+ ret = regmap_read(priv->regmap, pbus_addr, &val);
+ if (ret)
+ return ret;
+
+ return val & 0xffff;
+}
+
+static int an8855_mdio_write(struct mii_bus *bus, int addr, int regnum,
+ u16 value)
+{
+ struct an8855_mdio_priv *priv = bus->priv;
+ u32 pbus_addr = AN8855_GPHY_ACCESS;
+ u32 port = addr - priv->base_addr;
+
+ if (port >= AN8855_NUM_PHY_PORT)
+ return -EINVAL;
+
+ /* When PHY ask to change page, skip writing it and
+ * save it for the next read/write.
+ */
+ if (regnum == AN8855_PHY_SELECT_PAGE) {
+ priv->next_page = value;
+ return 0;
+ }
+
+ pbus_addr |= FIELD_PREP(AN8855_GPHY_PORT, port);
+ pbus_addr |= FIELD_PREP(AN8855_CL22_ADDR, regnum);
+ if (priv->next_page)
+ pbus_addr |= FIELD_PREP(AN8855_PAGE_SELECT,
+ priv->next_page + 2);
+
+ return regmap_write(priv->regmap, pbus_addr, value);
+}
+
+static int an8855_mdio_cl45_read(struct mii_bus *bus, int addr, int devnum,
+ int regnum)
+{
+ struct an8855_mdio_priv *priv = bus->priv;
+ u32 pbus_addr = AN8855_GPHY_ACCESS;
+ u32 port = addr - priv->base_addr;
+ u32 val;
+ int ret;
+
+ /* Signal invalid address for mdio tools */
+ if (port >= AN8855_NUM_PHY_PORT)
+ return 0xffff;
+
+ pbus_addr |= FIELD_PREP(AN8855_GPHY_PORT, port);
+ pbus_addr |= FIELD_PREP(AN8855_DEVAD_ADDR, devnum);
+ pbus_addr |= FIELD_PREP(AN8855_CL45_ADDR, regnum * 4);
+
+ ret = regmap_read(priv->regmap, pbus_addr, &val);
+ if (ret)
+ return ret;
+
+ return val & 0xffff;
+}
+
+static int an8855_mdio_cl45_write(struct mii_bus *bus, int addr, int devnum,
+ int regnum, u16 value)
+{
+ struct an8855_mdio_priv *priv = bus->priv;
+ u32 pbus_addr = AN8855_GPHY_ACCESS;
+ u32 port = addr - priv->base_addr;
+
+ if (port >= AN8855_NUM_PHY_PORT)
+ return -EINVAL;
+
+ pbus_addr |= FIELD_PREP(AN8855_GPHY_PORT, port);
+ pbus_addr |= FIELD_PREP(AN8855_DEVAD_ADDR, devnum);
+ pbus_addr |= FIELD_PREP(AN8855_CL45_ADDR, regnum * 4);
+
+ return regmap_write(priv->regmap, pbus_addr, value);
+}
+
+static int an8855_mdio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct an8855_mdio_priv *priv;
+ struct mii_bus *bus;
+ int ret;
+
+ bus = devm_mdiobus_alloc_size(dev, sizeof(*priv));
+ if (!bus)
+ return -ENOMEM;
+
+ priv = bus->priv;
+ priv->regmap = dev_get_regmap(dev->parent, NULL);
+ if (!priv->regmap)
+ return -ENOENT;
+
+ ret = of_property_read_u32(dev->parent->of_node, "reg",
+ &priv->base_addr);
+ if (ret)
+ return -EINVAL;
+
+ bus->name = "an8855_mdio_bus";
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s-gphy-pbus", dev_name(dev));
+ bus->parent = dev;
+ bus->read = an8855_mdio_read;
+ bus->write = an8855_mdio_write;
+ bus->read_c45 = an8855_mdio_cl45_read;
+ bus->write_c45 = an8855_mdio_cl45_write;
+
+ ret = devm_of_mdiobus_register(dev, bus, dev->of_node);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register MDIO bus\n");
+
+ return 0;
+}
+
+static const struct of_device_id an8855_mdio_of_match[] = {
+ { .compatible = "airoha,an8855-mdio", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, an8855_mdio_of_match);
+
+static struct platform_driver an8855_mdio_driver = {
+ .probe = an8855_mdio_probe,
+ .driver = {
+ .name = "an8855-mdio",
+ .of_match_table = an8855_mdio_of_match,
+ },
+};
+module_platform_driver(an8855_mdio_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_DESCRIPTION("Driver for AN8855 MDIO passthrough");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/dsa/an8855.h b/include/linux/dsa/an8855.h
new file mode 100644
index 000000000000..32ec29b3abb0
--- /dev/null
+++ b/include/linux/dsa/an8855.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _NET_AN8855_H
+#define _NET_AN8855_H
+
+#define AN8855_GPHY_ACCESS 0xa0800000
+#define AN8855_GPHY_PORT GENMASK(26, 24)
+#define AN8855_DEVAD_ADDR GENMASK(23, 18)
+#define AN8855_PAGE_SELECT GENMASK(14, 12)
+#define AN8855_ADDR GENMASK(11, 0)
+#define AN8855_CL45_ADDR AN8855_ADDR
+#define AN8855_CL22_ADDR GENMASK(8, 4)
+
+#define AN8855_PHY_SELECT_PAGE 0x1f
+
+#define AN8855_NUM_PHY_PORT 5
+
+#endif /* _NET_AN8855_H */
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [net-next PATCH v15 07/12] nvmem: an8855: Add support for Airoha AN8855 Switch EFUSE
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
` (5 preceding siblings ...)
2025-06-26 21:23 ` [net-next PATCH v15 06/12] net: mdio: Add Airoha AN8855 Switch MDIO PBUS Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
2025-06-26 21:23 ` [net-next PATCH v15 09/12] mfd: an8855: Add support for Airoha AN8855 Switch MFD Christian Marangi
` (4 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Add support for Airoha AN8855 Switch EFUSE. These EFUSE might be used
for calibration data for the internal switch PHYs.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/nvmem/Kconfig | 11 ++++++
drivers/nvmem/Makefile | 2 ++
drivers/nvmem/an8855-efuse.c | 68 ++++++++++++++++++++++++++++++++++++
3 files changed, 81 insertions(+)
create mode 100644 drivers/nvmem/an8855-efuse.c
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index d370b2ad11e7..8fb1a0efd431 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -28,6 +28,17 @@ source "drivers/nvmem/layouts/Kconfig"
# Devices
+config NVMEM_AN8855_EFUSE
+ tristate "Airoha AN8855 eFuse support"
+ depends on MFD_AIROHA_AN8855 || COMPILE_TEST
+ help
+ Say y here to enable support for reading eFuses on Airoha AN8855
+ Switch. These are e.g. used to store factory programmed
+ calibration data required for the PHY.
+
+ This driver can also be built as a module. If so, the module will
+ be called nvmem-an8855-efuse.
+
config NVMEM_APPLE_EFUSES
tristate "Apple eFuse support"
depends on ARCH_APPLE || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 2021d59688db..5c9e6e450181 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -10,6 +10,8 @@ nvmem_layouts-y := layouts.o
obj-y += layouts/
# Devices
+obj-$(CONFIG_NVMEM_AN8855_EFUSE) += nvmem-an8855-efuse.o
+nvmem-an8855-efuse-y := an8855-efuse.o
obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
nvmem-apple-efuses-y := apple-efuses.o
obj-$(CONFIG_NVMEM_APPLE_SPMI) += apple_nvmem_spmi.o
diff --git a/drivers/nvmem/an8855-efuse.c b/drivers/nvmem/an8855-efuse.c
new file mode 100644
index 000000000000..d1afde6f623f
--- /dev/null
+++ b/drivers/nvmem/an8855-efuse.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Airoha AN8855 Switch EFUSE Driver
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define AN8855_EFUSE_CELL 50
+
+#define AN8855_EFUSE_DATA0 0x1000a500
+#define AN8855_EFUSE_R50O GENMASK(30, 24)
+
+static int an8855_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct regmap *regmap = context;
+
+ return regmap_bulk_read(regmap, AN8855_EFUSE_DATA0 + offset,
+ val, bytes / sizeof(u32));
+}
+
+static int an8855_efuse_probe(struct platform_device *pdev)
+{
+ struct nvmem_config an8855_nvmem_config = {
+ .name = "an8855-efuse",
+ .size = AN8855_EFUSE_CELL * sizeof(u32),
+ .stride = sizeof(u32),
+ .word_size = sizeof(u32),
+ .reg_read = an8855_efuse_read,
+ };
+ struct device *dev = &pdev->dev;
+ struct nvmem_device *nvmem;
+ struct regmap *regmap;
+
+ /* Assign NVMEM priv to MFD regmap */
+ regmap = dev_get_regmap(dev->parent, NULL);
+ if (!regmap)
+ return -ENOENT;
+
+ an8855_nvmem_config.priv = regmap;
+ an8855_nvmem_config.dev = dev;
+ nvmem = devm_nvmem_register(dev, &an8855_nvmem_config);
+
+ return PTR_ERR_OR_ZERO(nvmem);
+}
+
+static const struct of_device_id an8855_efuse_of_match[] = {
+ { .compatible = "airoha,an8855-efuse", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, an8855_efuse_of_match);
+
+static struct platform_driver an8855_efuse_driver = {
+ .probe = an8855_efuse_probe,
+ .driver = {
+ .name = "an8855-efuse",
+ .of_match_table = an8855_efuse_of_match,
+ },
+};
+module_platform_driver(an8855_efuse_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_DESCRIPTION("Driver for AN8855 Switch EFUSE");
+MODULE_LICENSE("GPL");
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [net-next PATCH v15 09/12] mfd: an8855: Add support for Airoha AN8855 Switch MFD
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
` (6 preceding siblings ...)
2025-06-26 21:23 ` [net-next PATCH v15 07/12] nvmem: an8855: Add support for Airoha AN8855 Switch EFUSE Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
2025-07-02 16:12 ` Lee Jones
2025-06-26 21:23 ` [net-next PATCH v15 10/12] net: phy: Add Airoha AN8855 Internal Switch Gigabit PHY Christian Marangi
` (3 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Add support for Airoha AN8855 Switch MFD that provide support for a DSA
switch and a NVMEM provider. Also provide support for the PBUS MDIO
to access the internal PHYs address from the switch registers to permit
the usage of a single regmap to handle both switch and PHYs.
An interesting HW bug wes discovered with the implementation of the MDIO
PBUS where the PHY status is not correctly detected if the PBUS is used
to read the PHY BMSR. For the only BMSR register, it's required to read
the address directly from the MDIO bus.
A check and a workaround is implemented to address this in the
regmap_read function.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/mfd/Kconfig | 12 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/airoha-an8855.c | 393 ++++++++++++++++++++++++++++++++++++
3 files changed, 406 insertions(+)
create mode 100644 drivers/mfd/airoha-an8855.c
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6fb3768e3d71..f2bfd6c9fc5f 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -53,6 +53,18 @@ config MFD_ALTERA_SYSMGR
using regmap_mmio accesses for ARM32 parts and SMC calls to
EL3 for ARM64 parts.
+config MFD_AIROHA_AN8855
+ tristate "Airoha AN8855 Switch Core"
+ select MFD_CORE
+ select MDIO_DEVICE
+ depends on NETDEVICES && OF
+ help
+ Support for the Airoha AN8855 Switch Core. This is an SoC
+ that provides various peripherals, to count, i2c, an Ethrnet
+ Switch, a CPU timer, GPIO, eFUSE.
+
+ Currently it provides a DSA switch and a NVMEM provider.
+
config MFD_ACT8945A
tristate "Active-semi ACT8945A"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 79495f9f3457..f541b513f41e 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o
obj-$(CONFIG_MFD_88PM800) += 88pm800.o 88pm80x.o
obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
obj-$(CONFIG_MFD_88PM886_PMIC) += 88pm886.o
+obj-$(CONFIG_MFD_AIROHA_AN8855) += airoha-an8855.o
obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
diff --git a/drivers/mfd/airoha-an8855.c b/drivers/mfd/airoha-an8855.c
new file mode 100644
index 000000000000..bb03a2436f25
--- /dev/null
+++ b/drivers/mfd/airoha-an8855.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Core driver for Airoha AN8855 Switch
+ */
+
+#include <linux/bitfield.h>
+#include <linux/dsa/an8855.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/core.h>
+#include <linux/mdio.h>
+#include <linux/mdio/mdio-regmap.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/regmap.h>
+
+/* Register for HW trap status */
+#define AN8855_HWTRAP 0x1000009c
+
+#define AN8855_CREV 0x10005000
+#define AN8855_ID 0x8855
+
+#define AN8855_RG_GPHY_AFE_PWD 0x1028c840
+
+/* MII Registers */
+#define AN8855_PHY_SELECT_PAGE 0x1f
+#define AN8855_PHY_PAGE GENMASK(2, 0)
+#define AN8855_PHY_PAGE_STANDARD FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
+#define AN8855_PHY_PAGE_EXTENDED_1 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
+#define AN8855_PHY_PAGE_EXTENDED_4 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x4)
+
+/* MII Registers Page 4 */
+#define AN8855_PBUS_MODE 0x10
+#define AN8855_PBUS_MODE_ADDR_FIXED 0x0
+#define AN8855_PBUS_MODE_ADDR_INCR BIT(15)
+#define AN8855_PBUS_WR_ADDR_HIGH 0x11
+#define AN8855_PBUS_WR_ADDR_LOW 0x12
+#define AN8855_PBUS_WR_DATA_HIGH 0x13
+#define AN8855_PBUS_WR_DATA_LOW 0x14
+#define AN8855_PBUS_RD_ADDR_HIGH 0x15
+#define AN8855_PBUS_RD_ADDR_LOW 0x16
+#define AN8855_PBUS_RD_DATA_HIGH 0x17
+#define AN8855_PBUS_RD_DATA_LOW 0x18
+
+struct an8855_core_priv {
+ struct mii_bus *bus;
+
+ unsigned int switch_addr;
+};
+
+static const struct mfd_cell an8855_core_childs[] = {
+ {
+ .name = "an8855-efuse",
+ .of_compatible = "airoha,an8855-efuse",
+ }, {
+ .name = "an8855-switch",
+ .of_compatible = "airoha,an8855-switch",
+ }, {
+ .name = "an8855-mdio",
+ .of_compatible = "airoha,an8855-mdio",
+ }
+};
+
+static bool an8855_is_pbus_bmcr_reg(u32 reg)
+{
+ if ((reg & ~(AN8855_GPHY_PORT | AN8855_ADDR)) != AN8855_GPHY_ACCESS)
+ return false;
+
+ if ((reg & AN8855_ADDR) != FIELD_PREP_CONST(AN8855_CL22_ADDR,
+ MII_BMSR))
+ return false;
+
+ return true;
+}
+
+/* PHY page is Global for every Switch PHY.
+ * Configure it to 4 (as Switch PAGE) and keep it that way.
+ * Page selection doesn't affect the first PHY address from 0x0 to
+ * 0xf and we use PBUS to access the PHY address.
+ */
+static int an8855_mii_set_page(struct an8855_core_priv *priv, u8 addr,
+ u8 page) __must_hold(&priv->bus->mdio_lock)
+{
+ struct mii_bus *bus = priv->bus;
+ int ret;
+
+ ret = __mdiobus_write(bus, addr, AN8855_PHY_SELECT_PAGE, page);
+ if (ret)
+ dev_err_ratelimited(&bus->dev, "failed to set mii page\n");
+
+ return ret;
+}
+
+static int an8855_mii_read32(struct mii_bus *bus, u8 phy_id, u32 reg,
+ u32 *val) __must_hold(&bus->mdio_lock)
+{
+ int lo, hi, ret;
+
+ ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
+ AN8855_PBUS_MODE_ADDR_FIXED);
+ if (ret)
+ goto err;
+
+ ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_HIGH,
+ upper_16_bits(reg));
+ if (ret)
+ goto err;
+
+ ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_LOW,
+ lower_16_bits(reg));
+ if (ret)
+ goto err;
+
+ hi = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_HIGH);
+ if (hi < 0) {
+ ret = hi;
+ goto err;
+ }
+
+ lo = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_LOW);
+ if (lo < 0) {
+ ret = lo;
+ goto err;
+ }
+
+ *val = ((u16)hi << 16) | ((u16)lo & 0xffff);
+
+ return 0;
+err:
+ dev_err_ratelimited(&bus->dev, "failed to read register\n");
+ return ret;
+}
+
+static int an8855_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
+{
+ struct an8855_core_priv *priv = ctx;
+ struct mii_bus *bus = priv->bus;
+ u16 addr = priv->switch_addr;
+ int ret;
+
+ /* Workaround a HW BUG where using only PBUS for
+ * accessing internal PHY register cause the port status
+ * to not be correctly detected. It seems BMSR is required
+ * to go through direct MDIO read or is never refreshed.
+ *
+ * A theory about this is that PHY sideband signal is
+ * checked only with MDIO operation on BMSR and using
+ * PBUS doesn't trigger the check.
+ *
+ * Using interrupt to detect Link Up might be possible
+ * but it's considered an optional feature for the Switch
+ * reference (hence there could be devices with the
+ * interrupt line not connected)
+ */
+ if (an8855_is_pbus_bmcr_reg(reg)) {
+ addr += FIELD_GET(AN8855_GPHY_PORT, reg);
+ *val = mdiobus_read(bus, addr, MII_BMSR);
+ return 0;
+ }
+
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
+ if (ret < 0)
+ goto exit;
+
+ ret = an8855_mii_read32(bus, addr, reg, val);
+
+exit:
+ mutex_unlock(&bus->mdio_lock);
+
+ return ret < 0 ? ret : 0;
+}
+
+static int an8855_mii_write32(struct mii_bus *bus, u8 phy_id, u32 reg,
+ u32 val) __must_hold(&bus->mdio_lock)
+{
+ int ret;
+
+ ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
+ AN8855_PBUS_MODE_ADDR_FIXED);
+ if (ret)
+ goto err;
+
+ ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_HIGH,
+ upper_16_bits(reg));
+ if (ret)
+ goto err;
+ ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_LOW,
+ lower_16_bits(reg));
+ if (ret)
+ goto err;
+
+ ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_HIGH,
+ upper_16_bits(val));
+ if (ret)
+ goto err;
+
+ ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_LOW,
+ lower_16_bits(val));
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ dev_err_ratelimited(&bus->dev,
+ "failed to write an8855 register\n");
+ return ret;
+}
+
+static int an8855_regmap_write(void *ctx, uint32_t reg, uint32_t val)
+{
+ struct an8855_core_priv *priv = ctx;
+ struct mii_bus *bus = priv->bus;
+ u16 addr = priv->switch_addr;
+ int ret;
+
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
+ if (ret)
+ goto exit;
+
+ ret = an8855_mii_write32(bus, addr, reg, val);
+
+exit:
+ mutex_unlock(&bus->mdio_lock);
+
+ return ret < 0 ? ret : 0;
+}
+
+static int an8855_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask,
+ uint32_t write_val)
+{
+ struct an8855_core_priv *priv = ctx;
+ struct mii_bus *bus = priv->bus;
+ u16 addr = priv->switch_addr;
+ u32 val;
+ int ret;
+
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
+ if (ret)
+ goto exit;
+
+ ret = an8855_mii_read32(bus, addr, reg, &val);
+ if (ret < 0)
+ goto exit;
+
+ val &= ~mask;
+ val |= write_val;
+ ret = an8855_mii_write32(bus, addr, reg, val);
+
+exit:
+ mutex_unlock(&bus->mdio_lock);
+
+ return ret < 0 ? ret : 0;
+}
+
+static const struct regmap_range an8855_readable_ranges[] = {
+ regmap_reg_range(0x10000000, 0x10000fff), /* SCU */
+ regmap_reg_range(0x10001000, 0x10001fff), /* RBUS */
+ regmap_reg_range(0x10002000, 0x10002fff), /* MCU */
+ regmap_reg_range(0x10005000, 0x10005fff), /* SYS SCU */
+ regmap_reg_range(0x10007000, 0x10007fff), /* I2C Slave */
+ regmap_reg_range(0x10008000, 0x10008fff), /* I2C Master */
+ regmap_reg_range(0x10009000, 0x10009fff), /* PDMA */
+ regmap_reg_range(0x1000a100, 0x1000a2ff), /* General Purpose Timer */
+ regmap_reg_range(0x1000a200, 0x1000a2ff), /* GPU timer */
+ regmap_reg_range(0x1000a300, 0x1000a3ff), /* GPIO */
+ regmap_reg_range(0x1000a400, 0x1000a5ff), /* EFUSE */
+ regmap_reg_range(0x1000c000, 0x1000cfff), /* GDMP CSR */
+ regmap_reg_range(0x10010000, 0x1001ffff), /* GDMP SRAM */
+ regmap_reg_range(0x10200000, 0x10203fff), /* Switch - ARL Global */
+ regmap_reg_range(0x10204000, 0x10207fff), /* Switch - BMU */
+ regmap_reg_range(0x10208000, 0x1020bfff), /* Switch - ARL Port */
+ regmap_reg_range(0x1020c000, 0x1020cfff), /* Switch - SCH */
+ regmap_reg_range(0x10210000, 0x10213fff), /* Switch - MAC */
+ regmap_reg_range(0x10214000, 0x10217fff), /* Switch - MIB */
+ regmap_reg_range(0x10218000, 0x1021bfff), /* Switch - Port Control */
+ regmap_reg_range(0x1021c000, 0x1021ffff), /* Switch - TOP */
+ regmap_reg_range(0x10220000, 0x1022ffff), /* SerDes */
+ regmap_reg_range(0x10286000, 0x10286fff), /* RG Batcher */
+ regmap_reg_range(0x1028c000, 0x1028ffff), /* ETHER_SYS */
+ regmap_reg_range(0x30000000, 0x37ffffff), /* I2C EEPROM */
+ regmap_reg_range(0x38000000, 0x3fffffff), /* BOOT_ROM */
+ regmap_reg_range(0xa0000000, 0xbfffffff), /* GPHY */
+};
+
+static const struct regmap_access_table an8855_readable_table = {
+ .yes_ranges = an8855_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(an8855_readable_ranges),
+};
+
+static const struct regmap_config an8855_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0xbfffffff,
+ .reg_read = an8855_regmap_read,
+ .reg_write = an8855_regmap_write,
+ .reg_update_bits = an8855_regmap_update_bits,
+ .disable_locking = true,
+ .rd_table = &an8855_readable_table,
+};
+
+static int an8855_read_switch_id(struct device *dev, struct regmap *regmap)
+{
+ u32 id;
+ int ret;
+
+ ret = regmap_read(regmap, AN8855_CREV, &id);
+ if (ret)
+ return ret;
+
+ if (id != AN8855_ID) {
+ dev_err(dev, "Detected Switch ID %x but %x was expected\n",
+ id, AN8855_ID);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int an8855_core_probe(struct mdio_device *mdiodev)
+{
+ struct device *dev = &mdiodev->dev;
+ struct an8855_core_priv *priv;
+ struct gpio_desc *reset_gpio;
+ struct regmap *regmap;
+ u32 val;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->bus = mdiodev->bus;
+ priv->switch_addr = mdiodev->addr;
+ /* No DMA for mdiobus, mute warning for DMA mask not set */
+ dev->dma_mask = &dev->coherent_dma_mask;
+
+ regmap = devm_regmap_init(dev, NULL, priv, &an8855_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "regmap initialization failed\n");
+
+ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio))
+ return PTR_ERR(reset_gpio);
+
+ if (reset_gpio) {
+ usleep_range(100000, 150000);
+ gpiod_set_value_cansleep(reset_gpio, 0);
+ usleep_range(100000, 150000);
+ gpiod_set_value_cansleep(reset_gpio, 1);
+
+ /* Poll HWTRAP reg to wait for Switch to fully Init */
+ ret = regmap_read_poll_timeout(regmap, AN8855_HWTRAP, val,
+ val, 20, 200000);
+ if (ret)
+ return ret;
+ }
+
+ ret = an8855_read_switch_id(dev, regmap);
+ if (ret)
+ return ret;
+
+ /* Release global PHY power down */
+ ret = regmap_write(regmap, AN8855_RG_GPHY_AFE_PWD, 0x0);
+ if (ret)
+ return ret;
+
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, an8855_core_childs,
+ ARRAY_SIZE(an8855_core_childs), NULL, 0,
+ NULL);
+}
+
+static const struct of_device_id an8855_core_of_match[] = {
+ { .compatible = "airoha,an8855" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, an8855_core_of_match);
+
+static struct mdio_driver an8855_core_driver = {
+ .probe = an8855_core_probe,
+ .mdiodrv.driver = {
+ .name = "an8855",
+ .of_match_table = an8855_core_of_match,
+ },
+};
+mdio_module_driver(an8855_core_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_DESCRIPTION("Driver for Airoha AN8855 MFD");
+MODULE_LICENSE("GPL");
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [net-next PATCH v15 09/12] mfd: an8855: Add support for Airoha AN8855 Switch MFD
2025-06-26 21:23 ` [net-next PATCH v15 09/12] mfd: an8855: Add support for Airoha AN8855 Switch MFD Christian Marangi
@ 2025-07-02 16:12 ` Lee Jones
0 siblings, 0 replies; 18+ messages in thread
From: Lee Jones @ 2025-07-02 16:12 UTC (permalink / raw)
To: Christian Marangi
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Vladimir Oltean, Srinivas Kandagatla, Heiner Kallweit,
Russell King, Chester A. Unal, Daniel Golle, DENG Qingfang,
Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
> Add support for Airoha AN8855 Switch MFD that provide support for a DSA
Drop the MFD part from here and the subject line.
> switch and a NVMEM provider. Also provide support for the PBUS MDIO
> to access the internal PHYs address from the switch registers to permit
> the usage of a single regmap to handle both switch and PHYs.
>
> An interesting HW bug wes discovered with the implementation of the MDIO
> PBUS where the PHY status is not correctly detected if the PBUS is used
> to read the PHY BMSR. For the only BMSR register, it's required to read
> the address directly from the MDIO bus.
>
> A check and a workaround is implemented to address this in the
> regmap_read function.
Couple of final points.
Some of them are repeated from previous reviews.
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> ---
> drivers/mfd/Kconfig | 12 ++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/airoha-an8855.c | 393 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 406 insertions(+)
> create mode 100644 drivers/mfd/airoha-an8855.c
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 6fb3768e3d71..f2bfd6c9fc5f 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -53,6 +53,18 @@ config MFD_ALTERA_SYSMGR
> using regmap_mmio accesses for ARM32 parts and SMC calls to
> EL3 for ARM64 parts.
>
> +config MFD_AIROHA_AN8855
> + tristate "Airoha AN8855 Switch Core"
> + select MFD_CORE
> + select MDIO_DEVICE
> + depends on NETDEVICES && OF
> + help
> + Support for the Airoha AN8855 Switch Core. This is an SoC
> + that provides various peripherals, to count, i2c, an Ethrnet
> + Switch, a CPU timer, GPIO, eFUSE.
> +
> + Currently it provides a DSA switch and a NVMEM provider.
> +
> config MFD_ACT8945A
> tristate "Active-semi ACT8945A"
> select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 79495f9f3457..f541b513f41e 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o
> obj-$(CONFIG_MFD_88PM800) += 88pm800.o 88pm80x.o
> obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
> obj-$(CONFIG_MFD_88PM886_PMIC) += 88pm886.o
> +obj-$(CONFIG_MFD_AIROHA_AN8855) += airoha-an8855.o
> obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
> obj-$(CONFIG_MFD_SM501) += sm501.o
> obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
> diff --git a/drivers/mfd/airoha-an8855.c b/drivers/mfd/airoha-an8855.c
> new file mode 100644
> index 000000000000..bb03a2436f25
> --- /dev/null
> +++ b/drivers/mfd/airoha-an8855.c
> @@ -0,0 +1,393 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Core driver for Airoha AN8855 Switch
No Copyright?
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/dsa/an8855.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/mfd/core.h>
> +#include <linux/mdio.h>
> +#include <linux/mdio/mdio-regmap.h>
> +#include <linux/module.h>
> +#include <linux/phy.h>
> +#include <linux/regmap.h>
> +
> +/* Register for HW trap status */
> +#define AN8855_HWTRAP 0x1000009c
> +
> +#define AN8855_CREV 0x10005000
Please change the name of this or comment it.
I still have no idea what it is.
> +#define AN8855_ID 0x8855
Device ID, Chip ID, Platform ID, Driver's ID?
> +#define AN8855_RG_GPHY_AFE_PWD 0x1028c840
No clue. Comment please.
> +/* MII Registers */
> +#define AN8855_PHY_SELECT_PAGE 0x1f
> +#define AN8855_PHY_PAGE GENMASK(2, 0)
> +#define AN8855_PHY_PAGE_STANDARD FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
> +#define AN8855_PHY_PAGE_EXTENDED_1 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
> +#define AN8855_PHY_PAGE_EXTENDED_4 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x4)
> +
> +/* MII Registers Page 4 */
> +#define AN8855_PBUS_MODE 0x10
> +#define AN8855_PBUS_MODE_ADDR_FIXED 0x0
> +#define AN8855_PBUS_MODE_ADDR_INCR BIT(15)
> +#define AN8855_PBUS_WR_ADDR_HIGH 0x11
> +#define AN8855_PBUS_WR_ADDR_LOW 0x12
> +#define AN8855_PBUS_WR_DATA_HIGH 0x13
> +#define AN8855_PBUS_WR_DATA_LOW 0x14
> +#define AN8855_PBUS_RD_ADDR_HIGH 0x15
> +#define AN8855_PBUS_RD_ADDR_LOW 0x16
> +#define AN8855_PBUS_RD_DATA_HIGH 0x17
> +#define AN8855_PBUS_RD_DATA_LOW 0x18
> +
> +struct an8855_core_priv {
> + struct mii_bus *bus;
> +
Do we need this separation between only 2 attributes?
> + unsigned int switch_addr;
> +};
> +
> +static const struct mfd_cell an8855_core_childs[] = {
an8855_{devs,cells}
> + {
> + .name = "an8855-efuse",
> + .of_compatible = "airoha,an8855-efuse",
MFD_CELL_OF()
> + }, {
> + .name = "an8855-switch",
> + .of_compatible = "airoha,an8855-switch",
> + }, {
> + .name = "an8855-mdio",
> + .of_compatible = "airoha,an8855-mdio",
> + }
> +};
> +
> +static bool an8855_is_pbus_bmcr_reg(u32 reg)
> +{
> + if ((reg & ~(AN8855_GPHY_PORT | AN8855_ADDR)) != AN8855_GPHY_ACCESS)
> + return false;
> +
> + if ((reg & AN8855_ADDR) != FIELD_PREP_CONST(AN8855_CL22_ADDR,
> + MII_BMSR))
> + return false;
> +
> + return true;
> +}
> +
> +/* PHY page is Global for every Switch PHY.
> + * Configure it to 4 (as Switch PAGE) and keep it that way.
> + * Page selection doesn't affect the first PHY address from 0x0 to
> + * 0xf and we use PBUS to access the PHY address.
> + */
Proper multi-line comments please.
> +static int an8855_mii_set_page(struct an8855_core_priv *priv, u8 addr,
> + u8 page) __must_hold(&priv->bus->mdio_lock)
> +{
> + struct mii_bus *bus = priv->bus;
> + int ret;
> +
> + ret = __mdiobus_write(bus, addr, AN8855_PHY_SELECT_PAGE, page);
> + if (ret)
> + dev_err_ratelimited(&bus->dev, "failed to set mii page\n");
> +
> + return ret;
> +}
> +
> +static int an8855_mii_read32(struct mii_bus *bus, u8 phy_id, u32 reg,
> + u32 *val) __must_hold(&bus->mdio_lock)
> +{
> + int lo, hi, ret;
> +
> + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
> + AN8855_PBUS_MODE_ADDR_FIXED);
You can use up to 100-chars, if you want to avoid all of this wraps.
> + if (ret)
> + goto err;
> +
> + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_HIGH,
> + upper_16_bits(reg));
> + if (ret)
> + goto err;
> +
> + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_LOW,
> + lower_16_bits(reg));
> + if (ret)
> + goto err;
> +
> + hi = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_HIGH);
> + if (hi < 0) {
> + ret = hi;
> + goto err;
> + }
> +
> + lo = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_LOW);
> + if (lo < 0) {
> + ret = lo;
> + goto err;
> + }
> +
> + *val = ((u16)hi << 16) | ((u16)lo & 0xffff);
> +
> + return 0;
> +err:
> + dev_err_ratelimited(&bus->dev, "failed to read register\n");
> + return ret;
> +}
> +
> +static int an8855_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
> +{
> + struct an8855_core_priv *priv = ctx;
> + struct mii_bus *bus = priv->bus;
> + u16 addr = priv->switch_addr;
> + int ret;
> +
> + /* Workaround a HW BUG where using only PBUS for
> + * accessing internal PHY register cause the port status
> + * to not be correctly detected. It seems BMSR is required
> + * to go through direct MDIO read or is never refreshed.
> + *
> + * A theory about this is that PHY sideband signal is
> + * checked only with MDIO operation on BMSR and using
> + * PBUS doesn't trigger the check.
> + *
> + * Using interrupt to detect Link Up might be possible
> + * but it's considered an optional feature for the Switch
> + * reference (hence there could be devices with the
> + * interrupt line not connected)
> + */
Re: comment formatting - as above and throughout.
> + if (an8855_is_pbus_bmcr_reg(reg)) {
> + addr += FIELD_GET(AN8855_GPHY_PORT, reg);
> + *val = mdiobus_read(bus, addr, MII_BMSR);
> + return 0;
> + }
> +
> + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> + ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
> + if (ret < 0)
> + goto exit;
> +
> + ret = an8855_mii_read32(bus, addr, reg, val);
> +
> +exit:
> + mutex_unlock(&bus->mdio_lock);
> +
> + return ret < 0 ? ret : 0;
> +}
> +
> +static int an8855_mii_write32(struct mii_bus *bus, u8 phy_id, u32 reg,
> + u32 val) __must_hold(&bus->mdio_lock)
> +{
> + int ret;
> +
> + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
> + AN8855_PBUS_MODE_ADDR_FIXED);
> + if (ret)
> + goto err;
> +
> + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_HIGH,
> + upper_16_bits(reg));
> + if (ret)
> + goto err;
> + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_LOW,
> + lower_16_bits(reg));
> + if (ret)
> + goto err;
> +
> + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_HIGH,
> + upper_16_bits(val));
> + if (ret)
> + goto err;
> +
> + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_LOW,
> + lower_16_bits(val));
> + if (ret)
> + goto err;
> +
> + return 0;
> +err:
> + dev_err_ratelimited(&bus->dev,
> + "failed to write an8855 register\n");
> + return ret;
> +}
> +
> +static int an8855_regmap_write(void *ctx, uint32_t reg, uint32_t val)
> +{
> + struct an8855_core_priv *priv = ctx;
> + struct mii_bus *bus = priv->bus;
> + u16 addr = priv->switch_addr;
> + int ret;
> +
> + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> + ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
> + if (ret)
> + goto exit;
> +
> + ret = an8855_mii_write32(bus, addr, reg, val);
> +
> +exit:
> + mutex_unlock(&bus->mdio_lock);
> +
> + return ret < 0 ? ret : 0;
> +}
> +
> +static int an8855_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask,
> + uint32_t write_val)
> +{
> + struct an8855_core_priv *priv = ctx;
> + struct mii_bus *bus = priv->bus;
> + u16 addr = priv->switch_addr;
> + u32 val;
> + int ret;
> +
> + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> + ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
> + if (ret)
> + goto exit;
> +
> + ret = an8855_mii_read32(bus, addr, reg, &val);
> + if (ret < 0)
> + goto exit;
> +
> + val &= ~mask;
> + val |= write_val;
> + ret = an8855_mii_write32(bus, addr, reg, val);
> +
> +exit:
> + mutex_unlock(&bus->mdio_lock);
> +
> + return ret < 0 ? ret : 0;
> +}
> +
> +static const struct regmap_range an8855_readable_ranges[] = {
> + regmap_reg_range(0x10000000, 0x10000fff), /* SCU */
> + regmap_reg_range(0x10001000, 0x10001fff), /* RBUS */
> + regmap_reg_range(0x10002000, 0x10002fff), /* MCU */
> + regmap_reg_range(0x10005000, 0x10005fff), /* SYS SCU */
> + regmap_reg_range(0x10007000, 0x10007fff), /* I2C Slave */
> + regmap_reg_range(0x10008000, 0x10008fff), /* I2C Master */
> + regmap_reg_range(0x10009000, 0x10009fff), /* PDMA */
> + regmap_reg_range(0x1000a100, 0x1000a2ff), /* General Purpose Timer */
> + regmap_reg_range(0x1000a200, 0x1000a2ff), /* GPU timer */
> + regmap_reg_range(0x1000a300, 0x1000a3ff), /* GPIO */
> + regmap_reg_range(0x1000a400, 0x1000a5ff), /* EFUSE */
> + regmap_reg_range(0x1000c000, 0x1000cfff), /* GDMP CSR */
> + regmap_reg_range(0x10010000, 0x1001ffff), /* GDMP SRAM */
> + regmap_reg_range(0x10200000, 0x10203fff), /* Switch - ARL Global */
> + regmap_reg_range(0x10204000, 0x10207fff), /* Switch - BMU */
> + regmap_reg_range(0x10208000, 0x1020bfff), /* Switch - ARL Port */
> + regmap_reg_range(0x1020c000, 0x1020cfff), /* Switch - SCH */
> + regmap_reg_range(0x10210000, 0x10213fff), /* Switch - MAC */
> + regmap_reg_range(0x10214000, 0x10217fff), /* Switch - MIB */
> + regmap_reg_range(0x10218000, 0x1021bfff), /* Switch - Port Control */
> + regmap_reg_range(0x1021c000, 0x1021ffff), /* Switch - TOP */
> + regmap_reg_range(0x10220000, 0x1022ffff), /* SerDes */
> + regmap_reg_range(0x10286000, 0x10286fff), /* RG Batcher */
> + regmap_reg_range(0x1028c000, 0x1028ffff), /* ETHER_SYS */
> + regmap_reg_range(0x30000000, 0x37ffffff), /* I2C EEPROM */
> + regmap_reg_range(0x38000000, 0x3fffffff), /* BOOT_ROM */
> + regmap_reg_range(0xa0000000, 0xbfffffff), /* GPHY */
> +};
> +
> +static const struct regmap_access_table an8855_readable_table = {
> + .yes_ranges = an8855_readable_ranges,
> + .n_yes_ranges = ARRAY_SIZE(an8855_readable_ranges),
> +};
> +
> +static const struct regmap_config an8855_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0xbfffffff,
> + .reg_read = an8855_regmap_read,
> + .reg_write = an8855_regmap_write,
> + .reg_update_bits = an8855_regmap_update_bits,
> + .disable_locking = true,
> + .rd_table = &an8855_readable_table,
> +};
> +
> +static int an8855_read_switch_id(struct device *dev, struct regmap *regmap)
> +{
> + u32 id;
> + int ret;
> +
> + ret = regmap_read(regmap, AN8855_CREV, &id);
> + if (ret)
> + return ret;
> +
> + if (id != AN8855_ID) {
> + dev_err(dev, "Detected Switch ID %x but %x was expected\n",
> + id, AN8855_ID);
> + return -ENODEV;
> + }
> +
> + return 0;
> +}
> +
> +static int an8855_core_probe(struct mdio_device *mdiodev)
> +{
> + struct device *dev = &mdiodev->dev;
> + struct an8855_core_priv *priv;
> + struct gpio_desc *reset_gpio;
> + struct regmap *regmap;
> + u32 val;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->bus = mdiodev->bus;
> + priv->switch_addr = mdiodev->addr;
> + /* No DMA for mdiobus, mute warning for DMA mask not set */
> + dev->dma_mask = &dev->coherent_dma_mask;
> +
> + regmap = devm_regmap_init(dev, NULL, priv, &an8855_regmap_config);
> + if (IS_ERR(regmap))
> + return dev_err_probe(dev, PTR_ERR(regmap),
> + "regmap initialization failed\n");
> +
> + reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> + if (IS_ERR(reset_gpio))
> + return PTR_ERR(reset_gpio);
> +
> + if (reset_gpio) {
> + usleep_range(100000, 150000);
> + gpiod_set_value_cansleep(reset_gpio, 0);
> + usleep_range(100000, 150000);
> + gpiod_set_value_cansleep(reset_gpio, 1);
> +
> + /* Poll HWTRAP reg to wait for Switch to fully Init */
> + ret = regmap_read_poll_timeout(regmap, AN8855_HWTRAP, val,
> + val, 20, 200000);
> + if (ret)
> + return ret;
> + }
> +
> + ret = an8855_read_switch_id(dev, regmap);
> + if (ret)
> + return ret;
> +
> + /* Release global PHY power down */
> + ret = regmap_write(regmap, AN8855_RG_GPHY_AFE_PWD, 0x0);
> + if (ret)
> + return ret;
> +
> + return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, an8855_core_childs,
> + ARRAY_SIZE(an8855_core_childs), NULL, 0,
> + NULL);
> +}
> +
> +static const struct of_device_id an8855_core_of_match[] = {
> + { .compatible = "airoha,an8855" },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, an8855_core_of_match);
> +
> +static struct mdio_driver an8855_core_driver = {
> + .probe = an8855_core_probe,
> + .mdiodrv.driver = {
> + .name = "an8855",
> + .of_match_table = an8855_core_of_match,
> + },
> +};
> +mdio_module_driver(an8855_core_driver);
> +
> +MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
> +MODULE_DESCRIPTION("Driver for Airoha AN8855 MFD");
Drop MFD.
> +MODULE_LICENSE("GPL");
> --
> 2.48.1
>
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 18+ messages in thread
* [net-next PATCH v15 10/12] net: phy: Add Airoha AN8855 Internal Switch Gigabit PHY
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
` (7 preceding siblings ...)
2025-06-26 21:23 ` [net-next PATCH v15 09/12] mfd: an8855: Add support for Airoha AN8855 Switch MFD Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
2025-06-26 21:23 ` [net-next PATCH v15 11/12] MAINTAINERS: add myself as maintainer for AN8855 Christian Marangi
` (2 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Add support for Airoha AN8855 Internal Switch Gigabit PHY.
This is a simple PHY driver to configure and calibrate the PHY for the
AN8855 Switch with the use of NVMEM cells.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/phy/Kconfig | 5 +
drivers/net/phy/Makefile | 1 +
drivers/net/phy/air_an8855.c | 261 +++++++++++++++++++++++++++++++++++
3 files changed, 267 insertions(+)
create mode 100644 drivers/net/phy/air_an8855.c
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 28acc6392cfc..d25f36c82c48 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -91,6 +91,11 @@ config AS21XXX_PHY
AS21210PB1 that all register with the PHY ID 0x7500 0x7500
before the firmware is loaded.
+config AIR_AN8855_PHY
+ tristate "Airoha AN8855 Internal Gigabit PHY"
+ help
+ Currently supports the internal Airoha AN8855 Switch PHY.
+
config AIR_EN8811H_PHY
tristate "Airoha EN8811H 2.5 Gigabit PHY"
help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index b4795aaf9c1c..734adf4a3855 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -29,6 +29,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m)
obj-$(CONFIG_ADIN_PHY) += adin.o
obj-$(CONFIG_ADIN1100_PHY) += adin1100.o
+obj-$(CONFIG_AIR_AN8855_PHY) += air_an8855.o
obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o
obj-$(CONFIG_AMD_PHY) += amd.o
obj-$(CONFIG_AMCC_QT2025_PHY) += qt2025.o
diff --git a/drivers/net/phy/air_an8855.c b/drivers/net/phy/air_an8855.c
new file mode 100644
index 000000000000..a740dbaacf9a
--- /dev/null
+++ b/drivers/net/phy/air_an8855.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Christian Marangi <ansuelsmth@gmail.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+
+#define AN8855_PHY_SELECT_PAGE 0x1f
+#define AN8855_PHY_PAGE GENMASK(2, 0)
+#define AN8855_PHY_PAGE_STANDARD FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
+#define AN8855_PHY_PAGE_EXTENDED_1 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
+
+/* MII Registers Page 1 */
+#define AN8855_PHY_EXT_REG_14 0x14
+#define AN8855_PHY_EN_DOWN_SHIFT BIT(4)
+
+/* R50 Calibration regs in MDIO_MMD_VEND1 */
+#define AN8855_PHY_R500HM_RSEL_TX_AB 0x174
+#define AN8855_PHY_R50OHM_RSEL_TX_A_EN BIT(15)
+#define AN8855_PHY_R50OHM_RSEL_TX_A GENMASK(14, 8)
+#define AN8855_PHY_R50OHM_RSEL_TX_B_EN BIT(7)
+#define AN8855_PHY_R50OHM_RSEL_TX_B GENMASK(6, 0)
+#define AN8855_PHY_R500HM_RSEL_TX_CD 0x175
+#define AN8855_PHY_R50OHM_RSEL_TX_C_EN BIT(15)
+#define AN8855_PHY_R50OHM_RSEL_TX_C GENMASK(14, 8)
+#define AN8855_PHY_R50OHM_RSEL_TX_D_EN BIT(7)
+#define AN8855_PHY_R50OHM_RSEL_TX_D GENMASK(6, 0)
+
+#define AN8855_SWITCH_EFUSE_R50O GENMASK(30, 24)
+
+/* PHY TX PAIR DELAY SELECT Register */
+#define AN8855_PHY_TX_PAIR_DLY_SEL_GBE 0x013
+#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_A_GBE GENMASK(14, 12)
+#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_B_GBE GENMASK(10, 8)
+#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_C_GBE GENMASK(6, 4)
+#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_D_GBE GENMASK(2, 0)
+/* PHY ADC Register */
+#define AN8855_PHY_RXADC_CTRL 0x0d8
+#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_A BIT(12)
+#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_B BIT(8)
+#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_C BIT(4)
+#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_D BIT(0)
+#define AN8855_PHY_RXADC_REV_0 0x0d9
+#define AN8855_PHY_RG_AD_RESERVE0_A GENMASK(15, 8)
+#define AN8855_PHY_RG_AD_RESERVE0_B GENMASK(7, 0)
+#define AN8855_PHY_RXADC_REV_1 0x0da
+#define AN8855_PHY_RG_AD_RESERVE0_C GENMASK(15, 8)
+#define AN8855_PHY_RG_AD_RESERVE0_D GENMASK(7, 0)
+
+#define AN8855_PHY_ID 0xc0ff0410
+
+struct air_an8855_priv {
+ bool needs_calibration;
+};
+
+static const u8 dsa_r50ohm_table[] = {
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 126, 122, 117,
+ 112, 109, 104, 101, 97, 94, 90, 88, 84, 80,
+ 78, 74, 72, 68, 66, 64, 61, 58, 56, 53,
+ 51, 48, 47, 44, 42, 40, 38, 36, 34, 32,
+ 31, 28, 27, 24, 24, 22, 20, 18, 16, 16,
+ 14, 12, 11, 9
+};
+
+static int en8855_get_r50ohm_val(struct device *dev, const char *calib_name,
+ u8 *dest)
+{
+ u32 shift_sel, val;
+ int ret;
+ int i;
+
+ ret = nvmem_cell_read_u32(dev, calib_name, &val);
+ if (ret)
+ return ret;
+
+ shift_sel = FIELD_GET(AN8855_SWITCH_EFUSE_R50O, val);
+ for (i = 0; i < ARRAY_SIZE(dsa_r50ohm_table); i++)
+ if (dsa_r50ohm_table[i] == shift_sel)
+ break;
+
+ if (i < 8 || i >= ARRAY_SIZE(dsa_r50ohm_table))
+ *dest = dsa_r50ohm_table[25];
+ else
+ *dest = dsa_r50ohm_table[i - 8];
+
+ return 0;
+}
+
+static int an8855_probe(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ struct air_an8855_priv *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->needs_calibration = of_property_present(dev->of_node,
+ "nvmem-cells");
+
+ phydev->priv = priv;
+
+ return 0;
+}
+
+static int an8855_get_downshift(struct phy_device *phydev, u8 *data)
+{
+ int val;
+
+ val = phy_read_paged(phydev, AN8855_PHY_PAGE_EXTENDED_1, AN8855_PHY_EXT_REG_14);
+ if (val < 0)
+ return val;
+
+ *data = val & AN8855_PHY_EN_DOWN_SHIFT ? DOWNSHIFT_DEV_DEFAULT_COUNT :
+ DOWNSHIFT_DEV_DISABLE;
+
+ return 0;
+}
+
+static int an8855_set_downshift(struct phy_device *phydev, u8 cnt)
+{
+ u16 ds = cnt != DOWNSHIFT_DEV_DISABLE ? AN8855_PHY_EN_DOWN_SHIFT : 0;
+
+ return phy_modify_paged(phydev, AN8855_PHY_PAGE_EXTENDED_1,
+ AN8855_PHY_EXT_REG_14, AN8855_PHY_EN_DOWN_SHIFT,
+ ds);
+}
+
+static int an8855_config_init(struct phy_device *phydev)
+{
+ struct air_an8855_priv *priv = phydev->priv;
+ struct device *dev = &phydev->mdio.dev;
+ int ret;
+
+ /* Enable HW auto downshift */
+ ret = an8855_set_downshift(phydev, DOWNSHIFT_DEV_DEFAULT_COUNT);
+ if (ret)
+ return ret;
+
+ if (priv->needs_calibration) {
+ u8 calibration_data[4];
+
+ ret = en8855_get_r50ohm_val(dev, "tx_a", &calibration_data[0]);
+ if (ret)
+ return ret;
+
+ ret = en8855_get_r50ohm_val(dev, "tx_b", &calibration_data[1]);
+ if (ret)
+ return ret;
+
+ ret = en8855_get_r50ohm_val(dev, "tx_c", &calibration_data[2]);
+ if (ret)
+ return ret;
+
+ ret = en8855_get_r50ohm_val(dev, "tx_d", &calibration_data[3]);
+ if (ret)
+ return ret;
+
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_R500HM_RSEL_TX_AB,
+ AN8855_PHY_R50OHM_RSEL_TX_A | AN8855_PHY_R50OHM_RSEL_TX_B,
+ FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_A, calibration_data[0]) |
+ FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_B, calibration_data[1]));
+ if (ret)
+ return ret;
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_R500HM_RSEL_TX_CD,
+ AN8855_PHY_R50OHM_RSEL_TX_C | AN8855_PHY_R50OHM_RSEL_TX_D,
+ FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_C, calibration_data[2]) |
+ FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_D, calibration_data[3]));
+ if (ret)
+ return ret;
+ }
+
+ /* Apply values to reduce signal noise */
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_TX_PAIR_DLY_SEL_GBE,
+ FIELD_PREP(AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_A_GBE, 0x4) |
+ FIELD_PREP(AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_C_GBE, 0x4));
+ if (ret)
+ return ret;
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_CTRL,
+ AN8855_PHY_RG_AD_SAMNPLE_PHSEL_A |
+ AN8855_PHY_RG_AD_SAMNPLE_PHSEL_C);
+ if (ret)
+ return ret;
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_REV_0,
+ FIELD_PREP(AN8855_PHY_RG_AD_RESERVE0_A, 0x1));
+ if (ret)
+ return ret;
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_REV_1,
+ FIELD_PREP(AN8855_PHY_RG_AD_RESERVE0_C, 0x1));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int an8855_get_tunable(struct phy_device *phydev,
+ struct ethtool_tunable *tuna, void *data)
+{
+ switch (tuna->id) {
+ case ETHTOOL_PHY_DOWNSHIFT:
+ return an8855_get_downshift(phydev, data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int an8855_set_tunable(struct phy_device *phydev,
+ struct ethtool_tunable *tuna, const void *data)
+{
+ switch (tuna->id) {
+ case ETHTOOL_PHY_DOWNSHIFT:
+ return an8855_set_downshift(phydev, *(const u8 *)data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int an8855_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, AN8855_PHY_SELECT_PAGE);
+}
+
+static int an8855_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, AN8855_PHY_SELECT_PAGE, page);
+}
+
+static struct phy_driver an8855_driver[] = {
+{
+ PHY_ID_MATCH_EXACT(AN8855_PHY_ID),
+ .name = "Airoha AN8855 internal PHY",
+ /* PHY_GBIT_FEATURES */
+ .flags = PHY_IS_INTERNAL,
+ .probe = an8855_probe,
+ .config_init = an8855_config_init,
+ .soft_reset = genphy_soft_reset,
+ .get_tunable = an8855_get_tunable,
+ .set_tunable = an8855_set_tunable,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = an8855_read_page,
+ .write_page = an8855_write_page,
+}, };
+
+module_phy_driver(an8855_driver);
+
+static struct mdio_device_id __maybe_unused an8855_tbl[] = {
+ { PHY_ID_MATCH_EXACT(AN8855_PHY_ID) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(mdio, an8855_tbl);
+
+MODULE_DESCRIPTION("Airoha AN8855 PHY driver");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_LICENSE("GPL");
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [net-next PATCH v15 11/12] MAINTAINERS: add myself as maintainer for AN8855
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
` (8 preceding siblings ...)
2025-06-26 21:23 ` [net-next PATCH v15 10/12] net: phy: Add Airoha AN8855 Internal Switch Gigabit PHY Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
2025-06-26 21:23 ` [net-next PATCH v15 12/12] net: dsa: tag_mtk: add comments about Airoha usage of this TAG Christian Marangi
[not found] ` <20250626212321.28114-9-ansuelsmth@gmail.com>
11 siblings, 0 replies; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Add myself as maintainer for AN8855 DSA driver and all the related
subdriver (mfd, mdio, phy, nvmem)
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
MAINTAINERS | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index bb9df569a3ff..2d1785478855 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -737,6 +737,25 @@ S: Maintained
F: Documentation/devicetree/bindings/net/airoha,en7581-eth.yaml
F: drivers/net/ethernet/airoha/
+AIROHA AN8855 DSA DRIVER
+M: Christian Marangi <ansuelsmth@gmail.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
+L: netdev@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
+F: Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
+F: Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
+F: Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
+F: Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
+F: drivers/mfd/airoha-an8855.c
+F: drivers/net/dsa/an8855.c
+F: drivers/net/dsa/an8855.h
+F: drivers/net/mdio/mdio-an8855.c
+F: drivers/net/phy/air_an8855.c
+F: drivers/nvmem/an8855-efuse.c
+F: include/linux/dsa/an8855.h
+
AIROHA PCIE PHY DRIVER
M: Lorenzo Bianconi <lorenzo@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [net-next PATCH v15 12/12] net: dsa: tag_mtk: add comments about Airoha usage of this TAG
2025-06-26 21:22 [net-next PATCH v15 00/12] net: dsa: Add Airoha AN8855 support Christian Marangi
` (9 preceding siblings ...)
2025-06-26 21:23 ` [net-next PATCH v15 11/12] MAINTAINERS: add myself as maintainer for AN8855 Christian Marangi
@ 2025-06-26 21:23 ` Christian Marangi
[not found] ` <20250626212321.28114-9-ansuelsmth@gmail.com>
11 siblings, 0 replies; 18+ messages in thread
From: Christian Marangi @ 2025-06-26 21:23 UTC (permalink / raw)
To: Christian Marangi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
Add comments about difference between Airoha AN8855 and Mediatek tag
bitmap.
Airoha AN88555 doesn't support controlling SA learning and Leaky VLAN
from tag. Although these bits are not used (and even not defined for
Leaky VLAN), it's worth to add comments for these difference to prevent
any kind of regression in the future if ever these bits will be used.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
net/dsa/tag_mtk.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index b670e3c53e91..ac3f956abe39 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -18,6 +18,9 @@
#define MTK_HDR_XMIT_TAGGED_TPID_88A8 2
#define MTK_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0)
#define MTK_HDR_XMIT_DP_BIT_MASK GENMASK(5, 0)
+/* AN8855 doesn't support SA_DIS and Leaky VLAN
+ * control in tag as these bits doesn't exist.
+ */
#define MTK_HDR_XMIT_SA_DIS BIT(6)
static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
--
2.48.1
^ permalink raw reply related [flat|nested] 18+ messages in thread[parent not found: <20250626212321.28114-9-ansuelsmth@gmail.com>]
* Re: [net-next PATCH v15 08/12] net: dsa: Add Airoha AN8855 5-Port Gigabit DSA Switch driver
[not found] ` <20250626212321.28114-9-ansuelsmth@gmail.com>
@ 2025-06-28 8:33 ` Thomas Weißschuh
0 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-06-28 8:33 UTC (permalink / raw)
To: Christian Marangi
Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Vladimir Oltean, Srinivas Kandagatla,
Heiner Kallweit, Russell King, Chester A. Unal, Daniel Golle,
DENG Qingfang, Sean Wang, Simon Horman, Matthias Brugger,
AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
netdev, devicetree, linux-kernel
On 2025-06-26 23:23:07+0200, Christian Marangi wrote:
> Add Airoha AN8855 5-Port Gigabit DSA switch. Switch can support
> 10M, 100M, 1Gb, 2.5G and 5G Ethernet Speed but 5G is currently error out
> as it's not currently supported as requires additional configuration for
> the PCS.
>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> ---
> drivers/net/dsa/Kconfig | 9 +
> drivers/net/dsa/Makefile | 1 +
> drivers/net/dsa/an8855.c | 2386 ++++++++++++++++++++++++++++++++++++++
> drivers/net/dsa/an8855.h | 773 ++++++++++++
> 4 files changed, 3169 insertions(+)
> create mode 100644 drivers/net/dsa/an8855.c
> create mode 100644 drivers/net/dsa/an8855.h
<snip>
> +static int an8855_switch_probe(struct platform_device *pdev)
> +{
> + struct an8855_priv *priv;
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + /* Get regmap from MFD */
> + priv->regmap = dev_get_regmap(pdev->dev.parent, NULL);
> + if (!priv->regmap)
> + return -ENOENT;
> +
> + priv->ds = devm_kzalloc(&pdev->dev, sizeof(*priv->ds), GFP_KERNEL);
> + if (!priv->ds)
> + return -ENOMEM;
> +
> + priv->ds->dev = &pdev->dev;
> + priv->ds->num_ports = AN8855_NUM_PORTS;
> + priv->ds->priv = priv;
> + priv->ds->ops = &an8855_switch_ops;
> + devm_mutex_init(&pdev->dev, &priv->reg_mutex);
Check the return value of devm_mutex_init().
This will become a compile error soon.
> + priv->ds->phylink_mac_ops = &an8855_phylink_mac_ops;
> +
> + priv->pcs.ops = &an8855_pcs_ops;
> + priv->pcs.poll = true;
> +
> + dev_set_drvdata(&pdev->dev, priv);
> +
> + return dsa_register_switch(priv->ds);
> +}
<snip>
^ permalink raw reply [flat|nested] 18+ messages in thread