[00/21] net: phy: add X-Powers AC200/AC300 EPHY support

Message ID 20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com (mailing list archive)
Headers
Series net: phy: add X-Powers AC200/AC300 EPHY support |

Message

James Hilliard Aug. 3, 2026, 5:14 a.m. UTC
The Allwinner H616/H618 secondary EMAC is commonly connected to a Fast
Ethernet PHY in an X-Powers AC200 or AC300 companion package.  The two
packages expose the same link PHY ID and largely compatible link-side
registers, but require different control paths before those registers can
be accessed: AC200 is initialized through its I2C MFD, while AC300 uses a
non-PHY Clause 22 control endpoint.

Some H616-family products were shipped with either package under the same
board identity.  For those systems, this series uses a SID NVMEM field to
select the control provider at run time.  With CONFIG_OF_DYNAMIC, the link
PHY enables only the selected fail-needs-probe provider, so an AC300 board
does not probe the unused AC200 I2C controller or claim its pins.  The same
drivers also support fixed descriptions without CONFIG_OF_DYNAMIC: a board
can reference one enabled provider, or enable both candidates when runtime
selection is still required.

The series adds:

  - the H616 EMAC1 binding, stmmac variant and controller node;
  - generic MDIO OF reconfiguration support for PHYs, packages, scanned
    addresses and generic MDIO devices;
  - the AC200 MFD and AC200/AC300 EPHY control providers;
  - the shared AC200/AC300 link-PHY driver, including calibration, power and
    reset sequencing, MDI/MDI-X, statistics, EDPD, PHY-managed EEE, package
    LEDs, interrupts and Wake-on-LAN; and
  - H6 and H616-family device-tree descriptions and arm64 defconfig support.

The AC200 and AC300 control and link paths were exercised on H616-family
hardware during development, including link traffic, address handling,
ethtool EDPD/EEE controls, statistics and LEDs.  The H6 interrupt and
Wake-on-LAN description still needs validation by an H6 hardware user.

This series depends on Richard Genoud's v7 H616 PWM controller series,
which provides the bypass clock used by the companion EPHY:

  https://lore.kernel.org/all/20260703152215.192859-1-richard.genoud@bootlin.com/

The PWM patches are an external prerequisite and are intentionally not
included in this 21-patch series.

Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
James Hilliard (18):
      net: mdio: factor out OF child registration helpers
      net: mdio: make device map changes hotplug-safe
      net: mdio: support dynamic OF device changes
      dt-bindings: net: x-powers: add AC200 EPHY control
      dt-bindings: mfd: x-powers: add AC200
      mfd: add X-Powers AC200 support
      net: phy: add X-Powers AC200 EPHY control driver
      dt-bindings: net: x-powers: add AC300 EPHY control
      net: phy: add X-Powers AC300 EPHY control driver
      dt-bindings: net: x-powers: add AC200/AC300 EPHY
      net: phy: support configuring PHY-autonomous Tx LPI
      net: phylink: allow PHY-autonomous EEE without MAC LPI
      net: phy: add X-Powers AC200/AC300 EPHY driver
      arm64: dts: allwinner: h616: add ACx00 EPHY resources
      arm64: dts: allwinner: orangepi-zero2w: enable Ethernet expansion
      arm64: dts: allwinner: h6: add AC200 EPHY resources
      arm64: dts: allwinner: h6: tanix: enable AC200 EPHY
      arm64: defconfig: enable X-Powers ACx00 Ethernet support

Richard Genoud (3):
      dt-bindings: net: allwinner: add H616 EMAC1
      net: stmmac: sun8i: add support for Allwinner H616 EMAC1
      arm64: dts: allwinner: h616: add EMAC1 controller

 .../devicetree/bindings/mfd/x-powers,ac200.yaml    |  118 ++
 .../bindings/net/allwinner,sun8i-a83t-emac.yaml    |   18 +-
 .../devicetree/bindings/net/snps,dwmac.yaml        |    2 +
 .../bindings/net/x-powers,ac200-ephy-ctl.yaml      |   46 +
 .../bindings/net/x-powers,ac300-ephy-ctl.yaml      |   77 ++
 .../bindings/net/x-powers,acx00-ephy.yaml          |  217 +++
 arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi |   45 +
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi       |   73 +
 .../boot/dts/allwinner/sun50i-h616-acx00-ephy.dtsi |   61 +
 arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi     |   51 +
 .../dts/allwinner/sun50i-h618-orangepi-zero2w.dts  |   13 +
 arch/arm64/configs/defconfig                       |    6 +
 drivers/mfd/Kconfig                                |   13 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/ac200.c                                |  302 ++++
 drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c  |   21 +
 drivers/net/mdio/of_mdio.c                         |  508 ++++++-
 drivers/net/phy/Kconfig                            |   30 +
 drivers/net/phy/Makefile                           |    3 +
 drivers/net/phy/mdio_bus.c                         |   14 +-
 drivers/net/phy/mdio_bus_provider.c                |  140 +-
 drivers/net/phy/mdio_device.c                      |  235 +++-
 drivers/net/phy/phy.c                              |   35 +-
 drivers/net/phy/phy_device.c                       |  127 +-
 drivers/net/phy/phylib-internal.h                  |    4 +-
 drivers/net/phy/phylink.c                          |   35 +-
 drivers/net/phy/xpowers-ac200-ctl.c                |  330 +++++
 drivers/net/phy/xpowers-ac300-ctl.c                |  454 ++++++
 drivers/net/phy/xpowers-acx00.c                    | 1457 ++++++++++++++++++++
 drivers/net/phy/xpowers-acx00.h                    |   27 +
 include/dt-bindings/mfd/x-powers,ac200.h           |   13 +
 include/linux/mdio.h                               |    6 +
 include/linux/phy.h                                |   36 +
 33 files changed, 4384 insertions(+), 134 deletions(-)
---
base-commit: 075b74841bd0065a3bda3440873c747938e69b68
change-id: 20260802-submit-acx00-of-dynamic-v1-94a0dc15f282
prerequisite-message-id: <20260703152215.192859-1-richard.genoud@bootlin.com>
prerequisite-patch-id: 8c447ebd677ea7bf9e63a77d34d8fdaa05eebe7f
prerequisite-patch-id: c7574f9c0e2571ce8c6129ac6db7aa959c986ef3
prerequisite-patch-id: e8b00768102951244927ecf054314f6e02f9ff1b
prerequisite-patch-id: a3e2055ed7f3b5751a3e02d57e674b25ee404ff7

Best regards,
--  
James Hilliard <james.hilliard1@gmail.com>
  

Comments

Andrew Lunn Aug. 3, 2026, 1:01 p.m. UTC | #1
On Sun, Aug 02, 2026 at 11:14:10PM -0600, James Hilliard wrote:
> The Allwinner H616/H618 secondary EMAC is commonly connected to a Fast
> Ethernet PHY in an X-Powers AC200 or AC300 companion package.  The two
> packages expose the same link PHY ID and largely compatible link-side
> registers, but require different control paths before those registers can
> be accessed: AC200 is initialized through its I2C MFD, while AC300 uses a
> non-PHY Clause 22 control endpoint.
> 
> Some H616-family products were shipped with either package under the same
> board identity.  For those systems, this series uses a SID NVMEM field to
> select the control provider at run time.  With CONFIG_OF_DYNAMIC, the link
> PHY enables only the selected fail-needs-probe provider, so an AC300 board
> does not probe the unused AC200 I2C controller or claim its pins.  The same
> drivers also support fixed descriptions without CONFIG_OF_DYNAMIC: a board
> can reference one enabled provider, or enable both candidates when runtime
> selection is still required.
> 
> The series adds:
> 
>   - the H616 EMAC1 binding, stmmac variant and controller node;
>   - generic MDIO OF reconfiguration support for PHYs, packages, scanned
>     addresses and generic MDIO devices;
>   - the AC200 MFD and AC200/AC300 EPHY control providers;
>   - the shared AC200/AC300 link-PHY driver, including calibration, power and
>     reset sequencing, MDI/MDI-X, statistics, EDPD, PHY-managed EEE, package
>     LEDs, interrupts and Wake-on-LAN; and
>   - H6 and H616-family device-tree descriptions and arm64 defconfig support.
> 
> The AC200 and AC300 control and link paths were exercised on H616-family
> hardware during development, including link traffic, address handling,
> ethtool EDPD/EEE controls, statistics and LEDs.  The H6 interrupt and
> Wake-on-LAN description still needs validation by an H6 hardware user.
> 
> This series depends on Richard Genoud's v7 H616 PWM controller series,
> which provides the bypass clock used by the companion EPHY:
> 
>   https://lore.kernel.org/all/20260703152215.192859-1-richard.genoud@bootlin.com/
> 
> The PWM patches are an external prerequisite and are intentionally not
> included in this 21-patch series.

21 patches is on the big side. Now you have shown the big picture, can
you break this up into a couple of series?

    Andrew
  
Andrew Lunn Aug. 3, 2026, 1:14 p.m. UTC | #2
On Sun, Aug 02, 2026 at 11:14:10PM -0600, James Hilliard wrote:
> The Allwinner H616/H618 secondary EMAC is commonly connected to a Fast
> Ethernet PHY in an X-Powers AC200 or AC300 companion package.  The two
> packages expose the same link PHY ID and

I have a couple of terminology questions, one here, anther later

What do you mean by link PHY ID? Especially the link part?

Are you talking about 802.3 Clause 22 registers 2 and 3?

	Andrew
  
Andre Przywara Aug. 3, 2026, 1:26 p.m. UTC | #3
Hi James,

thanks for sending this to the list, but as Andrew already mentioned: 
this is quite a beast, and would need to be broken down.
Jernej and I created some patches just for the AC200 PHY on the H6, 
which Jernej recently revived, and IIUC, wanted to send to the list. 
This would probably be a more workable route: start easy, then add 
support for more SoCs (H616 depends on the WIP PWM driver) and more 
variants (AC300) later.

Which also brings me to some attribution questions: If I understand 
correctly, this has been written mostly by some LLM? I think you would 
need at least to disclose that, if not even add an official tag?
Also I wonder how this relates to the patches floating around for a 
while already: https://github.com/jernejsk/linux-1/commits/ac200-v4. 
This branch is relatively new, but the ac200-v3 branch for instance is 
much older.

On 8/3/26 07:14, James Hilliard wrote:
> The Allwinner H616/H618 secondary EMAC is commonly connected to a Fast
> Ethernet PHY in an X-Powers AC200 or AC300 companion package.  The two
> packages expose the same link PHY ID and largely compatible link-side
> registers, but require different control paths before those registers can
> be accessed: AC200 is initialized through its I2C MFD, while AC300 uses a
> non-PHY Clause 22 control endpoint.
> 
> Some H616-family products were shipped with either package under the same
> board identity.  For those systems, this series uses a SID NVMEM field to
> select the control provider at run time.  With CONFIG_OF_DYNAMIC, the link
> PHY enables only the selected fail-needs-probe provider, so an AC300 board

Just to bring that shallow discussion we had on IRC to the list: I 
wonder if this is the right solution? Alternatively I was wondering if 
just patching the DT in U-Boot would simplify things, and also help 
other DT users like *BSD or U-Boot (proper) itself, to not boil the 
ocean, but just allowing them to follow a standard DT description.

Cheers,
Andre

> does not probe the unused AC200 I2C controller or claim its pins.  The same
> drivers also support fixed descriptions without CONFIG_OF_DYNAMIC: a board
> can reference one enabled provider, or enable both candidates when runtime
> selection is still required.
> 
> The series adds:
> 
>    - the H616 EMAC1 binding, stmmac variant and controller node;
>    - generic MDIO OF reconfiguration support for PHYs, packages, scanned
>      addresses and generic MDIO devices;
>    - the AC200 MFD and AC200/AC300 EPHY control providers;
>    - the shared AC200/AC300 link-PHY driver, including calibration, power and
>      reset sequencing, MDI/MDI-X, statistics, EDPD, PHY-managed EEE, package
>      LEDs, interrupts and Wake-on-LAN; and
>    - H6 and H616-family device-tree descriptions and arm64 defconfig support.
> 
> The AC200 and AC300 control and link paths were exercised on H616-family
> hardware during development, including link traffic, address handling,
> ethtool EDPD/EEE controls, statistics and LEDs.  The H6 interrupt and
> Wake-on-LAN description still needs validation by an H6 hardware user.
> 
> This series depends on Richard Genoud's v7 H616 PWM controller series,
> which provides the bypass clock used by the companion EPHY:
> 
>    https://lore.kernel.org/all/20260703152215.192859-1-richard.genoud@bootlin.com/
> 
> The PWM patches are an external prerequisite and are intentionally not
> included in this 21-patch series.
> 
> Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
> ---
> James Hilliard (18):
>        net: mdio: factor out OF child registration helpers
>        net: mdio: make device map changes hotplug-safe
>        net: mdio: support dynamic OF device changes
>        dt-bindings: net: x-powers: add AC200 EPHY control
>        dt-bindings: mfd: x-powers: add AC200
>        mfd: add X-Powers AC200 support
>        net: phy: add X-Powers AC200 EPHY control driver
>        dt-bindings: net: x-powers: add AC300 EPHY control
>        net: phy: add X-Powers AC300 EPHY control driver
>        dt-bindings: net: x-powers: add AC200/AC300 EPHY
>        net: phy: support configuring PHY-autonomous Tx LPI
>        net: phylink: allow PHY-autonomous EEE without MAC LPI
>        net: phy: add X-Powers AC200/AC300 EPHY driver
>        arm64: dts: allwinner: h616: add ACx00 EPHY resources
>        arm64: dts: allwinner: orangepi-zero2w: enable Ethernet expansion
>        arm64: dts: allwinner: h6: add AC200 EPHY resources
>        arm64: dts: allwinner: h6: tanix: enable AC200 EPHY
>        arm64: defconfig: enable X-Powers ACx00 Ethernet support
> 
> Richard Genoud (3):
>        dt-bindings: net: allwinner: add H616 EMAC1
>        net: stmmac: sun8i: add support for Allwinner H616 EMAC1
>        arm64: dts: allwinner: h616: add EMAC1 controller
> 
>   .../devicetree/bindings/mfd/x-powers,ac200.yaml    |  118 ++
>   .../bindings/net/allwinner,sun8i-a83t-emac.yaml    |   18 +-
>   .../devicetree/bindings/net/snps,dwmac.yaml        |    2 +
>   .../bindings/net/x-powers,ac200-ephy-ctl.yaml      |   46 +
>   .../bindings/net/x-powers,ac300-ephy-ctl.yaml      |   77 ++
>   .../bindings/net/x-powers,acx00-ephy.yaml          |  217 +++
>   arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi |   45 +
>   arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi       |   73 +
>   .../boot/dts/allwinner/sun50i-h616-acx00-ephy.dtsi |   61 +
>   arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi     |   51 +
>   .../dts/allwinner/sun50i-h618-orangepi-zero2w.dts  |   13 +
>   arch/arm64/configs/defconfig                       |    6 +
>   drivers/mfd/Kconfig                                |   13 +
>   drivers/mfd/Makefile                               |    1 +
>   drivers/mfd/ac200.c                                |  302 ++++
>   drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c  |   21 +
>   drivers/net/mdio/of_mdio.c                         |  508 ++++++-
>   drivers/net/phy/Kconfig                            |   30 +
>   drivers/net/phy/Makefile                           |    3 +
>   drivers/net/phy/mdio_bus.c                         |   14 +-
>   drivers/net/phy/mdio_bus_provider.c                |  140 +-
>   drivers/net/phy/mdio_device.c                      |  235 +++-
>   drivers/net/phy/phy.c                              |   35 +-
>   drivers/net/phy/phy_device.c                       |  127 +-
>   drivers/net/phy/phylib-internal.h                  |    4 +-
>   drivers/net/phy/phylink.c                          |   35 +-
>   drivers/net/phy/xpowers-ac200-ctl.c                |  330 +++++
>   drivers/net/phy/xpowers-ac300-ctl.c                |  454 ++++++
>   drivers/net/phy/xpowers-acx00.c                    | 1457 ++++++++++++++++++++
>   drivers/net/phy/xpowers-acx00.h                    |   27 +
>   include/dt-bindings/mfd/x-powers,ac200.h           |   13 +
>   include/linux/mdio.h                               |    6 +
>   include/linux/phy.h                                |   36 +
>   33 files changed, 4384 insertions(+), 134 deletions(-)
> ---
> base-commit: 075b74841bd0065a3bda3440873c747938e69b68
> change-id: 20260802-submit-acx00-of-dynamic-v1-94a0dc15f282
> prerequisite-message-id: <20260703152215.192859-1-richard.genoud@bootlin.com>
> prerequisite-patch-id: 8c447ebd677ea7bf9e63a77d34d8fdaa05eebe7f
> prerequisite-patch-id: c7574f9c0e2571ce8c6129ac6db7aa959c986ef3
> prerequisite-patch-id: e8b00768102951244927ecf054314f6e02f9ff1b
> prerequisite-patch-id: a3e2055ed7f3b5751a3e02d57e674b25ee404ff7
> 
> Best regards,
> --
> James Hilliard <james.hilliard1@gmail.com>
>
  
Andrew Lunn Aug. 3, 2026, 1:30 p.m. UTC | #4
> Just to bring that shallow discussion we had on IRC to the list: I wonder if
> this is the right solution? Alternatively I was wondering if just patching
> the DT in U-Boot would simplify things, and also help other DT users like
> *BSD or U-Boot (proper) itself, to not boil the ocean, but just allowing
> them to follow a standard DT description.

I've not looked into the MDIO bus probing changes in detail yet, but
that was also what i was thinking.

     Andrew
  
Andrew Lunn Aug. 3, 2026, 1:52 p.m. UTC | #5
On Sun, Aug 02, 2026 at 11:14:10PM -0600, James Hilliard wrote:
> The Allwinner H616/H618 secondary EMAC is commonly connected to a Fast
> Ethernet PHY in an X-Powers AC200 or AC300 companion package.

Is there an open data sheet for these devices?

   Andrew
  
Andre Przywara Aug. 3, 2026, 1:54 p.m. UTC | #6
Hi Andrew,

On 8/3/26 15:52, Andrew Lunn wrote:
> On Sun, Aug 02, 2026 at 11:14:10PM -0600, James Hilliard wrote:
>> The Allwinner H616/H618 secondary EMAC is commonly connected to a Fast
>> Ethernet PHY in an X-Powers AC200 or AC300 companion package.
> 
> Is there an open data sheet for these devices?

Find the datasheets at the end of this Wiki page:
https://linux-sunxi.org/AC200

Cheers,
Andre
  
Andrew Lunn Aug. 3, 2026, 1:57 p.m. UTC | #7
On Mon, Aug 03, 2026 at 03:54:26PM +0200, Andre Przywara wrote:
> Hi Andrew,
> 
> On 8/3/26 15:52, Andrew Lunn wrote:
> > On Sun, Aug 02, 2026 at 11:14:10PM -0600, James Hilliard wrote:
> > > The Allwinner H616/H618 secondary EMAC is commonly connected to a Fast
> > > Ethernet PHY in an X-Powers AC200 or AC300 companion package.
> > 
> > Is there an open data sheet for these devices?
> 
> Find the datasheets at the end of this Wiki page:
> https://linux-sunxi.org/AC200

Thanks.

It would be useful to add that to patch 0/X.

   Andrew
  
James Hilliard Aug. 3, 2026, 3:57 p.m. UTC | #8
On Mon, Aug 3, 2026 at 7:26 AM Andre Przywara <andre.przywara@arm.com> wrote:
>
> Hi James,
>
> thanks for sending this to the list, but as Andrew already mentioned:
> this is quite a beast, and would need to be broken down.
> Jernej and I created some patches just for the AC200 PHY on the H6,
> which Jernej recently revived, and IIUC, wanted to send to the list.
> This would probably be a more workable route: start easy, then add
> support for more SoCs (H616 depends on the WIP PWM driver) and more
> variants (AC300) later.

Well, I wanted to validate that the overall driver design is suitable for
the H616 which has to support both PHY variants at runtime effectively
since that is the most complex use case, I also don't have a H6 board
to test with myself at the moment. I think being able to see a more
complete implementation like this is helpful as it can better inform how
we can tie the different control interfaces to the link PHY in a way that
works for the more complex H616 case.

> Which also brings me to some attribution questions: If I understand
> correctly, this has been written mostly by some LLM? I think you would
> need at least to disclose that, if not even add an official tag?

Some patches were, sure, my understanding is that it's not required to
explicitly call that out but I can add more info if that helps, this was
tested/validated using a heavily automated hardware in the loop
testbench setup on an AC200 and AC300 variant H616 board.

> Also I wonder how this relates to the patches floating around for a
> while already: https://github.com/jernejsk/linux-1/commits/ac200-v4.
> This branch is relatively new, but the ac200-v3 branch for instance is
> much older.

Yeah, parts of this are loosely based off of some existing patches that
were floating around like those, although it has diverged quite a bit as
well since this series is designed to handle both phy variants.

I guess I should link to some of the earlier work in the cover letter?

> On 8/3/26 07:14, James Hilliard wrote:
> > The Allwinner H616/H618 secondary EMAC is commonly connected to a Fast
> > Ethernet PHY in an X-Powers AC200 or AC300 companion package.  The two
> > packages expose the same link PHY ID and largely compatible link-side
> > registers, but require different control paths before those registers can
> > be accessed: AC200 is initialized through its I2C MFD, while AC300 uses a
> > non-PHY Clause 22 control endpoint.
> >
> > Some H616-family products were shipped with either package under the same
> > board identity.  For those systems, this series uses a SID NVMEM field to
> > select the control provider at run time.  With CONFIG_OF_DYNAMIC, the link
> > PHY enables only the selected fail-needs-probe provider, so an AC300 board
>
> Just to bring that shallow discussion we had on IRC to the list: I
> wonder if this is the right solution? Alternatively I was wondering if
> just patching the DT in U-Boot would simplify things, and also help
> other DT users like *BSD or U-Boot (proper) itself, to not boil the
> ocean, but just allowing them to follow a standard DT description.

This can be used either way, CONFIG_OF_DYNAMIC isn't a hard
dependency with this design, aside from adding CONFIG_OF_DYNAMIC
support for mdio the dynamic enablement of the correct phy control
drivers is relatively simple with this architecture.
  
Jernej Škrabec Aug. 4, 2026, 5:03 a.m. UTC | #9
Dne ponedeljek, 3. avgust 2026 ob 17:57:15 Srednjeevropski poletni čas je James Hilliard napisal(a):
> On Mon, Aug 3, 2026 at 7:26 AM Andre Przywara <andre.przywara@arm.com> wrote:
> >
> > Hi James,
> >
> > thanks for sending this to the list, but as Andrew already mentioned:
> > this is quite a beast, and would need to be broken down.
> > Jernej and I created some patches just for the AC200 PHY on the H6,
> > which Jernej recently revived, and IIUC, wanted to send to the list.
> > This would probably be a more workable route: start easy, then add
> > support for more SoCs (H616 depends on the WIP PWM driver) and more
> > variants (AC300) later.
> 
> Well, I wanted to validate that the overall driver design is suitable for
> the H616 which has to support both PHY variants at runtime effectively
> since that is the most complex use case, I also don't have a H6 board
> to test with myself at the moment. I think being able to see a more
> complete implementation like this is helpful as it can better inform how
> we can tie the different control interfaces to the link PHY in a way that
> works for the more complex H616 case.

No. AC200 and AC300 are separate chips.

Just making some artificial connection in DT, because H616 wafer is once
copackaged with AC200 die and at other time with AC300 is not correct.
Let just have bootloader properly identify copackaged chip, enable it
and be done with it.

I'm working on proper AC200 series as Andre mentioned. I researched all
functionality because I don't want to miss anything in DT and to have
good arguments why I did thing the way I did. This series doesn't care
of anything else than AC200 EPHY, which isn't correct. Some things are
even not properly modeled and it was already discussed in previous
reviews. For example, MDIO PHY node should reference both, clock and
resets.

I plan to post AC200 patches with at least audio codec included,
alongside EPHY. TVE is also working but it has more open questions, so
it won't be part of next submission.

> 
> > Which also brings me to some attribution questions: If I understand
> > correctly, this has been written mostly by some LLM? I think you would
> > need at least to disclose that, if not even add an official tag?
> 
> Some patches were, sure, my understanding is that it's not required to
> explicitly call that out but I can add more info if that helps, this was
> tested/validated using a heavily automated hardware in the loop
> testbench setup on an AC200 and AC300 variant H616 board.

Yes, you have to reveal AI involvement.

> 
> > Also I wonder how this relates to the patches floating around for a
> > while already: https://github.com/jernejsk/linux-1/commits/ac200-v4.
> > This branch is relatively new, but the ac200-v3 branch for instance is
> > much older.
> 
> Yeah, parts of this are loosely based off of some existing patches that
> were floating around like those, although it has diverged quite a bit as
> well since this series is designed to handle both phy variants.
> 
> I guess I should link to some of the earlier work in the cover letter?

However, what bother me more, is that obviously a lot of AC200 things
were copied (even if only by LLM) from my WIP AC200 branch without any
atribution to either Andre or me.

As Andre mentioned in other response, let do it separately for AC200,
AC300 and detection between them (best in bootloader).

Best regards,
Jernej

> 
> > On 8/3/26 07:14, James Hilliard wrote:
> > > The Allwinner H616/H618 secondary EMAC is commonly connected to a Fast
> > > Ethernet PHY in an X-Powers AC200 or AC300 companion package.  The two
> > > packages expose the same link PHY ID and largely compatible link-side
> > > registers, but require different control paths before those registers can
> > > be accessed: AC200 is initialized through its I2C MFD, while AC300 uses a
> > > non-PHY Clause 22 control endpoint.
> > >
> > > Some H616-family products were shipped with either package under the same
> > > board identity.  For those systems, this series uses a SID NVMEM field to
> > > select the control provider at run time.  With CONFIG_OF_DYNAMIC, the link
> > > PHY enables only the selected fail-needs-probe provider, so an AC300 board
> >
> > Just to bring that shallow discussion we had on IRC to the list: I
> > wonder if this is the right solution? Alternatively I was wondering if
> > just patching the DT in U-Boot would simplify things, and also help
> > other DT users like *BSD or U-Boot (proper) itself, to not boil the
> > ocean, but just allowing them to follow a standard DT description.
> 
> This can be used either way, CONFIG_OF_DYNAMIC isn't a hard
> dependency with this design, aside from adding CONFIG_OF_DYNAMIC
> support for mdio the dynamic enablement of the correct phy control
> drivers is relatively simple with this architecture.
>
  
James Hilliard Aug. 4, 2026, 5:48 a.m. UTC | #10
On Mon, Aug 3, 2026 at 11:03 PM Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
>
> Dne ponedeljek, 3. avgust 2026 ob 17:57:15 Srednjeevropski poletni čas je James Hilliard napisal(a):
> > On Mon, Aug 3, 2026 at 7:26 AM Andre Przywara <andre.przywara@arm.com> wrote:
> > >
> > > Hi James,
> > >
> > > thanks for sending this to the list, but as Andrew already mentioned:
> > > this is quite a beast, and would need to be broken down.
> > > Jernej and I created some patches just for the AC200 PHY on the H6,
> > > which Jernej recently revived, and IIUC, wanted to send to the list.
> > > This would probably be a more workable route: start easy, then add
> > > support for more SoCs (H616 depends on the WIP PWM driver) and more
> > > variants (AC300) later.
> >
> > Well, I wanted to validate that the overall driver design is suitable for
> > the H616 which has to support both PHY variants at runtime effectively
> > since that is the most complex use case, I also don't have a H6 board
> > to test with myself at the moment. I think being able to see a more
> > complete implementation like this is helpful as it can better inform how
> > we can tie the different control interfaces to the link PHY in a way that
> > works for the more complex H616 case.
>
> No. AC200 and AC300 are separate chips.

I agree that AC200 and AC300 are separate chips. That does not imply
that their link-side PHY implementations are different, however.

The AC200 Datasheet V1.1 and AC300 User Manual V1.0 block diagrams show
effectively the same EPHY organization: MII/RMII, auto-negotiation,
Auto-MDIX, 10/100 transmit and receive PCS/PMA blocks, LED and
clock/reset logic, a PLL, and the EPHY analog front end. Both variants
also report PHY ID 0x00441400, and testing shows compatible link-side
paged registers and behavior.

What differs is the surrounding control path. AC200 is configured
through its RSB/TWI-backed MFD registers, while AC300 has a separate
non-PHY MDIO control endpoint. Separate control drivers combined with a
shared link-PHY driver reflect that hardware organization; they do not
model the complete AC200 and AC300 chips as one device.

> Just making some artificial connection in DT, because H616 wafer is once
> copackaged with AC200 die and at other time with AC300 is not correct.
> Let just have bootloader properly identify copackaged chip, enable it
> and be done with it.

I do not think the control-provider reference is artificial. It
describes a real functional dependency: the Clause 22 endpoint cannot
be accessed until the selected package-specific control block has
powered, calibrated and configured it.

I also do not think a bootloader fixup should be the only supported
selection mechanism. Boards using the same compatible have shipped with
either package, and the SID field provides an authoritative package
selector which Linux can read directly. Handling that selector in Linux
avoids making support depend on a particular bootloader implementation.

There is already upstream precedent for unresolved second-source
components in DT. drivers/i2c/i2c-core-of-prober.c handles alternative
components marked "fail-needs-probe" and enables only the populated one.
This case uses a deterministic SID value rather than probing addresses,
but the underlying DT situation is the same.

A bootloader fixup remains compatible with this design. If firmware
enables only the correct provider, the fixed-description path is used
and Linux does not need to change the tree. Runtime selection is used
when firmware leaves the package variant unresolved.

> I'm working on proper AC200 series as Andre mentioned. I researched all
> functionality because I don't want to miss anything in DT and to have
> good arguments why I did thing the way I did. This series doesn't care
> of anything else than AC200 EPHY, which isn't correct. Some things are
> even not properly modeled and it was already discussed in previous
> reviews. For example, MDIO PHY node should reference both, clock and
> resets.

I agree that the AC200 parent binding and MFD core must accommodate its
audio, TV encoder, RTC and EPHY functions.

I do not think every AC200 child driver must be developed or merged
atomically, though. MFD functionality is commonly added incrementally,
provided the parent binding and driver do not prevent the remaining
functions from being added later.

I also do not think clock and reset references alone fully model the
EPHY control dependency. Bringing the link PHY up requires calibration,
input-clock selection, interface configuration, PHY-address programming,
LED pad configuration, and an ordered power, reset and shutdown
sequence. AC300 additionally requires access through a separately
addressed MDIO control endpoint and validation of its package straps.

The common PHY is the authoritative source for the link address,
interface mode and suspend/resume lifecycle. AC200 must program the link
address through its control interface, while AC300 must validate the
relationship between its control and link addresses. Passing that
information from phydev avoids duplicating the PHY node's reg value in
the control node.

Likewise, the next revision removes phy-mode from the control nodes.
The MAC supplies phydev->interface, which the common PHY passes to the
selected control provider.

Individual clock gates and reset signals could still use their standard
frameworks where they behave as independent resources. Those interfaces
do not replace the complete package-control operation, however. Putting
calibration, addressing and I/O configuration into clock or reset
callbacks would give those operations unrelated side effects.

> I plan to post AC200 patches with at least audio codec included,
> alongside EPHY. TVE is also working but it has more open questions, so
> it won't be part of next submission.

I am happy to coordinate the common AC200 core and binding work so that
the two efforts do not conflict and the other AC200 functions remain
properly represented. I do not think the audio and EPHY child drivers
need to be coupled beyond their shared dependency on that parent,
however.

> > > Which also brings me to some attribution questions: If I understand
> > > correctly, this has been written mostly by some LLM? I think you would
> > > need at least to disclose that, if not even add an official tag?
> >
> > Some patches were, sure, my understanding is that it's not required to
> > explicitly call that out but I can add more info if that helps, this was
> > tested/validated using a heavily automated hardware in the loop
> > testbench setup on an AC200 and AC300 variant H616 board.
>
> Yes, you have to reveal AI involvement.

My reading of the policy is that it's recommended but not required.

https://docs.kernel.org/process/coding-assistants.html

>
> >
> > > Also I wonder how this relates to the patches floating around for a
> > > while already: https://github.com/jernejsk/linux-1/commits/ac200-v4.
> > > This branch is relatively new, but the ac200-v3 branch for instance is
> > > much older.
> >
> > Yeah, parts of this are loosely based off of some existing patches that
> > were floating around like those, although it has diverged quite a bit as
> > well since this series is designed to handle both phy variants.
> >
> > I guess I should link to some of the earlier work in the cover letter?
>
> However, what bother me more, is that obviously a lot of AC200 things
> were copied (even if only by LLM) from my WIP AC200 branch without any
> atribution to either Andre or me.

The AC200 code went through substantial refactoring and integration with
the AC300 path, and the provenance of individual parts became mixed in
the process. Could you and Andre clarify which parts should be credited
to each of you, and what form of attribution you would prefer?

> As Andre mentioned in other response, let do it separately for AC200,
> AC300 and detection between them (best in bootloader).

I can reorganize the submission around subsystem and merge
dependencies, but I do not agree that this requires separate link-PHY
implementations or bootloader-only package detection.

The common EPHY code, package-specific control providers, and runtime
provider selection address different parts of one initialization
dependency. Giving the variants separate firmware identities and two
phy_driver structures would only move package selection into firmware;
the two drivers would still need to share nearly all their link-side
implementation to avoid duplicating the same EPHY code.

>
> Best regards,
> Jernej
>
> >
> > > On 8/3/26 07:14, James Hilliard wrote:
> > > > The Allwinner H616/H618 secondary EMAC is commonly connected to a Fast
> > > > Ethernet PHY in an X-Powers AC200 or AC300 companion package.  The two
> > > > packages expose the same link PHY ID and largely compatible link-side
> > > > registers, but require different control paths before those registers can
> > > > be accessed: AC200 is initialized through its I2C MFD, while AC300 uses a
> > > > non-PHY Clause 22 control endpoint.
> > > >
> > > > Some H616-family products were shipped with either package under the same
> > > > board identity.  For those systems, this series uses a SID NVMEM field to
> > > > select the control provider at run time.  With CONFIG_OF_DYNAMIC, the link
> > > > PHY enables only the selected fail-needs-probe provider, so an AC300 board
> > >
> > > Just to bring that shallow discussion we had on IRC to the list: I
> > > wonder if this is the right solution? Alternatively I was wondering if
> > > just patching the DT in U-Boot would simplify things, and also help
> > > other DT users like *BSD or U-Boot (proper) itself, to not boil the
> > > ocean, but just allowing them to follow a standard DT description.
> >
> > This can be used either way, CONFIG_OF_DYNAMIC isn't a hard
> > dependency with this design, aside from adding CONFIG_OF_DYNAMIC
> > support for mdio the dynamic enablement of the correct phy control
> > drivers is relatively simple with this architecture.
> >
>
>
>
>
  
Andrew Lunn Aug. 4, 2026, 5:38 p.m. UTC | #11
> The AC200 Datasheet V1.1 and AC300 User Manual V1.0 block diagrams show
> effectively the same EPHY organization: MII/RMII, auto-negotiation,
> Auto-MDIX, 10/100 transmit and receive PCS/PMA blocks, LED and
> clock/reset logic, a PLL, and the EPHY analog front end. Both variants
> also report PHY ID 0x00441400, and testing shows compatible link-side
> paged registers and behavior.
> 
> What differs is the surrounding control path.

Which is still part of the PHY, needs driver code, and so should be
part of the PHY driver. 

> AC200 is configured
> through its RSB/TWI-backed MFD registers, while AC300 has a separate
> non-PHY MDIO control endpoint.

Which is an implementation detail.

> I do not think the control-provider reference is artificial. It
> describes a real functional dependency: the Clause 22 endpoint cannot
> be accessed until the selected package-specific control block has
> powered, calibrated and configured it.

Nothing too special here. There are PHYs which do this, in the PHY
driver.

> I also do not think a bootloader fixup should be the only supported
> selection mechanism. Boards using the same compatible have shipped with
> either package, and the SID field provides an authoritative package
> selector which Linux can read directly. Handling that selector in Linux
> avoids making support depend on a particular bootloader implementation.

There is a trade off here. If the hardware design is just ugly, badly
thought out, poorly executed, not following the industries norms, we
want to push back on the hardware vendor to make the next version
better. Until that improved version comes out, either the vendor crap
driver should be used, not Mainline, or we try to hide away the issues
in the bootloader. A vendor which actually cares will improve, they
know what Mainline means. And for vendors which don't care, why should
Mainline care, especially if the issues can be pushed to the
bootloader.

We don't want to mess up core Linux code to handle one broken device,
that just makes ongoing Maintenance more expensive for everybody.

> A bootloader fixup remains compatible with this design. If firmware
> enables only the correct provider, the fixed-description path is used
> and Linux does not need to change the tree. Runtime selection is used
> when firmware leaves the package variant unresolved.

So i would not try to fix up the unresolved situation, just do a
dev_error(dev, "Please upgrade your bootloader"); and return -ENODEV.

	Andrew
  
James Hilliard Aug. 4, 2026, 6:18 p.m. UTC | #12
On Tue, Aug 4, 2026 at 11:38 AM Andrew Lunn <andrew@lunn.ch> wrote:
>
> > The AC200 Datasheet V1.1 and AC300 User Manual V1.0 block diagrams show
> > effectively the same EPHY organization: MII/RMII, auto-negotiation,
> > Auto-MDIX, 10/100 transmit and receive PCS/PMA blocks, LED and
> > clock/reset logic, a PLL, and the EPHY analog front end. Both variants
> > also report PHY ID 0x00441400, and testing shows compatible link-side
> > paged registers and behavior.
> >
> > What differs is the surrounding control path.
>
> Which is still part of the PHY, needs driver code, and so should be
> part of the PHY driver.

I agree that the EPHY-specific control registers are functionally part
of the Ethernet function. I do not agree that this implies every device
containing or exposing those registers must be owned by one
struct phy_driver.

There are two orthogonal parts to this design. The control-driver split
models the actual hardware devices and is used by fixed AC200, fixed
AC300 and bootloader-selected systems. CONFIG_OF_DYNAMIC is only one
optional mechanism for resolving which provider exists on a
dual-source system. Removing that mechanism would change variant
selection, not the device boundaries or the justification for sharing
the link-PHY code.

AC200 in particular is not an Ethernet PHY. It is an MFD containing
audio, RTC, TV encoder and Ethernet functions, with a shared parent
regmap, input clock, supplies and interrupt controller. The EPHY
control registers are associated with its Ethernet function, but that
does not make the whole AC200 an MDIO PHY device or make its parent
resources belong to a struct phy_driver.

Mainline MFDs normally keep the shared device and regmap in the MFD
core and bind child drivers to the individual functions. The existing
X-Powers AC100 and AXP20x drivers follow that model. This distinction
also matters once multiple AC200 functions are active: the Ethernet
driver must not assume exclusive ownership of the parent or reset and
disable resources which may be used by the audio, RTC or TV encoder
children.

There are also Ethernet precedents for keeping such controls outside
the link-PHY driver. In
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c, the H3/V3s EPHY
clock, reset, power sequencing, mux selection and MDIO address
programming are handled outside the PHY driver. The link endpoint is
still managed through phylib. The Rockchip stmmac glue similarly
handles integrated EPHY power-up and power-down outside its PHY
driver.

Those examples are not identical to ACx00, but they show that mainline
does not impose a rule that every register affecting a PHY must reside
in its phylib driver. The appropriate boundary depends on how the
devices are addressed and owned.

The MDIO PHY node and the AC200 control child represent devices on
different buses. The phandle between them describes that the MDIO
endpoint depends on the Ethernet function of the AC200 MFD; it does
not claim that the whole AC200 is part of the link PHY.

AC300 has a different topology, but its control interface is likewise
a separately addressed MDIO device. Folding everything into the
link-PHY driver would not eliminate either cross-device dependency. It
would make the driver reach through an MFD parent in one case and
operate a second MDIO device in the other case.

This remains true with CONFIG_OF_DYNAMIC disabled. A fixed AC200
system still consists of an AC200 MFD function and an MDIO PHY, while
a fixed AC300 system still has a control endpoint and link endpoint at
different MDIO addresses. Both then use the same link-side PHY
implementation.

> > AC200 is configured
> > through its RSB/TWI-backed MFD registers, while AC300 has a separate
> > non-PHY MDIO control endpoint.
>
> Which is an implementation detail.

It is an implementation detail of the common power and configuration
operations, but it is not an implementation detail of the Linux device
model. It determines which bus enumerates the device, which driver owns
its registers, how accesses are serialized, and how its resources,
power-management lifetime and removal are handled.

Mainline commonly separates shared functionality from
transport-specific frontends. For example, the AXP20x MFD has common
code with separate I2C and RSB frontends, and the Microchip KSZ switch
drivers share ksz_common.c while retaining separate I2C and SPI
frontends. MDIO mux drivers likewise model access-path control
separately from the PHY devices behind the mux.

The ACx00 provider operations serve the same purpose. They keep the
common link-side PHY behavior independent of whether its prerequisite
control device is an AC200 MFD child or an AC300 MDIO device, without
pretending those devices have the same bus semantics.

These bus, ownership and lifetime differences exist in a completely
static DT. They are not introduced by CONFIG_OF_DYNAMIC or by runtime
node selection.

> > I do not think the control-provider reference is artificial. It
> > describes a real functional dependency: the Clause 22 endpoint cannot
> > be accessed until the selected package-specific control block has
> > powered, calibrated and configured it.
>
> Nothing too special here. There are PHYs which do this, in the PHY
> driver.

The individual reset and calibration operations are not unusual. The
relevant difference is ordering: the real PHY ID cannot be read, and a
normal PHY driver therefore cannot be matched, until another device on
another control bus has completed the sequence.

Mainline already handles some pre-identification prerequisites outside
PHY drivers. Phylib handles generic reset and supply resources before
driver binding, MDIO mux drivers establish access paths, and the sun8i
stmmac driver powers its internal EPHY before MDIO enumeration.

Using a forced compatible can arrange for the link driver to bind
without reading the ID, but it does not make the prerequisite control
device part of the link MDIO device. In particular, AC300 still occupies
a separate MDIO address and should have normal MDIO-device ownership
rather than being accessed behind the MDIO core's back by a driver bound
to another address.

The same cross-device prerequisite exists on fixed AC200 and fixed
AC300 systems with CONFIG_OF_DYNAMIC disabled. Runtime selection only
decides which prerequisite device exists on a dual-source system; it
does not create the dependency or motivate the control-driver split.

> > I also do not think a bootloader fixup should be the only supported
> > selection mechanism. Boards using the same compatible have shipped with
> > either package, and the SID field provides an authoritative package
> > selector which Linux can read directly. Handling that selector in Linux
> > avoids making support depend on a particular bootloader implementation.
>
> There is a trade off here. If the hardware design is just ugly, badly
> thought out, poorly executed, not following the industries norms, we
> want to push back on the hardware vendor to make the next version
> better. Until that improved version comes out, either the vendor crap
> driver should be used, not Mainline, or we try to hide away the issues
> in the bootloader. A vendor which actually cares will improve, they
> know what Mainline means. And for vendors which don't care, why should
> Mainline care, especially if the issues can be pushed to the
> bootloader.

I agree that mainline should not absorb an unbounded vendor workaround.
I do not think this is such a case, however. The package choice and SID
selector are documented hardware configuration, not a heuristic for
guessing around an unknown silicon failure. Supporting second-source
components under one board identity is also not unique to this
hardware.

Mainline's drivers/i2c/i2c-core-of-prober.c exists specifically for
systems such as the Google Hana Chromebooks which were produced with
alternative components. Their candidate nodes are marked
"fail-needs-probe", and Linux determines which component exists and
enables exactly that node so the candidates do not fight over shared
resources.

That helper only covers alternatives on one I2C bus, so it cannot be
used directly for the AC200-I2C versus AC300-MDIO topology. It does,
however, establish that selecting a documented second-source component
in Linux is an accepted model and not inherently bootloader policy.

Whether a future component should be redesigned also does not resolve
how to model already shipped systems. I think the relevant mainline
questions are whether the description matches the hardware, whether
the implementation is bounded and maintainable, and whether it has
real users and testing. Here the selection is deterministic, comes
from an authoritative SID field, and has been tested on both package
variants.

A bootloader fixup can resolve the package variant, but it does not
change the driver architecture. Once the bootloader has enabled the
correct provider, Linux still has an AC200 MFD child or an AC300 MDIO
control device plus the common link PHY. The bootloader chooses which
provider is instantiated; it does not merge that device into the link
PHY.

This is another point which is independent of CONFIG_OF_DYNAMIC. Fixed
descriptions and bootloader-resolved descriptions still use the
control-provider split. Dynamic OF handling only adds Linux-side
selection when firmware leaves both candidates unresolved.

> We don't want to mess up core Linux code to handle one broken device,
> that just makes ongoing Maintenance more expensive for everybody.

I agree that core changes require separate justification. The proposed
MDIO OF reconfiguration support is generic rather than containing
ACx00-specific checks, but it should be reviewed independently on its
own API, concurrency and lifetime merits.

However, rejecting or narrowing the CONFIG_OF_DYNAMIC and MDIO-core
portion would only mean that unresolved dual-source systems require
firmware selection. It would not make a fixed AC200 cease to be an MFD,
make the AC300 control endpoint cease to be a separate MDIO device, or
justify duplicating the common link-PHY implementation.

Fixed AC200 and fixed AC300 descriptions do not require dynamic OF
handling at all. The control-provider model therefore does not impose
this core cost on systems whose package variant is already known.

> > A bootloader fixup remains compatible with this design. If firmware
> > enables only the correct provider, the fixed-description path is used
> > and Linux does not need to change the tree. Runtime selection is used
> > when firmware leaves the package variant unresolved.
>
> So i would not try to fix up the unresolved situation, just do a
> dev_error(dev, "Please upgrade your bootloader"); and return -ENODEV.

I do not think -ENODEV is appropriate when the configuration is not
actually ambiguous. Linux has the authoritative SID selector and all
the resources needed to instantiate the selected provider safely.

A bootloader fixup remains useful and takes precedence naturally: when
firmware has already enabled one provider, Linux follows that fixed
description. Runtime selection only handles the otherwise unresolved
description, just as the mainline I2C component prober handles
unresolved second-source components.

If the SID cell is absent, invalid, or selects a provider not described
by firmware, then failing with an actionable error is appropriate. When
the SID value and both candidate descriptions are valid, requiring a
bootloader upgrade would reject a configuration Linux can identify
without guessing.

This proposed error path concerns only the optional unresolved-selection
case. It is not an argument for folding the AC200 MFD function and AC300
MDIO control endpoint into the common link-PHY driver. With
CONFIG_OF_DYNAMIC disabled, fixed and bootloader-selected systems still
retain exactly the same provider and common-PHY division.