-
Notifications
You must be signed in to change notification settings - Fork 7.7k
drivers: ethernet: xlnx_gem: switch integrated MDIO/PHY support over to Zephyr's framework #87313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
50db3d0
to
cc57b2d
Compare
@ibirnbaum I saw that you added two phy drivers, what is the benefit of them, to the already existing generic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
entry in the migration guide needed
cc57b2d
to
50872bf
Compare
I can add the interrupt support, however, as mentioned in the PR's description, my initial intention was just to carry over what was already working in the driver's local MDIO/PHY code to Zephyr's respective frameworks and then go for extensions afterwards. If combining such a transitional PR with new features isn't an issue for you, I can add the support now. What's your preference? When it comes to having a separate driver aside from the generic one, there is some selfishness involved. The reason is that Weidmüller uses the DP83822 (and its predecessor, the TLK105) in conjunction with several industrial field buses which use Ethernet as physical layer (e.g. EtherCAT, Ethernet/IP, Profinet, Powerlink, Modbus TCP) in the field bus couplers of the u-remote product range. For EtherCAT, ProfiNet and Ethernet/IP, some settings which go beyond the generic register set have to be altered. Depending on which bus is implemented, those settings relate to LED behavior (MLEDCR register), Analog Power Detect Control (APDS/APDC registers), Auto MDIX, Force MDIX, Robust Auto MDIX (PHYCR/CR1 registers) and Fast Link Down (CR3 register). My intention would be to make those settings available to everyone, likely in the form of DT properties. The old PHY code custom to the GEM driver contained some of those (and they'd be carried over for now with the adoption of this PR), but we so far haven't gone public with everything we have nowadays as a) our exact settings probably won't work for someone else, b) we knew that maintaining the custom GEM MDIO/PHY code would likely be a dead end eventually, and c) the varying configurations per firmware build variant are probably better handled via the DT rather than littering the driver code with ifdefs. The assumption is that those options for this PHY might eventually also be useful to someone else. The afforementioned DP83867 GBit PHY requires a separate driver as it has a specific issue revolving around the bootstrap configuration pins. Certain boards exist, amongst them UltraScale boards made by Xilinx themselves (e.g. ZCU102), where the bootstrap configuration sometimes causes the PHY to come up in self-test mode, which has to be handled in software. In Linux, a custom DT property exists for this issue, IIRC named something like "rx-strap-quirk". I'll check in the existing driver if this is already handled properly. Regarding the Marvell Alaska PHYs, I'll check to what extent they're compatible with the generic approach. Configuration of those PHYs comes with some bank switching and frequent resets, and at least the common Digilent-made Zynq-based eval boards I know of couldn't be used for implementing interrupt support as the IRQ line simply isn't wired up on those boards. If the PHY's configuration approach requires the custom driver, somebody else will have to retrofit the interrupt support. EDIT: the DP83867 driver doesn't seem to handle that issue yet, as the related register CFG4 doesn't seem to be referenced anywhere. |
Noted, I'll take care of it |
If you can get both phys working with just the generic phy driver, its preferred to use that now and and the more specific phys in a later PR, when the extra features can be set and used. |
50872bf
to
b944a0f
Compare
/* Device configuration data declaration macro */ | ||
#define ETH_XLNX_GEM_DEV_CONFIG(port) \ | ||
static const struct eth_xlnx_gem_dev_cfg eth_xlnx_gem##port##_dev_cfg = {\ | ||
.mdio_dev = ETH_XLNX_GEM_MDIO_DEV(port),\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mdio_dev can be removed, it is not really needed, also would hinder the use of phys that use i2c or spi.
drivers/ethernet/eth_xlnx_gem.c
Outdated
net_eth_carrier_on(dev_data->iface); | ||
} else { | ||
net_eth_carrier_off(dev_data->iface); | ||
ret = phy_configure_link(dev_conf->phy_dev, speeds); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the phy should have done phy_configure_link()
in it's init already no need to do that again here.
drivers/ethernet/eth_xlnx_gem.c
Outdated
int ret; | ||
|
||
if (dev_conf->phy_dev != NULL && dev_conf->mdio_dev != NULL) { | ||
ret = phy_link_callback_set(dev_conf->phy_dev, eth_xlnx_gem_phy_cb, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
phy_link_callback_set() should be done in the iface init, when dev_data->iface
is no longer NULL
drivers/ethernet/eth_xlnx_gem.c
Outdated
enum phy_link_speed speeds = LINK_HALF_10BASE_T | LINK_FULL_10BASE_T | | ||
LINK_HALF_100BASE_T | LINK_FULL_100BASE_T | | ||
LINK_HALF_1000BASE_T | LINK_FULL_1000BASE_T; | ||
ret = phy_configure_link(dev_conf->phy_dev, speeds); | ||
if (ret) { | ||
LOG_ERR("%s: configure PHY link failed", dev->name); | ||
return ret; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this uses the speeds, that a phy should configure itself with by default, should therefore not be needed
drivers/ethernet/eth_xlnx_gem.c
Outdated
caps |= ETHERNET_LINK_1000BASE_T | | ||
ETHERNET_LINK_100BASE_T | | ||
ETHERNET_LINK_10BASE_T | | ||
ETHERNET_DUPLEX_SET; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ETHERNET_DUPLEX_SET
means you can manually set the duplex via the set_config api function, which this driver does not have. should be removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, removed the flag for now, now that there's a set_config function, I can add manual duplex / link / auto-neg capabilities later on.
drivers/ethernet/eth_xlnx_gem.c
Outdated
|
||
/* Set the initial contents of the current instance's run-time data */ | ||
dev_data->iface = iface; | ||
net_if_set_link_addr(iface, dev_data->mac_addr, 6, NET_LINK_ETHERNET); | ||
ethernet_init(iface); | ||
net_if_carrier_off(iface); | ||
net_eth_carrier_off(iface); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider making the phy-handle
required in the xlnx,gem.yaml
. It seems to be needed to configure the GEM Network Configuration Register and clock speed. also without a phy the carrier would never be set to on.
@@ -29,6 +29,9 @@ if NETWORKING | |||
config NET_L2_ETHERNET | |||
default y | |||
|
|||
config MDIO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add select MDIO if DT_HAS_XLNX_GEM_MDIO_ENABLED
to menuconfig ETH_XLNX_GEM
in drivers/ethernet/Kconfig.xlnx_gem instead. could also be a imply instead of a select
@pdgendt @maass-hamburg |
Remove the legacy MDIO and PHY support for the GEM MAC which dates back to 2021 and doesn't use the MDIO/PHY frameworks provided by Zephyr nowadays, as those didn't exist back then. Signed-off-by: Immo Birnbaum <mail@birnbaum.immo>
Separate the MDIO functionality from the Xilinx GEM MAC driver into a separate driver conforming with the standard MDIO API. Signed-off-by: Immo Birnbaum <mail@birnbaum.immo>
Enable access to the registers used to set a GEM instance's TX clock frequency. Without this memory mapping, the GEM controllers are only usable without PHY management via MDIO with a fixed TX clock frequency set by the FSBL. If MDIO and PHY management are enabled for either GEM on the Zynq, the system will crash with a data abort without this mapping. The ZynqMP is not affected by this issue, as even with the MPU enabled, the relevant SLCR register space is covered by the "peripherals" mapping entry in the ZynqMP's MPU region table. Signed-off-by: Immo Birnbaum <mail@birnbaum.immo>
Remove any properties from the Xilinx GEM DT node specification and the associated header in dt-bindings that relate to the legacy MDIO/PHY support. Signed-off-by: Immo Birnbaum <mail@birnbaum.immo>
Remove all instances of DT properties relating to the legacy MDIO/PHY support. Add the new MDIO nodes for GEM0 and GEM1. Signed-off-by: Immo Birnbaum <mail@birnbaum.immo>
Remove all instances of DT properties relating to the legacy MDIO/PHY support. Add the new MDIO nodes for GEM[0..3]. Signed-off-by: Immo Birnbaum <mail@birnbaum.immo>
Re-based against main due to the introduction of set_config in a separate PR. Some of the comments have been taken care of already, others are still to follow. Checking that the tests still pass after the rebase. Haven't gotten around to testing the DP83822 and the Alaska PHYs with just the generic PHY support, that's still on my list. |
@maass-hamburg Regarding your comments on:
The GEM controller as found in the Xilinx SoCs has some properties / design aspects that differ from other FPGA-less SoCs incorporating the GEM, which is originally a Cadence IP used by Xilinx among others, which I think result in neither of your suggestions being feasible. The big issue is that the assumption 'the respective controller instance is connected to the outside world via a managed PHY, because it's capable of doing so', be it via the controller's own MDIO interface, or, as you mentioned, via I2C/SPI (actually a setup I haven't worked with yet) isn't universally valid in the Xilinx SoCs. It's not uncommon with the Xilinx SoCs to configure one or more GEM(s) to not 'face the outside world' via MIO pins in the form of an RGMII interface with a PHY attached, but 'face inwards' to the FPGA part of the SoC in the form of a GMII interface, which can, for example, be hooked up to an FPGA IP implementing a [n]-Port Ethernet Switch (which in turn can expose its ports either internally or externally, eventually potentially leading to the need for MDIO facilities for a PHY not associated with an Ethernet controller - but that's another issue for some other time). In such a scenario, neither MDIO nor a PHY are involved for the respective controller instance, and its link properties don't ever have to be altered at run-time. Yet, at the same time, one or more other GEM instance(s) (1 in the Zynq, up to 3 in the ZynqMP) could still 'face outwards' with MDIO and PHY enabled. Such system designs would be prevented if a PHY device handle was universally mandatory in conjunction with the GEM controller, therefore, I'd rather not make phy-handle mandatory. Regarding the MDIO device pointer:
Re 1): The Xilinx SoCs have two different types of I/O pins: MIO pins, which are associated with the Processor System - the part of the SoC the GEM controllers reside in - and EMIO pins, which are accessible only from within the FPGA part of the SoC. When a significant number of the Processor System's integrated peripherals are to be connected to the outside world, it's not uncommon, in particular with the smaller chip packages, to not have enough MIO pins available to expose them all directly. In that case, the workaround is to just route their interface signals into the FPGA part of the SoC and just 'hardwire' them to available EMIO pins. When using this workaround for the GEM Ethernet controllers, the media interface automatically changes from RGMII to GMII the moment the respective controller's interface signals are routed into the FPGA part. In order to end up with an RGMII interface via EMIO pins just as you would when using MIO pins, the system design must include the GMII-to-RGMII Converter IP in the FPGA. This converter becomes a separate node on the respective GEM controller's MDIO bus in addition to the external PHY, usually at address 8. At least older versions of this IP consist of just a single register into which the detected link speed has to be written whenever a link speed change is detected by the PHY (more recent versions snoop the MDIO bus for reads of the relevant status registers from the PHY and extract the newly detected link speed automatically). Whenever the GMII-to-RGMII Converter IP is in use, it not only converts interface signals, but also takes the generation of the TX clock away from the controller. Therefore, what it uses the link speed information (either written explicitly or snooped from the MDIO bus) for is to generate a TX clock matching either 10, 100 or 1000 MBps. Which means that, when an older version of this IP core is in use, and I'd like to support that eventually, the driver's eth_xlnx_gem_configure_clocks() function must not calculate matching clock dividers for the master PLL driving the controller, but perform an MDIO write operation to a node that is not the PHY, just passing on the detected link speed for the FPGA-based clock generator to adjust to. In case of newer versions of the converter IP, it wouldn't technically have to do anything, however, as the newer IP versions are backwards compatible, I'd like to keep the implementation identical. Support for the separate MDIO node that is the optional GMII-to-RGMII Converter is my primary motivation for the existence of the MDIO device pointer in the GEM driver's local data. But then, there's also... Re 2): I've occasionally switched over drivers used in conjunction with the MMU-equipped Zynq-7000 to the DEVICE_MMIO API whenever possible in order to eventually get rid of the respective entries in the SoC's static MMU mapping table, which are #ifdef'd depending on the respective devices being enabled in the DT. This is where I'd eventually like to go with the GEM driver as well. However, there's a bit of an issue there: the MDIO interface is a subset of the respective controller's register space. I.e., if the MDIO driver has its own DEVICE_MMIO mapping and the GEM driver has its own DEVICE_MMIO mapping, two MMU entries with different virtual addresses will point to the same physical address that is the respective controller's 4k register space. While this technically works, I'd rather not have that even if the code for the two drivers comes from the same person and mappings based on DEVICE_MMIO entries always happen the same way. This is due to ARM's statement in the ARM Architecture Reference Manual for ARMv7-A:
The ARMv7 MMU code at the time being has no safeguards against what ARM calls 'mismatched memory attributes'. Therefore, my idea regarding automated mapping of the register space just once is:
This admittedly isn't fully tested yet, as this to me is a future feature that's not in the scope of this MDIO-/PHY-related PR. It's a concept that I'd like to try out for the reason mentioned above, but this is secondary to the GMII-to-RGMII Converter support I'm going to need the MDIO device - not the PHY device - for. |
Remove all data/functions/function calls relating to the now removed legacy MDIO/PHY support directly integrated into the GEM device driver. Switch over to using the standard MDIO/PHY interfaces which will now refer to the new separate MDIO driver and the separated PHY drivers. Signed-off-by: Immo Birnbaum <mail@birnbaum.immo>
The legacy MDIO/PHY driver integrated into the Xilinx GEM device driver supported two PHY families: the Marvell Alaska 88E1xxx series PHYs and the TI DP83822 which is a pin- and register compatible drop-in replacement of the TI TLK105, which is therefore also supported by the same driver. These two PHY families are now provided as separate drivers implemented against the standard PHY driver APIs, therefore also enabling their use with MACs other than the GEM. Signed-off-by: Immo Birnbaum <mail@birnbaum.immo>
enable MDIO in the board's Kconfig, specify the Ethernet operational mode for QEMU, add/configure MDIO/PHY nodes in the device tree. Signed-off-by: Immo Birnbaum <mail@birnbaum.immo>
|
if (dev_conf->phy_dev != NULL) { | ||
net_eth_carrier_off(iface); | ||
|
||
ret = phy_link_callback_set(dev_conf->phy_dev, eth_xlnx_gem_phy_cb, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the phy is a fixed link, this function will execute the callback when setting it, so no need for a manual phy_get_link_state
after it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've re-worked things quite a bit once more, including a change of the DT structure (mdio is now a child node of the MAC, which prevents faulty nodelabel-based resolving of the MDIO node if both GEM0 and GEM1 are enabled, GEM1's MDIO is enabled but GEM0's is not, in that case, the one existing node associated with GEM1 will be labeled gem0_mdio). A phy-handle is no longer required, the PHY is now obtained via an array of the MDIO node's child devices. This also lays the groundwork for the afforementioned GMII-to-RGMII converter, which can later be implemented as a PHY device. If there is a converter instance, the MDIO node will have two child devices, if it's just a PHY, it'll be just one.
I've confirmed that the Marvell PHYs which can be found on some Digilent boards work with the generic PHY driver as long as no special features are requested. Therefore, also based on your statement that the DP83822 works with the generic drivers as well, both additional PHY drivers are out for now.
I'm currently working on link configuration via the set_config function, then I'll have a look at how the framework handles fixed links. The big push should be there in a few days.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the phy handle should still be used, as there might be users that have phys that don't connect via mdio.
special phy drivers are only needed, when special configuration is needed or features are used. the generic phy driver only uses the registers specified in the ethernet specification, so therefore should work with all phys that follow that specification.
|
||
#define XLNX_GEM_MDIO_DEV_CONFIG(port) \ | ||
static const struct xlnx_gem_mdio_config xlnx_gem##port##_mdio_cfg = { \ | ||
.gem_base_addr = DT_REG_ADDR_BY_IDX(DT_INST(port, xlnx_gem), 0), \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if it needs the base address of the ethernet mac, it's a better way to have a common parent and the ethernet mac and mdio as a child of it. like here:
https://github.com/zephyrproject-rtos/zephyr/blob/main/dts/bindings/ethernet/st%2Cstm32-ethernet-controller.yaml and
zephyr/dts/arm/st/f7/stm32f765.dtsi
Lines 71 to 94 in 179045e
ethernet@40028000 { | |
reg = <0x40028000 0x8000>; | |
compatible = "st,stm32-ethernet-controller"; | |
clock-names = "stm-eth"; | |
clocks = <&rcc STM32_CLOCK(AHB1, 25)>; | |
mac: ethernet { | |
compatible = "st,stm32-ethernet"; | |
interrupts = <61 0>; | |
clock-names = "mac-clk-tx", "mac-clk-rx", | |
"mac-clk-ptp"; | |
clocks = <&rcc STM32_CLOCK(AHB1, 26)>, | |
<&rcc STM32_CLOCK(AHB1, 27)>, | |
<&rcc STM32_CLOCK(AHB1, 28)>; | |
status = "disabled"; | |
}; | |
mdio: mdio { | |
compatible = "st,stm32-mdio"; | |
#address-cells = <1>; | |
#size-cells = <0>; | |
status = "disabled"; | |
}; | |
}; |
# Copyright (c) 2021, Weidmueller Interface GmbH & Co. KG | ||
# Copyright (c) 2025 Immo Birnbaum | ||
# SPDX-License-Identifier: Apache-2.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
take a look at https://docs.zephyrproject.org/latest/contribute/guidelines.html#copyrights-notices
also the 2021 seems wrong here, as the file is new and it doesn't seems to be copied from another
When the device driver for the GEM Ethernet controller was first implemented, Zephyr's framework for MDIO and PHY devices was still in its very early stages and was too limited for use in conjunction with the GEM MAC. While MDIO-less use cases exist for the GEM (such as connecting it to an Ethernet switch in the FPGA part of the chip), pretty much every Zynq-/ZynqMP-based eval board comes with a PHY, and in order to support more flexible use than just supporting the one default speed setting configured by the FSBL at power-up, including the basic ability to detect link up/down, MDIO and PHY support were integrated directly into the driver. The GEM driver was one of two drivers to do it this way, and this internal implementation outlasted the appearance of generic MDIO and PHY support for quite some time.
Now that the limitations of the early stages of the generic MDIO/PHY support within Zephyr no longer exist, I propose switching the GEM's MDIO and PHY capabilities over to the facilities Zephyr provides nowadays. This to me appears beneficial as the addition of a new supported PHY (such as the TI DP83867 which is common in conjunction with the ZynqMP) is not limited to a single Ethernet MAC and also, it's not an addition to code that will inevitably at some point be a dead end if demands are made for the remaining device drivers bypassing the dedicated frameworks to switch over.
Considering that we're talking about two supported SoCs, one in-tree target board definition with a supported (simulated) PHY, the MDIO driver itself, two supported PHYs and a lot of code that has to be shifted around and broken up into pieces as well as obsolete configuration items from the DT that are removed due to them being replaced with those provided by the MDIO/PHY framework, this PR is a pretty big package. However, it contains everything that is required to just keep running what was already running - the integration into the MDIO shell is one little feature that is added on top.
There's no consideration yet if there's settings that could or should be added to the supported PHYs' DTs (a few PHYs have custom DT items, such as the DP83867's "RX strap quirk" setting), or if any setting that is being applied in the PHY drivers' code should be enabled by default as they are right now (e.g. should 'robust auto MDIX' always be on by default in the TI PHY).
This PR would open up the use of the PHYs so far only supported by the GEM to everyone, allowing anyone who is more familiar with those PHYs and thinks that things should be done differently to make suggestions in that direction.