Skip to content

Commit

Permalink
realtek: phy: add serdes driver
Browse files Browse the repository at this point in the history
Until now we have a lot of things in the normal net/phy driver. The
SerDes stuff does not belong there. Looking around we can take a lot
of ideas from the ocelot/felix drivers and provide a nice implementation
for the realtek target. Add the driver and enable it in the readonly
mode for all 4 SoC types.

What can we do later with this:

1. Inject patch commands through the devicetree.
2. Lookup the SerDes thorugh the net/phy driver to control
   the SerDes at appropriate events (e.g. mac_config()).

The NIC adress range in the rlt839x.dtsi is inconsistent and overlaps
with the SerDes registers. Reorganize that to some meaningful range.
The NIC driver does not use that base at all.

Tested on:

RTL838x: Linksys LGS310C
RTL839x: Zyxel GS1920-24
RTL930x: Zyxel XGS1210-12
RTL931x: Linksys LGS352C

Signed-off-by: Markus Stockhausen <[email protected]>
  • Loading branch information
plappermaul committed Oct 3, 2024
1 parent d03f3dc commit 0e35d0b
Show file tree
Hide file tree
Showing 12 changed files with 1,414 additions and 2 deletions.
18 changes: 18 additions & 0 deletions target/linux/realtek/dts/rtl838x.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@
phy-mode = #m ; \
};

#define SWITCH_PORT_SDS(n, s, m, sds1, sds2) \
port@##n { \
reg = <##n>; \
label = SWITCH_PORT_LABEL(s) ; \
phy-handle = <&phy##n>; \
phy-mode = #m ; \
phys = <&serdes0 sds1 sds2>; \
};

#define SWITCH_SFP_PORT(n, s, m) \
port##n: port@##n { \
reg = <##n>; \
Expand Down Expand Up @@ -276,6 +285,15 @@
};
};

serdes0: serdes@1b00e780 {
compatible = "realtek,rtl8380-serdes", "realtek,otto-serdes";
reg = <0x1b00e780 0x1200>;
port-count = <6>;
page-count = <4>;
controlled-ports = <0x0000>;
#phy-cells = <2>;
};

sram0: sram@9f000000 {
compatible = "mmio-sram";
reg = <0x9f000000 0x10000>;
Expand Down
22 changes: 20 additions & 2 deletions target/linux/realtek/dts/rtl839x.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@
phy-mode = #m ; \
};

#define SWITCH_PORT_SDS(n, s, m, sds1, sds2) \
port@##n { \
reg = <##n>; \
label = SWITCH_PORT_LABEL(s) ; \
phy-handle = <&phy##n>; \
phy-mode = #m ; \
phys = <&serdes0 sds1 sds2>; \
};

#define SWITCH_SFP_PORT(n, s, m) \
port@##n { \
reg = <##n>; \
Expand Down Expand Up @@ -292,9 +301,9 @@
};
};

ethernet0: ethernet@1b00a300 {
ethernet0: ethernet@1b00780c {
compatible = "realtek,rtl838x-eth";
reg = <0x1b00a300 0x100>;
reg = <0x1b00780c 0x74>;

interrupt-parent = <&intc>;
interrupts = <24 3>;
Expand All @@ -307,6 +316,15 @@
};
};

serdes0: serdes@1b00a000 {
compatible = "realtek,rtl8390-serdes", "realtek,otto-serdes";
reg = <0x1b00a000 0x1c00>;
port-count = <14>;
page-count = <12>;
controlled-ports = <0x0000>;
#phy-cells = <2>;
};

sram0: sram@9f000000 {
compatible = "mmio-sram";
reg = <0x9f000000 0x18000>;
Expand Down
10 changes: 10 additions & 0 deletions target/linux/realtek/dts/rtl930x.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,16 @@
};
};

serdes0: serdes@1b0003b0 {
compatible = "realtek,rtl9300-serdes", "realtek,otto-serdes";
reg = <0x1b0003b0 0x8>;
port-count = <12>;
page-count = <64>;
controlled-ports = <0x0000>;
#phy-cells = <2>;
};


switch0: switch@1b000000 {
compatible = "realtek,rtl83xx-switch";
status = "okay";
Expand Down
9 changes: 9 additions & 0 deletions target/linux/realtek/dts/rtl931x.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,15 @@
};
};

serdes0: serdes@1b005638 {
compatible = "realtek,rtl9310-serdes", "realtek,otto-serdes";
reg = <0x1b005638 0x8>;
port-count = <14>;
page-count = <192>;
controlled-ports = <0x0000>;
#phy-cells = <2>;
};

switch0: switch@1b000000 {
compatible = "realtek,rtl83xx-switch";
status = "okay";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/realtek,otto-serdes.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Realtek Otto SerDes controller

maintainers:
- Markus Stockhausen <[email protected]>

description: |
The MIPS based Realtek Switch SoCs of the Realtek RTL838x, RTL839x,
RTL930x and RTL931x series have multiple SerDes built in. They are
linked to different single/quad/octa PHYs like the RTL8218B, RTL8218D
or RTL8214FC and are the integral part of the up-to-52-port switch
architecture.
Although the The SerDes controllers have common basics they behave
differently on the SoC families and rely on heavy register magic.
To keep the driver clean it can load patch sequences from devictree
and executes them during the controller actions like phy_init().
properties:
$nodename:
pattern: "^serdes@[0-9a-f]+$"

compatible:
items:
- enum:
- realtek,rtl8380-serdes
- realtek,rtl8390-serdes
- realtek,rtl9300-serdes
- realtek,rtl9310-serdes

reg:
items:
- description: serdes registers

port-count:
description: |
The number of SerDes ports of the SoC. The RTL838x series has 6
ports, the RTL839x has 14 ports, the RTL930x has 12 ports and the
RTL931x has 14 ports.
page-count:
description: |
The number of register pages the SerDes have. The RTL838x series
has 4 pages, the RTL839x has 12 pages, the RTL930x has 64 pages and
the RTL931x has 128 pages. Each page consists of 32 registers with
16 bit each.
controlled-ports:
description: |
A bit mask defining the ports that are actively controlled by the
driver. In case a bit is not set the driver will only process read
operations on the SerDes.
"#phy-cells":
const: 2
description: |
The first number defines the SerDes to use. The second number a
linked SerDes. E.g. if a octa 1G PHY is attached to two QSGMII
SerDes.
cmd-setup:
description: |
A field of 16 bit values that contain a patch/command sequence to run
on the SerDes registers during driver setup.
cmd-init:
description: |
A field of 16 bit values that contain a patch/command sequence to run
on the SerDes registers when a controller calls phy_init().
cmd-power-on:
description: |
A field of 16 bit values that contain a patch/command sequence to run
on the SerDes registers when a controller calls phy_power_on().
cmd-pre-set-mode:
description: |
A field of 16 bit values that contain a patch/command sequence to run
on the SerDes registers when a controller calls phy_set_mode() and before
the driver actually sets the mode.
cmd-post-set-mode:
description: |
A field of 16 bit values that contain a patch/command sequence to run
on the SerDes registers when a controller calls phy_set_mode() and after
the driver has set the mode.
cmd-pre-reset:
description: |
A field of 16 bit values that contain a patch/command sequence to run
on the SerDes registers when a controller calls phy_reset() and before
the driver actually resets the SerDes.
cmd-post-reset:
description: |
A field of 16 bit values that contain a patch/command sequence to run
on the SerDes registers when a controller calls phy_reset() and after
the driver has reset the SerDes.
cmd-pre-power-off:
description: |
A field of 16 bit values that contain a patch/command sequence to run
on the SerDes registers when a controller calls phy_power_off() and
befor the driver actually powers off the SerDes.
cmd-post-power-off:
description: |
A field of 16 bit values that contain a patch/command sequence to run
on the SerDes registers when a controller calls phy_power_off() and
after the driver has powered off the SerDes.
reguired:
- compatible
- reg
- port-count
- page-count
- controlled-ports
- "#phy-cells"

additionalProperties:
false

examples:
- |
serdes: serdes@1b00e780 {
compatible = "realtek,rtl8380-serdes", "realtek,otto-serdes";
reg = <0x1b00e780 0x1200>;
port-count = <6>;
page-count = <4>;
controlled-ports = <0x003f>;
#phy-cells = <2>;
};
- |
serdes: serdes@1b00a000 {
compatible = "realtek,rtl8390-serdes", "realtek,otto-serdes";
reg = <0x1b00a000 0x1c00>;
port-count = <14>;
page-count = <12>;
controlled-ports = <0x3fff>;
#phy-cells = <2>;
};
- |
serdes: serdes@1b0003b0 {
compatible = "realtek,rtl9300-serdes", "realtek,otto-serdes";
reg = <0x1b0003b0 0x8>;
port-count = <12>;
page-count = <64>;
controlled-ports = <0x0fff>;
#phy-cells = <2>;
};
- |
serdes: serdes@1b005638 {
compatible = "realtek,rtl9310-serdes", "realtek,otto-serdes";
reg = <0x1b005638 0x8>;
port-count = <14>;
page-count = <192>;
controlled-ports = <0x3fff>;
#phy-cells = <2>;
};
- |
#define _MASK_ 1
#define _WAIT_ 2
serdes: serdes@1b00a000 {
compatible = "realtek,rtl8390-serdes", "realtek,otto-serdes";
reg = <0x1b00a000 0x1c00>;
port-count = <14>;
page-count = <12>;
controlled-ports = <0x3fff>;
#phy-cells = <2>;
cmd-setup = /bits/ 16 <
/*
* set clock edge bit 14 during driver setup for ports 10-11
* on page 0, register 7. Wait 128 ms. Afterwards set whole
* register 0 on page 10 of ports 8, 9, 12, 13 to 0x5800.
*/
_MASK_ 0x0c00 0x00 0x07 0x4000 0x4000
_WAIT_ 0x0c00 0x00 0x00 0x0080 0x0000
_MASK_ 0x3300 0x0a 0x00 0x5800 0xffff
>;
};
Loading

0 comments on commit 0e35d0b

Please sign in to comment.