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 4, 2024
1 parent d03f3dc commit 304a249
Show file tree
Hide file tree
Showing 12 changed files with 1,599 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,179 @@
# 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 or 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. If not set the driver will run all ports in read only mode.
"#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 before 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
- "#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 304a249

Please sign in to comment.