* [PATCH net-next 0/2] Add DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY driver
@ 2026-07-13 13:12 Artem Shimko
2026-07-13 13:12 ` [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding Artem Shimko
2026-07-13 13:12 ` [PATCH net-next 2/2] net: phy: add DAPU Telecom DAP8210R(I) Gigabit Ethernet PHY driver Artem Shimko
0 siblings, 2 replies; 7+ messages in thread
From: Artem Shimko @ 2026-07-13 13:12 UTC (permalink / raw)
To: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Artem Shimko, linux-kernel, devicetree
Hello,
This series adds support for the DAPU Telecom DAP8211R(I) Gigabit
Ethernet PHY, commonly used in enterprise and industrial networking
applications. The PHY supports 10/100/1000 Mbps operation with RGMII
interface and includes features such as IEEE 802.3az Energy Efficient
Ethernet, IEEE 1588 SyncE, and an internal packet generator for
diagnostics.
The driver implements extended register access via indirect addressing
(registers 0x1E/0x1F) and provides comprehensive device tree support
for RGMII delay configuration. The rx-internal-delay-ps and
tx-internal-delay-ps properties allow precise tuning of clock delays
in 150 ps steps from 0 to 2250 ps, with automatic selection of the
nearest supported value if an exact match is not specified. The
optional tx-inverted-clk flag enables 180-degree TX clock phase shift
for boards where signal integrity or MAC requirements necessitate
clock inversion.
The driver also includes a debugfs interface for diagnostics, exposing
PHY status registers (info) and providing runtime control over the
internal packet generator (pkg_gen), CRC corruption, and loopback
functionality. This interface is particularly useful for development
and field diagnostics without requiring external test equipment.
This PHY is used on the NDA platform with 1G Ethernet tile and has
been tested on that hardware with successful link establishment and
RGMII delay tuning.
Due to the specific PCB layout of the platform and FPGA configuration,
the default RGMII timing configuration was insufficient, causing packet
loss during normal operation. Tuning the TX/RX line delays and enabling
clock inversion restored proper signal timing, resulting in zero packet
loss and stable link performance.
$ make dt_binding_check
SCHEMA Documentation/devicetree/bindings/processed-schema.json
...
DTEX Documentation/devicetree/bindings/net/dapu,dap8211r.example.dts
DTC [C] Documentation/devicetree/bindings/net/dapu,dap8211r.example.dtb
...
grep -i "dap8211r" Documentation/devicetree/bindings/processed-schema.json
chema.json
"http://devicetree.org/schemas/net/dapu,dap8211r.yaml": {
"$filename": ".../devicetree/bindings/net/dapu,dap8211r.yaml",
"$id": "http://devicetree.org/schemas/net/dapu,dap8211r.yaml#",
"title": "DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY",
Working with xgmac.
Board side not pkc_gen mode (normal):
$ arping -I eth0 192.168.5.100
ARPING 192.168.5.1 from 192.168.5.100 eth0
Unicast reply from 192.168.5.1 [board.mac.addr] 8.543ms
Unicast reply from 192.168.5.1 [board.mac.addr] 3.295ms
Unicast reply from 192.168.5.1 [board.mac.addr] 4.301ms
Unicast reply from 192.168.5.1 [board.mac.addr] 4.096ms
Unicast reply from 192.168.5.1 [board.mac.addr] 2.872ms
...
$ Unfortunately, there is a dependence on the axibus speed here
$ iperf3 -c 192.168.5.1
Connecting to host 192.168.5.1, port 5201
[ 5] local 192.168.5.100 port 58936 connected to 192.168.5.1 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 7.88 MBytes 65.8 Mbits/sec 0 150 KBytes
[ 5] 1.00-2.00 sec 8.50 MBytes 71.4 Mbits/sec 0 165 KBytes
[ 5] 2.00-3.00 sec 8.25 MBytes 69.2 Mbits/sec 0 165 KBytes
[ 5] 3.00-4.01 sec 8.50 MBytes 71.1 Mbits/sec 0 165 KBytes
[ 5] 4.01-5.00 sec 8.38 MBytes 70.3 Mbits/sec 0 165 KBytes
[ 5] 5.00-6.00 sec 8.50 MBytes 71.5 Mbits/sec 0 165 KBytes
[ 5] 6.00-7.01 sec 8.62 MBytes 72.0 Mbits/sec 0 174 KBytes
[ 5] 7.01-8.00 sec 8.62 MBytes 72.8 Mbits/sec 0 174 KBytes
[ 5] 8.00-9.00 sec 8.62 MBytes 72.2 Mbits/sec 0 174 KBytes
[ 5] 9.00-10.04 sec 8.62 MBytes 69.9 Mbits/sec 0 174 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.04 sec 84.6 MBytes 70.7 Mbits/sec 0 sender
[ 5] 0.00-10.12 sec 84.8 MBytes 70.3 Mbits/sec receiveriperf Done.
$ ethtool -t eth0
...
The test extra info:
1. MAC Loopback 0
2. MAC Loopback (diff. queues) 0
3. PHY Loopback 0
...
ELP side not pkc_gen mode (normal):
...
17:29:11.974973 ARP, Reply ELP is-at elp.mac.addr(oui Unknown), length 28
17:29:12.975199 ARP, Request who-has ELP (elp.mac.addr(oui Unknown)) tell 192.168.5.100, length 46
17:29:12.975217 ARP, Reply ELP is-at elp.mac.addr(oui Unknown), length 28
17:29:13.975022 ARP, Request who-has ELP (elp.mac.addr(oui Unknown)) tell 192.168.5.100, length 46
17:29:13.975035 ARP, Reply ELP is-at elp.mac.addr(oui Unknown), length 28
17:29:14.974837 ARP, Request who-has ELP (elp.mac.addr(oui Unknown)) tell 192.168.5.100, length 46
17:29:14.974849 ARP, Reply ELP is-at elp.mac.addr(oui Unknown), length 28
17:29:15.975026 ARP, Request who-has ELP (elp.mac.addr(oui Unknown)) tell 192.168.5.100, length 46
...
Accepted connection from 192.168.5.100, port 58932
[ 5] local 192.168.5.1 port 5201 connected to 192.168.5.100 port 58936
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 7.12 MBytes 59.7 Mbits/sec
[ 5] 1.00-2.00 sec 8.50 MBytes 71.3 Mbits/sec
[ 5] 2.00-3.00 sec 8.50 MBytes 71.3 Mbits/sec
[ 5] 3.00-4.00 sec 8.38 MBytes 70.3 Mbits/sec
[ 5] 4.00-5.00 sec 8.50 MBytes 71.3 Mbits/sec
[ 5] 5.00-6.00 sec 8.38 MBytes 70.3 Mbits/sec
[ 5] 6.00-7.00 sec 8.62 MBytes 72.4 Mbits/sec
[ 5] 7.00-8.00 sec 8.62 MBytes 72.3 Mbits/sec
[ 5] 8.00-9.00 sec 8.62 MBytes 72.4 Mbits/sec
[ 5] 9.00-10.00 sec 8.62 MBytes 72.4 Mbits/sec
[ 5] 10.00-10.12 sec 896 KBytes 62.3 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.12 sec 84.8 MBytes 70.3 Mbits/sec receiver
Board side pkc_gen mode:
To send pck_gen patern frame to ELP
$ echo N > pkg_gen_loopback
$ echo 1 > pkg_gen
To send pck_gen patern frame to MAC
$ echo Y > pkg_gen_loopback
$ echo 1 > pkg_gen
ELP side pkc_gen mode:
$ Ther is expected patern
$ tcpdump -i ens16
17:27:18.993518 5a:a5:5a:a5:5a:a5 (oui Unknown) > 5a:a5:5a:a5:5a:a5, ethertype Unknown (0x5aa5), length 60:
0x0000: 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 Z.Z.Z.Z.Z.Z.Z.Z.
0x0010: 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 Z.Z.Z.Z.Z.Z.Z.Z.
0x0020: 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 Z.Z.Z.Z.Z.Z.Z.
17:27:18.995522 5a:a5:5a:a5:5a:a5 (oui Unknown) > 5a:a5:5a:a5:5a:a5, ethertype Unknown (0x5aa5), length 60:
0x0000: 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 Z.Z.Z.Z.Z.Z.Z.Z.
0x0010: 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 Z.Z.Z.Z.Z.Z.Z.Z.
0x0020: 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 5aa5 Z.Z.Z.Z.Z.Z.Z.
...
DTS node example:
ðernet_1g_tile {
...
phy-mode = "rgmii-rxid";
phy-handle = <&phy1>;
...
mdio: mdio {
phy1: ethernet-phy@1 {
...
compatible = "ethernet-phy-ieee802.3-c22";
rx-internal-delay-ps = <1050>;
tx-use-inverted-clk;
...
};
};
};
--
Best regards,
Artem Shimko
Artem Shimko (2):
dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding
net: phy: add DAPU Telecom DAP8210R(I) Gigabit Ethernet PHY driver
.../bindings/net/dapu,dap8211r.yaml | 78 +++
drivers/net/phy/Kconfig | 10 +
drivers/net/phy/Makefile | 1 +
drivers/net/phy/dap8211r.c | 544 ++++++++++++++++++
4 files changed, 633 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/dapu,dap8211r.yaml
create mode 100644 drivers/net/phy/dap8211r.c
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding 2026-07-13 13:12 [PATCH net-next 0/2] Add DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY driver Artem Shimko @ 2026-07-13 13:12 ` Artem Shimko 2026-07-13 15:51 ` Rob Herring (Arm) ` (2 more replies) 2026-07-13 13:12 ` [PATCH net-next 2/2] net: phy: add DAPU Telecom DAP8210R(I) Gigabit Ethernet PHY driver Artem Shimko 1 sibling, 3 replies; 7+ messages in thread From: Artem Shimko @ 2026-07-13 13:12 UTC (permalink / raw) To: netdev, Andrew Lunn, Heiner Kallweit, Russell King, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: Artem Shimko, linux-kernel, devicetree Add device tree binding documentation for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY. The PHY supports TX and RX clock delays in 150 ps steps from 0 to 2250 ps, with a default of 1950 ps if not specified. The tx-inverted-clk flag provides a vendor-specific extension for boards where PCB trace length or MAC requirements necessitate 180-degree clock phase shift. Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com> --- .../bindings/net/dapu,dap8211r.yaml | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/dapu,dap8211r.yaml diff --git a/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml b/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml new file mode 100644 index 000000000000..208a82f779d6 --- /dev/null +++ b/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/dapu,dap8211r.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY + +maintainers: + - Artem Shimko <a.shimko.dev@gmail.com> + +description: | + The DAP8211R(I) is a Gigabit Ethernet PHY with RGMII interface, + supporting IEEE 802.3az Energy Efficient Ethernet, IEEE 1588 SyncE, + and an internal packet generator for diagnostics. + + Specifications: + - 10BASE-Te, 100BASE-TX, 1000BASE-T + - RGMII with configurable TX/RX clock delays (150 ps steps, 0-2250 ps) + - IEEE 802.3az-2010 Energy Efficient Ethernet + - IEEE 1588 SyncE support + - Internal packet generator and checker for link diagnostics + +allOf: + - $ref: ethernet-phy.yaml# + +properties: + compatible: + const: ethernet-phy-id0008.011b + + reg: + maxItems: 1 + + rx-internal-delay-ps: + description: + RGMII RX clock delay in picoseconds. The PHY supports 150 ps steps + from 0 to 2250 ps. If not specified, defaults to 1950 ps. If the + requested value does not exactly match a supported step, the driver + selects the nearest supported value and issues a warning. + enum: [0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500, + 1650, 1800, 1950, 2100, 2250] + default: 1950 + + tx-internal-delay-ps: + description: + RGMII TX clock delay in picoseconds. The PHY supports 150 ps steps + from 0 to 2250 ps. If not specified, defaults to 1950 ps. If the + requested value does not exactly match a supported step, the driver + selects the nearest supported value and issues a warning. + enum: [0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500, + 1650, 1800, 1950, 2100, 2250] + default: 1950 + + tx-inverted-clk: + $ref: /schemas/types.yaml#/definitions/flag + description: + If present, the RGMII TX clock to the MAC is inverted (180 degree + phase shift relative to the data lines). This is a vendor-specific + extension for boards where PCB trace length or MAC requirements + necessitate clock inversion. Only use this property after hardware + signal integrity validation. + +unevaluatedProperties: false + +examples: + - | + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + rx-internal-delay-ps = <1050>; + tx-internal-delay-ps = <1150>; + tx-inverted-clk; + }; + }; \ No newline at end of file -- 2.43.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding 2026-07-13 13:12 ` [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding Artem Shimko @ 2026-07-13 15:51 ` Rob Herring (Arm) 2026-07-13 17:22 ` Rob Herring 2026-07-14 13:17 ` sashiko-bot 2 siblings, 0 replies; 7+ messages in thread From: Rob Herring (Arm) @ 2026-07-13 15:51 UTC (permalink / raw) To: Artem Shimko Cc: Andrew Lunn, Jakub Kicinski, Paolo Abeni, Krzysztof Kozlowski, Eric Dumazet, netdev, devicetree, David S . Miller, Heiner Kallweit, Conor Dooley, linux-kernel, Russell King On Mon, 13 Jul 2026 16:12:22 +0300, Artem Shimko wrote: > Add device tree binding documentation for the DAPU Telecom DAP8211R(I) > Gigabit Ethernet PHY. > > The PHY supports TX and RX clock delays in 150 ps steps from 0 to 2250 ps, > with a default of 1950 ps if not specified. The tx-inverted-clk flag > provides a vendor-specific extension for boards where PCB trace length or > MAC requirements necessitate 180-degree clock phase shift. > > Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com> > --- > .../bindings/net/dapu,dap8211r.yaml | 78 +++++++++++++++++++ > 1 file changed, 78 insertions(+) > create mode 100644 Documentation/devicetree/bindings/net/dapu,dap8211r.yaml > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: ./Documentation/devicetree/bindings/net/dapu,dap8211r.yaml:78:7: [error] no new line character at the end of file (new-line-at-end-of-file) dtschema/dtc warnings/errors: doc reference errors (make refcheckdocs): See https://patchwork.kernel.org/project/devicetree/patch/20260713131223.279555-2-a.shimko.dev@gmail.com The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding 2026-07-13 13:12 ` [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding Artem Shimko 2026-07-13 15:51 ` Rob Herring (Arm) @ 2026-07-13 17:22 ` Rob Herring 2026-07-14 13:17 ` sashiko-bot 2 siblings, 0 replies; 7+ messages in thread From: Rob Herring @ 2026-07-13 17:22 UTC (permalink / raw) To: Artem Shimko Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Krzysztof Kozlowski, Conor Dooley, linux-kernel, devicetree On Mon, Jul 13, 2026 at 04:12:22PM +0300, Artem Shimko wrote: > Add device tree binding documentation for the DAPU Telecom DAP8211R(I) > Gigabit Ethernet PHY. > > The PHY supports TX and RX clock delays in 150 ps steps from 0 to 2250 ps, > with a default of 1950 ps if not specified. The tx-inverted-clk flag > provides a vendor-specific extension for boards where PCB trace length or > MAC requirements necessitate 180-degree clock phase shift. > > Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com> > --- > .../bindings/net/dapu,dap8211r.yaml | 78 +++++++++++++++++++ > 1 file changed, 78 insertions(+) > create mode 100644 Documentation/devicetree/bindings/net/dapu,dap8211r.yaml > > diff --git a/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml b/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml > new file mode 100644 > index 000000000000..208a82f779d6 > --- /dev/null > +++ b/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml > @@ -0,0 +1,78 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/net/dapu,dap8211r.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY > + > +maintainers: > + - Artem Shimko <a.shimko.dev@gmail.com> > + > +description: | > + The DAP8211R(I) is a Gigabit Ethernet PHY with RGMII interface, > + supporting IEEE 802.3az Energy Efficient Ethernet, IEEE 1588 SyncE, > + and an internal packet generator for diagnostics. > + > + Specifications: > + - 10BASE-Te, 100BASE-TX, 1000BASE-T > + - RGMII with configurable TX/RX clock delays (150 ps steps, 0-2250 ps) > + - IEEE 802.3az-2010 Energy Efficient Ethernet > + - IEEE 1588 SyncE support > + - Internal packet generator and checker for link diagnostics > + > +allOf: > + - $ref: ethernet-phy.yaml# > + > +properties: > + compatible: > + const: ethernet-phy-id0008.011b > + > + reg: > + maxItems: 1 > + > + rx-internal-delay-ps: > + description: > + RGMII RX clock delay in picoseconds. The PHY supports 150 ps steps > + from 0 to 2250 ps. If not specified, defaults to 1950 ps. If the > + requested value does not exactly match a supported step, the driver > + selects the nearest supported value and issues a warning. > + enum: [0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500, > + 1650, 1800, 1950, 2100, 2250] > + default: 1950 > + > + tx-internal-delay-ps: > + description: > + RGMII TX clock delay in picoseconds. The PHY supports 150 ps steps > + from 0 to 2250 ps. If not specified, defaults to 1950 ps. If the > + requested value does not exactly match a supported step, the driver > + selects the nearest supported value and issues a warning. > + enum: [0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500, > + 1650, 1800, 1950, 2100, 2250] This would also work: multipleOf: 150 maximum: 2250 > + default: 1950 > + > + tx-inverted-clk: > + $ref: /schemas/types.yaml#/definitions/flag > + description: > + If present, the RGMII TX clock to the MAC is inverted (180 degree > + phase shift relative to the data lines). This is a vendor-specific > + extension for boards where PCB trace length or MAC requirements > + necessitate clock inversion. Only use this property after hardware > + signal integrity validation. > + > +unevaluatedProperties: false > + > +examples: > + - | > + mdio { > + #address-cells = <1>; > + #size-cells = <0>; > + > + ethernet-phy@1 { > + compatible = "ethernet-phy-ieee802.3-c22"; > + reg = <1>; > + rx-internal-delay-ps = <1050>; > + tx-internal-delay-ps = <1150>; > + tx-inverted-clk; > + }; > + }; > \ No newline at end of file With this fixed, Reviewed-by: Rob Herring (Arm) <robh@kernel.org> ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding 2026-07-13 13:12 ` [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding Artem Shimko 2026-07-13 15:51 ` Rob Herring (Arm) 2026-07-13 17:22 ` Rob Herring @ 2026-07-14 13:17 ` sashiko-bot 2 siblings, 0 replies; 7+ messages in thread From: sashiko-bot @ 2026-07-14 13:17 UTC (permalink / raw) To: Artem Shimko; +Cc: conor+dt, devicetree, robh Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [Medium] The example's `compatible` string does not match the schema's required `compatible` string, causing the example to silently bypass this schema's validation. - [Medium] The example uses an invalid value for `tx-internal-delay-ps` that violates the strict enum constraints. - [Medium] The vendor-specific property `tx-inverted-clk` lacks the required vendor prefix. -- --- Patch [1]: [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding --- commit acf143bd06413ea91d469e7f087d2e96207a1bec Author: Artem Shimko <a.shimko.dev@gmail.com> dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding Add device tree binding documentation for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY. > diff --git a/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml b/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml > new file mode 100644 > index 0000000000000..208a82f779d61 > --- /dev/null > +++ b/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml [ ... ] > + tx-internal-delay-ps: > + description: > + RGMII TX clock delay in picoseconds. The PHY supports 150 ps steps > + from 0 to 2250 ps. If not specified, defaults to 1950 ps. If the > + requested value does not exactly match a supported step, the driver > + selects the nearest supported value and issues a warning. > + enum: [0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500, > + 1650, 1800, 1950, 2100, 2250] > + default: 1950 > + > + tx-inverted-clk: [Severity: Medium] Since this property is a vendor-specific extension, should it include a vendor prefix like dapu,tx-inverted-clk? Introducing custom properties without a prefix risks colliding with future standard properties. > + $ref: /schemas/types.yaml#/definitions/flag > + description: > + If present, the RGMII TX clock to the MAC is inverted (180 degree > + phase shift relative to the data lines). This is a vendor-specific [ ... ] > +examples: > + - | > + mdio { > + #address-cells = <1>; > + #size-cells = <0>; > + > + ethernet-phy@1 { > + compatible = "ethernet-phy-ieee802.3-c22"; [Severity: Medium] Will this compatible string cause the example to bypass validation for this schema? The schema requires the compatible string to be exactly "ethernet-phy-id0008.011b". If the example is not evaluated against this file's schema, it can hide other validation failures. > + reg = <1>; > + rx-internal-delay-ps = <1050>; > + tx-internal-delay-ps = <1150>; [Severity: Medium] Will this value trigger a validation error when the compatible string mismatch is fixed? The tx-internal-delay-ps property enforces an enum with strict 150 ps steps, and 1150 is not in the list of allowed values. > + tx-inverted-clk; > + }; > + }; -- Sashiko AI review · https://sashiko.dev/#/patchset/20260713131223.279555-1-a.shimko.dev@gmail.com?part=1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next 2/2] net: phy: add DAPU Telecom DAP8210R(I) Gigabit Ethernet PHY driver 2026-07-13 13:12 [PATCH net-next 0/2] Add DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY driver Artem Shimko 2026-07-13 13:12 ` [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding Artem Shimko @ 2026-07-13 13:12 ` Artem Shimko 2026-07-14 13:17 ` sashiko-bot 1 sibling, 1 reply; 7+ messages in thread From: Artem Shimko @ 2026-07-13 13:12 UTC (permalink / raw) To: netdev, Andrew Lunn, Heiner Kallweit, Russell King, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: Artem Shimko, linux-kernel, devicetree Add a new PHY driver for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY, which is commonly used in enterprise and industrial networking applications. The driver implements extended register access via indirect addressing through corresponding registers, and provides comprehensive device tree support for RGMII delay configuration. The rx-internal-delay-ps and tx-internal-delay-ps properties allow precise tuning of clock delays in 150 ps steps from 0 to 2250 ps, with automatic selection of the nearest supported value if an exact match is not specified. Additionally, the optional tx-inverted-clk flag enables 180-degree TX clock phase shift for boards where signal integrity or MAC requirements necessitate clock inversion. The driver also exports a debugfs interface for diagnostics, exposing PHY status registers and providing runtime control over the internal packet generator, CRC corruption, and loopback functionality. Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com> --- drivers/net/phy/Kconfig | 10 + drivers/net/phy/Makefile | 1 + drivers/net/phy/dap8211r.c | 544 +++++++++++++++++++++++++++++++++++++ 3 files changed, 555 insertions(+) create mode 100644 drivers/net/phy/dap8211r.c diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 099f25dceabb..4576f707ac94 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -237,6 +237,16 @@ config DAVICOM_PHY help Currently supports dm9161e and dm9131 +config DAP8211R_PHY + tristate "DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY" + depends on OF + help + Support for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY. + This PHY is designed for enterprise and industrial networking + applications, supporting 10/100/1000 Mbps operation. + RGMII with: configurable TX/RX clock delays, optional flag to enable + 180-degree TX clock phase shift and internal packet generator. + config ICPLUS_PHY tristate "ICPlus PHYs" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index de660ae94945..ad35733eb4bb 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_BROADCOM_PHY) += broadcom.o obj-$(CONFIG_CICADA_PHY) += cicada.o obj-$(CONFIG_CORTINA_PHY) += cortina.o obj-$(CONFIG_DAVICOM_PHY) += davicom.o +obj-$(CONFIG_DAP8211R_PHY) += dap8211r.o obj-$(CONFIG_DP83640_PHY) += dp83640.o obj-$(CONFIG_DP83822_PHY) += dp83822.o obj-$(CONFIG_DP83848_PHY) += dp83848.o diff --git a/drivers/net/phy/dap8211r.c b/drivers/net/phy/dap8211r.c new file mode 100644 index 000000000000..bd695bc4953a --- /dev/null +++ b/drivers/net/phy/dap8211r.c @@ -0,0 +1,544 @@ +// SPDX-License-Identifier: GPL +/* + * Driver for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY. + * + * Specifications: + * - IEEE 802.3 10BASE-Te, 100BASE-TX, 1000BASE-T + * - IEEE 802.3az-2010 Energy Efficient Ethernet + * - IEEE 1588 SyncE support + * - RGMII + * - Package Generator for diagnostics + * + * Author: Artem Shimko <a.shimko.dev@gmail.com> + */ + +#include <linux/bitfield.h> +#include <linux/debugfs.h> +#include <linux/ethtool.h> +#include <linux/kernel.h> +#include <linux/mii.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/of.h> +#include <linux/phy.h> + +#define DAP8211R_PHY_ID 0x0008011B +#define DAP8211R_PHY_ID_MASK 0xFFFFFFFF + +#define DAP8211R_EXT_ADD 0x1E +#define DAP8211R_EXT_DATA 0x1F + +#define DAP8211R_PKGC5 0xA0 +#define DAP8211R_PKG_PL_MASK GENMASK(1, 0) +#define DAP8211R_PKG_PL_5AA5 BIT(1) +#define DAP8211R_PKG_COR_CRC BIT(2) +#define DAP8211R_PKG_GEN_EN BIT(12) +#define DAP8211R_PKG_GEN_MODE BIT(13) +#define DAP8211R_PKG_GATE_EN BIT(14) +#define DAP8211R_PKG_CHK_EN BIT(15) +#define DAP8211R_PKG_GEN_MASK GENMASK(15, 12) + +#define DAP8211R_PHY_CON 0xA001 +#define DAP8211R_PHY_LDO_EN BIT(6) +#define DAP8211R_PHY_RX_DLY BIT(8) +#define DAP8211R_PHY_GATE_RX_CLK BIT(9) +#define DAP8211R_PHY_SW_RST BIT(15) + +#define DAP8211R_RGMII_CON 0xA003 +#define DAP8211R_RGMII_TX_DEL_MASK GENMASK(3, 0) +#define DAP8211R_RGMII_RX_DEL_MASK GENMASK(13, 10) +#define DAP8211R_RGMII_CLK_INVERT BIT(14) + +/* Default RGMII delay (1.95ns == 13 * 150)ps) */ +#define DAP8211R_DEFAULT_DELAY_PS 1950 + +struct dap8211r_delay_config { + u32 ps; + u8 sel; +}; + +static const struct dap8211r_delay_config delay_config[] = { + { 0, 0}, + { 150, 1}, + { 300, 2}, + { 450, 3}, + { 600, 4}, + { 750, 5}, + { 900, 6}, + {1050, 7}, + {1200, 8}, + {1350, 9}, + {1500, 10}, + {1650, 11}, + {1800, 12}, + {1950, 13}, + {2100, 14}, + {2250, 15}, +}; + +#define DAP8211R_DELAY_COUNT ARRAY_SIZE(delay_config) + +struct dap8211r_priv { + struct device *dev; +#if IS_ENABLED(CONFIG_DEBUG_FS) + struct dentry *root_dir; + bool crc_cor; + bool loopback; +#endif +}; + +/** + * dap8211r_delay_ps_to_sel() - Convert picoseconds to register value + * @ps: Delay in picoseconds (0-2250) + * + * Converts a delay value in picoseconds to the corresponding register value + * for RGMII delay configuration. The PHY supports 150ps steps from 0 to 2250ps. + * + * Return: Register value (0-15) + */ +static u16 dap8211r_delay_ps_to_sel(struct phy_device *phydev, u32 ps) +{ + int i, best_idx = 0; + u32 best_diff = UINT_MAX, diff = 0; + + if (!ps) + return 0; + + for (i = 0; i < DAP8211R_DELAY_COUNT; i++) { + diff = abs(ps - delay_config[i].ps); + + if (diff < best_diff) { + best_diff = diff; + best_idx = i; + } + + if (!diff) + break; + } + + if (best_diff) + phydev_warn(phydev, "Delay %u ps not found, using closest %u ps\n", ps, + delay_config[best_idx].ps); + + phydev_dbg(phydev, "Delay ps idx: %u\n", delay_config[best_idx].sel); + + return delay_config[best_idx].sel; +} + +/** + * dap8211r_read_ext() - Read extended register + * @phydev: PHY device structure + * @reg: Extended register address + * + * Reads a PHY extended register using the indirect access method. + * The caller must hold the MDIO bus lock. + * + * Return: Register value on success, or negative error code + */ +static int dap8211r_read_ext(struct phy_device *phydev, u16 reg) +{ + int ret; + + phy_lock_mdio_bus(phydev); + ret = __phy_write(phydev, DAP8211R_EXT_ADD, reg); + if (ret < 0) + goto out; + + ret = __phy_read(phydev, DAP8211R_EXT_DATA); +out: + phy_unlock_mdio_bus(phydev); + return ret; +} + +/** + * dap8211r_modify_ext() - Modify extended register bits + * @phydev: PHY device structure + * @reg: Extended register address + * @mask: Bit mask of bits to clear + * @set: Bit mask of bits to set + * + * Modifies a PHY extended register using the indirect access method. + * New value = (old value & ~mask) | set. + * The caller must hold the MDIO bus lock. + * + * Return: 0 on success, or negative error code + */ +static int dap8211r_modify_ext(struct phy_device *phydev, u16 reg, u16 mask, u16 set) +{ + int ret; + + phy_lock_mdio_bus(phydev); + ret = __phy_write(phydev, DAP8211R_EXT_ADD, reg); + if (ret < 0) + goto out; + + ret = __phy_modify(phydev, DAP8211R_EXT_DATA, mask, set); +out: + phy_unlock_mdio_bus(phydev); + return ret; +} + +/** + * dap8211r_get_rgmii_delay() - Get RGMII delay from device tree + * @phydev: PHY device structure + * @prop_name: Device tree property name + * + * Reads the RGMII delay from the device tree. If the property is not + * specified, the default delay (1950ps) is used. + * + * Return: Register value (0-15) or default if property not found + */ +static u32 dap8211r_get_rgmii_delay(struct phy_device *phydev, const char *prop_name) +{ + struct device_node *np = phydev->mdio.dev.of_node; + int ret; + u32 ps = 0; + + ret = of_property_read_u32(np, prop_name, &ps); + if (ret) { + phydev_dbg(phydev, "Using default delay (%ups)\n", DAP8211R_DEFAULT_DELAY_PS); + ps = DAP8211R_DEFAULT_DELAY_PS; + } + + return dap8211r_delay_ps_to_sel(phydev, ps); +} + +/** + * dap8211r_config_init() - Initialize PHY + * @phydev: PHY device structure + * + * Configures the PHY during initialization: + * - RGMII delays based on interface mode + * - TX clock invertion + * - Software reset to apply settings + * + * Return: 0 on success, or negative error code + */ +static int dap8211r_config_init(struct phy_device *phydev) +{ + struct device_node *phydev_node = phydev->mdio.dev.of_node; + u16 mask = 0, set = 0; + int ret; + + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII: + break; + case PHY_INTERFACE_MODE_RGMII_RXID: + set = FIELD_PREP(DAP8211R_RGMII_RX_DEL_MASK, + dap8211r_get_rgmii_delay(phydev, "rx-internal-delay-ps")); + mask = DAP8211R_RGMII_RX_DEL_MASK; + break; + case PHY_INTERFACE_MODE_RGMII_ID: + set = FIELD_PREP(DAP8211R_RGMII_RX_DEL_MASK, + dap8211r_get_rgmii_delay(phydev, "rx-internal-delay-ps")); + mask = DAP8211R_RGMII_RX_DEL_MASK; + fallthrough; + case PHY_INTERFACE_MODE_RGMII_TXID: + set |= FIELD_PREP(DAP8211R_RGMII_TX_DEL_MASK, + dap8211r_get_rgmii_delay(phydev, "tx-internal-delay-ps")); + mask |= DAP8211R_RGMII_TX_DEL_MASK; + break; + default: + phydev_err(phydev, "Unsupported interface: %d\n", + phydev->interface); + return -EINVAL; + } + + if (of_property_read_bool(phydev_node, "tx-use-inverted-clk")) + set |= DAP8211R_RGMII_CLK_INVERT; + + mask |= DAP8211R_RGMII_CLK_INVERT; + + ret = dap8211r_modify_ext(phydev, DAP8211R_PHY_CON, DAP8211R_PHY_SW_RST, 0); + if (ret) + return ret; + + /* Wait for reset self-clear */ + fsleep(200); + + ret = dap8211r_modify_ext(phydev, DAP8211R_RGMII_CON, mask, set); + if (ret) + return ret; + + phydev_dbg(phydev, "RGMII configured: interface=%d, mask=0x%04x, set=0x%04x\n", + phydev->interface, mask, set); + + return 0; +} + +#if IS_ENABLED(CONFIG_DEBUG_FS) + +/** + * info_show() - Show PHY status information + * @sf: Sequence file structure + * @data: Private data (struct dap8211r_priv *) + * + * Displays PHY configuration and status registers for debugging. + * + * Return: 0 on success, or negative error code + */ +static int info_show(struct seq_file *sf, void *data) +{ + struct dap8211r_priv *priv = sf->private; + struct phy_device *phydev = to_phy_device(priv->dev); + int val; + + val = dap8211r_read_ext(phydev, DAP8211R_PHY_CON); + if (val < 0) + return val; + + seq_printf(sf, "PHY_CON: 0x%04x\n", val); + seq_printf(sf, " LDO enabled: %s\n", FIELD_GET(DAP8211R_PHY_LDO_EN, val) ? + "yes" : "no"); + seq_printf(sf, " RX dly en: %s\n", FIELD_GET(DAP8211R_PHY_RX_DLY, val) ? + "yes" : "no"); + seq_printf(sf, " RX ckl gating: %s\n", FIELD_GET(DAP8211R_PHY_GATE_RX_CLK, val) ? + "yes" : "no"); + + val = dap8211r_read_ext(phydev, DAP8211R_RGMII_CON); + if (val < 0) + return val; + + seq_printf(sf, "RGMII_CON: 0x%04x\n", val); + seq_printf(sf, " TX delay idx: %lx\n", FIELD_GET(DAP8211R_RGMII_TX_DEL_MASK, val)); + seq_printf(sf, " RX delay idx: %lx\n", FIELD_GET(DAP8211R_RGMII_RX_DEL_MASK, val)); + seq_printf(sf, " CLK invert: %s\n", FIELD_GET(DAP8211R_RGMII_CLK_INVERT, val) ? + "yes" : "no"); + + val = phy_read(phydev, MII_BMSR); + if (val < 0) + return val; + + seq_printf(sf, "BMSR: 0x%04x\n", val); + seq_printf(sf, " Link: %s\n", FIELD_GET(BMSR_LSTATUS, val) ? + "up" : "down"); + seq_printf(sf, " AN complete: %s\n", FIELD_GET(BMSR_ANEGCOMPLETE, val) ? + "yes" : "no"); + + val = dap8211r_read_ext(phydev, DAP8211R_PKGC5); + if (val < 0) + return val; + + if (FIELD_GET(DAP8211R_PKG_GEN_EN, val) && + FIELD_GET(DAP8211R_PKG_CHK_EN, val)) + seq_puts(sf, "WARNING: Package Generating enabled\n"); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(info); + +/** + * pkg_gen_show() - Show packet generator status + * @sf: Sequence file structure + * @data: Private data (struct dap8211r_priv *) + * + * Displays the current status of the internal packet generator, + * including CRC corruption and loopback settings. + * + * Return: 0 on success, or negative error code + */ +static int pkg_gen_show(struct seq_file *sf, void *data) +{ + struct dap8211r_priv *priv = sf->private; + struct phy_device *phydev = to_phy_device(priv->dev); + int val; + + val = dap8211r_read_ext(phydev, DAP8211R_PKGC5); + if (val < 0) + return val; + + seq_puts(sf, "Package Generating: "); + if (FIELD_GET(DAP8211R_PKG_GEN_EN, val) && + FIELD_GET(DAP8211R_PKG_CHK_EN, val)) + seq_puts(sf, "enabled\n"); + else + seq_puts(sf, "disabled\n"); + + seq_printf(sf, "CRC corruption en: %s\n", FIELD_GET(DAP8211R_PKG_COR_CRC, val) ? + "enabled" : "disabled"); + + val = phy_read(phydev, MII_BMCR); + if (val < 0) + return val; + + seq_printf(sf, "Loopback en: %s\n", FIELD_GET(BMCR_LOOPBACK, val) ? + "enabled" : "disabled"); + return 0; +} + +/** + * pkg_gen_write() - Enable/disable packet generator + * @file: File structure + * @user_buf: User space buffer + * @count: Buffer size + * @ppos: File position + * + * Enables or disables the internal packet generator. + * Also controls loopback and CRC corruption via debugfs flags. + * + * NOTE: We intentionally do not use genphy_loopback() here. + * genphy_loopback() does a full BMCR overwrite (mask = ~0) and + * waits up to 500 ms for link in loopback mode. This is too + * heavy for a diagnostic packet generator: + * + * - It destroys all other BMCR state (speed, duplex, AN config). + * - The 500 ms link poll is unnecessary: we already have a link + * or are deliberately setting up a test condition. + * - We want to minimize changes to BMCR during debugging. + * + * Return: Number of bytes written on success, or negative error code + */ +static ssize_t pkg_gen_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct seq_file *sf = file->private_data; + struct dap8211r_priv *priv = sf->private; + struct phy_device *phydev = to_phy_device(priv->dev); + bool en; + u16 mask, set, set_bmcr; + int ret; + + ret = kstrtobool_from_user(user_buf, count, &en); + if (ret) + return ret; + + if (en) { + set = DAP8211R_PKG_GEN_EN | DAP8211R_PKG_CHK_EN | DAP8211R_PKG_PL_5AA5; + + if (priv->crc_cor) + set |= DAP8211R_PKG_COR_CRC; + + if (priv->loopback) + set_bmcr = BMCR_LOOPBACK; + else + set_bmcr = BMCR_ANENABLE; + } else { + set = DAP8211R_PKG_GEN_MODE | DAP8211R_PKG_GATE_EN; + set_bmcr = BMCR_ANENABLE; + } + + ret = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK | BMCR_ANENABLE, set_bmcr); + if (ret < 0) + return ret; + + mask = DAP8211R_PKG_GEN_MASK | DAP8211R_PKG_PL_MASK | DAP8211R_PKG_COR_CRC; + ret = dap8211r_modify_ext(phydev, DAP8211R_PKGC5, mask, set); + if (ret < 0) { + phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0); + return ret; + } + + return count; +} +DEFINE_SHOW_STORE_ATTRIBUTE(pkg_gen); + +/** + * dap8211r_debug_init() - Initialize debugfs entries + * @priv: Private driver data + * + * Creates debugfs directory and files for PHY debugging. + * - info: PHY status information + * - pkg_gen: Enable/disable generator (1/0) + * - pkg_gen_crc_cor: Enable CRC corruption (Y/N) + * - pkg_gen_loopback: Enable loopback (Y/N) + * + * Debugfs is only available when CONFIG_DEBUG_FS is enabled. + */ +static void dap8211r_debug_init(struct dap8211r_priv *priv) +{ + priv->root_dir = debugfs_create_dir(dev_name(priv->dev), NULL); + if (IS_ERR(priv->root_dir)) + return; + + debugfs_create_file("info", 0444, priv->root_dir, priv, + &info_fops); + debugfs_create_file("pkg_gen", 0644, priv->root_dir, priv, + &pkg_gen_fops); + debugfs_create_bool("pkg_gen_crc_cor", 0644, priv->root_dir, + &priv->crc_cor); + debugfs_create_bool("pkg_gen_loopback", 0644, priv->root_dir, + &priv->loopback); +} + +/** + * dap8211r_debug_remove() - Remove debugfs entries + * @priv: Private driver data + * + * Recursively removes all debugfs files and directories created + * by dap8211r_debug_init(). + */ +static void dap8211r_debug_remove(struct dap8211r_priv *priv) +{ + debugfs_remove_recursive(priv->root_dir); +} + +#else /* !CONFIG_DEBUG_FS */ +static void dap8211r_debug_init(struct dap8211r_priv *priv) {} +static void dap8211r_debug_remove(struct dap8211r_priv *priv) {} +#endif /* CONFIG_DEBUG_FS */ + +/** + * dap8211r_probe() - PHY probe callback + * @phydev: PHY device structure + * + * Called when the PHY is discovered. Allocates and initializes + * private driver data and debugfs entries. + * + * Return: 0 on success, or negative error code + */ +static int dap8211r_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct dap8211r_priv *priv; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + phydev->priv = priv; + + dap8211r_debug_init(priv); + phydev_dbg(phydev, "DAP8211R PHY probed\n"); + + return 0; +} + +/** + * dap8211r_remove() - PHY remove callback + * @phydev: PHY device structure + * + * Called when the PHY is removed. Cleans up private driver data + * and debugfs entries. + */ +static void dap8211r_remove(struct phy_device *phydev) +{ + dap8211r_debug_remove(phydev->priv); +} + +static struct phy_driver dap8211r_driver[] = { + { + PHY_ID_MATCH_EXACT(DAP8211R_PHY_ID), + .name = "DAP8211R Gigabit Ethernet", + .probe = dap8211r_probe, + .remove = dap8211r_remove, + .config_init = dap8211r_config_init, + .read_status = genphy_read_status, + .set_loopback = genphy_loopback, + .config_aneg = genphy_config_aneg, + .suspend = genphy_suspend, + .resume = genphy_resume, + }, +}; +module_phy_driver(dap8211r_driver); + +MODULE_DESCRIPTION("DAP8211R Gigabit Ethernet PHY driver"); +MODULE_AUTHOR("Artem Shimko <a.shimko.dev@gmail.com>"); +MODULE_LICENSE("GPL"); + +static const struct mdio_device_id __maybe_unused dap8211r_tb[] = { + { DAP8211R_PHY_ID, DAP8211R_PHY_ID_MASK }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(mdio, dap8211r_tb); -- 2.43.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH net-next 2/2] net: phy: add DAPU Telecom DAP8210R(I) Gigabit Ethernet PHY driver 2026-07-13 13:12 ` [PATCH net-next 2/2] net: phy: add DAPU Telecom DAP8210R(I) Gigabit Ethernet PHY driver Artem Shimko @ 2026-07-14 13:17 ` sashiko-bot 0 siblings, 0 replies; 7+ messages in thread From: sashiko-bot @ 2026-07-14 13:17 UTC (permalink / raw) To: Artem Shimko; +Cc: robh, conor+dt, devicetree Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider: - [High] PHY software reset is not actually triggered because the driver writes `0` to the reset bit instead of `1`. - [High] RGMII delay configurations are not explicitly cleared when the interface mode disables them. - [Medium] The debugfs package generator interface unconditionally overwrites the Auto-Negotiation state upon disable. - [Medium] The debugfs write callback modifies the PHY's MII_BMCR register without acquiring `phydev->lock`. - [Low] The driver uses a fixed sleep instead of polling the self-clearing reset bit. - [Low] Incorrect use of `abs()` macro with unsigned types causes a build failure. - [Low] The device tree property for clock inversion in the code does not match the commit message. -- --- Patch [2]: [PATCH net-next 2/2] net: phy: add DAPU Telecom DAP8210R(I) Gigabit Ethernet PHY driver --- commit 78567017e0db0de14fb31e8cedc75e8b75b18e2f Author: Artem Shimko <a.shimko.dev@gmail.com> net: phy: add DAPU Telecom DAP8210R(I) Gigabit Ethernet PHY driver This commit adds support for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY. It implements extended register access for RGMII delay configuration and provides a debugfs interface for diagnostics. > The rx-internal-delay-ps and > tx-internal-delay-ps properties allow precise tuning of clock delays in > 150 ps steps from 0 to 2250 ps, with automatic selection of the nearest > supported value if an exact match is not specified. Additionally, > the optional tx-inverted-clk flag enables 180-degree TX clock phase shift > for boards where signal integrity or MAC requirements necessitate clock [Severity: Low] The commit message documents the property as tx-inverted-clk, but the code implementation looks for tx-use-inverted-clk. Which one is the intended property name? > diff --git a/drivers/net/phy/dap8211r.c b/drivers/net/phy/dap8211r.c > new file mode 100644 > index 0000000000000..bd695bc4953a2 > --- /dev/null > +++ b/drivers/net/phy/dap8211r.c [ ... ] > +static u16 dap8211r_delay_ps_to_sel(struct phy_device *phydev, u32 ps) > +{ > + int i, best_idx = 0; > + u32 best_diff = UINT_MAX, diff = 0; > + > + if (!ps) > + return 0; > + > + for (i = 0; i < DAP8211R_DELAY_COUNT; i++) { > + diff = abs(ps - delay_config[i].ps); [Severity: Low] Does this cause a compilation error? The abs() macro in the kernel strictly checks for signed types, but the result of the subtraction here is unsigned. [ ... ] > +static int dap8211r_config_init(struct phy_device *phydev) > +{ > + struct device_node *phydev_node = phydev->mdio.dev.of_node; > + u16 mask = 0, set = 0; > + int ret; > + > + switch (phydev->interface) { > + case PHY_INTERFACE_MODE_RGMII: > + break; [Severity: High] If the bootloader configured RGMII delays, are they left intact here? By not setting the mask to clear the delays for pure RGMII mode, this leaves the PHY with whatever delays were previously configured, violating the RGMII interface contract. [ ... ] > + if (of_property_read_bool(phydev_node, "tx-use-inverted-clk")) > + set |= DAP8211R_RGMII_CLK_INVERT; > + > + mask |= DAP8211R_RGMII_CLK_INVERT; > + > + ret = dap8211r_modify_ext(phydev, DAP8211R_PHY_CON, DAP8211R_PHY_SW_RST, 0); [Severity: High] Does this write actually trigger the software reset? This clears the reset bit by passing 0 for the set argument, instead of asserting it by writing DAP8211R_PHY_SW_RST. > + if (ret) > + return ret; > + > + /* Wait for reset self-clear */ > + fsleep(200); [Severity: Low] Would it be safer to poll the self-clearing reset bit instead of using a fixed sleep? A fixed sleep might fail if the hardware reset takes longer than expected, and contradicts the comment about waiting for a self-clear. [ ... ] > +static ssize_t pkg_gen_write(struct file *file, > + const char __user *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct seq_file *sf = file->private_data; > + struct dap8211r_priv *priv = sf->private; > + struct phy_device *phydev = to_phy_device(priv->dev); > + bool en; > + u16 mask, set, set_bmcr; > + int ret; > + > + ret = kstrtobool_from_user(user_buf, count, &en); > + if (ret) > + return ret; > + > + if (en) { > + set = DAP8211R_PKG_GEN_EN | DAP8211R_PKG_CHK_EN | DAP8211R_PKG_PL_5AA5; > + > + if (priv->crc_cor) > + set |= DAP8211R_PKG_COR_CRC; > + > + if (priv->loopback) > + set_bmcr = BMCR_LOOPBACK; > + else > + set_bmcr = BMCR_ANENABLE; > + } else { > + set = DAP8211R_PKG_GEN_MODE | DAP8211R_PKG_GATE_EN; > + set_bmcr = BMCR_ANENABLE; > + } > + > + ret = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK | BMCR_ANENABLE, set_bmcr); [Severity: Medium] Is it safe to modify MII_BMCR here without acquiring phydev->lock? Concurrent execution of the phylib state machine might race with this debugfs write, leading to corrupted link state. [Severity: Medium] Does the else branch intentionally destroy the previous BMCR state? By unconditionally writing BMCR_ANENABLE to 1 when disabling the packet generator, any manual speed or duplex settings previously configured by the user via ethtool will be overwritten. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260713131223.279555-1-a.shimko.dev@gmail.com?part=2 ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-07-14 13:17 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-13 13:12 [PATCH net-next 0/2] Add DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY driver Artem Shimko 2026-07-13 13:12 ` [PATCH net-next 1/2] dt-bindings: net: add DAPU Telecom DAP8211R(I) PHY binding Artem Shimko 2026-07-13 15:51 ` Rob Herring (Arm) 2026-07-13 17:22 ` Rob Herring 2026-07-14 13:17 ` sashiko-bot 2026-07-13 13:12 ` [PATCH net-next 2/2] net: phy: add DAPU Telecom DAP8210R(I) Gigabit Ethernet PHY driver Artem Shimko 2026-07-14 13:17 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox