Zynq Ultrascale MPSOC Linux SIOU driver
Table of Contents
Introduction
ZynqMP SoC has a SerDes/SIOU (Serial Input and Output block) module that provides a high-speed physical interface
for the high-speed peripherals present in the SoC.
USB (2 controllers)
SATA (1 controller with two lanes)
DisplayPort (1 controller with two lanes)
SGMII (4 controllers)
PCIe (1 controller with four lanes)
The inputs to SerDes are PIPE interfaces, and the outputs are four high-speed serial lanes. PHY provides 4 output lanes only for 14 PIPE inputs (as mentioned above: 2 + 2 + 4 + 2 + 4 = 14). All inputs are routed to PHY output lanes with a mux (interconnect matrix). Only some combinations are valid; for example, USB1 cannot be assigned to lane 0. The PHY driver validates DTS entries for the correct combination of controller and SerDes lanes.
Note:
Due to the new driver introduced in the upstream flow, kernel and devicetree configurations are based on the release:
Support till 2020.2 release
Support from 2021.1 release
HW/IP Features
The ZynqMP PS shall incorporate a quad GT. Features include:
A quad transceiver
Support for PCIe, SATA, USB 3.0, SGMII, and DisplayPort requirements
1, 2, or 4-lane PCIe support at 2.5 or 5.0 Gbps
1 or 2-lane DisplayPort (TX only) at 1.62, 2.7, or 5.4 Gbps
1-2 SATA channels at 1.5, 3.0, or 6.0 Gbps
1-2 USB 3.0 channels at 5.0 Gbps
1-4 Ethernet SGMII channels at 1.25 Gbps
Supports SGMII for data only (no clock, or clock optional)
Supports any 4 of the standards simultaneously
Provides flexible host-programmable multiplexing for connecting the GT resources to the PS masters (DisplayPort, PCIe, SATA, GEM).
Kernel Configuration
Support till 2020.2 release:
Device Drivers------>
Phy Subsystem-->
<*> Xilinx ZynqMP phy driverBy enabling the above, the following Kconfig parameter should be enabled:
CONFIG_PHY_XILINX_ZYNQMP=y
Support from 2021.1 release:
Device Drivers------>
Phy Subsystem-->
-*- PHY Core
-*- Xilinx ZynqMP PHY driverBy enabling the above, the following Kconfig parameter should be enabled:
CONFIG_PHY_XILINX_ZYNQMP=y
Devicetree
Support till 2020.2 release:
Device nodes should specify the required configuration in their "phys" property, containing a phandle to the PHY port node and a device type.
The phys property should be as mentioned below:
phys = <PHANDLE CONTROLLER_TYPE CONTROLLER_INSTANCE LANE_NUM LANE_FREQ>;
PHANDLE can be any of &lane0, &lane1, &lane2, or &lane3.
CONTROLLER_TYPE can be any of PHY_TYPE_PCIE, PHY_TYPE_SATA, PHY_TYPE_USB, PHY_TYPE_DP, or PHY_TYPE_SGMII.
CONTROLLER_INSTANCE depends on the controller type used and can be any of the following:
PHY_TYPE_PCIE: 0 or 1 or 2 or 3
PHY_TYPE_SATA: 0 or 1
PHY_TYPE_USB: 0 or 1
PHY_TYPE_DP: 0 or 1
PHY_TYPE_SGMII: 0 or 1 or 2 or 3
LANE_NUM depends on which lane clock is used as refclk and can be 0, 1, 2, or 3.
LANE_FREQ is the frequency at which the controller can operate and can be any of 19.2 MHz, 20 MHz, 24 MHz, 26 MHz, 27 MHz, 28.4 MHz, 40 MHz, 52 MHz, 100 MHz, 108 MHz, 125 MHz, 135 MHz, or 150 MHz.
Example
The code below is required for probing the SerDes driver. This should be added in zynqmp.dtsi.
serdes: zynqmp_phy@fd400000 {
compatible = "xlnx,zynqmp-psgtr";
status = "okay";
reg = <0x0 0xfd400000 0x0 0x40000>, <0x0 0xfd3d0000 0x0 0x1000>,
<0x0 0xfd1a0000 0x0 0x1000>, <0x0 0xff5e0000 0x0 0x1000>;
reg-names = "serdes", "siou", "fpd", "lpd";
xlnx,tx_termination_fix;
lane0: lane@0 {
#phy-cells = <4>;
};
lane1: lane@1 {
#phy-cells = <4>;
};
lane2: lane@2 {
#phy-cells = <4>;
};
lane3: lane@3 {
#phy-cells = <4>;
};
};The code below configures USB instance 0 to use lane 2 and get a 26 MHz lane refclk from lane 2.
usb@fe200000 {
...
phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
...
};The code below configures SATA instance 1 to use lane 3 and get a 125 MHz lane refclk from lane 1.
ahci@fd0c0000 {
...
phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
...
};Support from 2021.1 release:
In the new upstream flow, the following changes need to be added:
phys = <PHANDLE LANE_NUM CONTROLLER_TYPE CONTROLLER_INSTANCE LANE_FREQ>;
PHANDLE = &psgtr
LANE_NUM = 0, 1, 2, 3
CONTROLLER_TYPE = PHY_TYPE_PCIE, PHY_TYPE_SATA, PHY_TYPE_USB, PHY_TYPE_DP, or PHY_TYPE_SGMII
CONTROLLER_INSTANCE depends on the controller type used and can be any of the following:
PHY_TYPE_PCIE: 0 or 1 or 2 or 3
PHY_TYPE_SATA: 0 or 1
PHY_TYPE_USB: 0 or 1
PHY_TYPE_DP: 0 or 1
PHY_TYPE_SGMII: 0 or 1 or 2 or 3
LANE_FREQ = refclk number that has the desired frequency
Example:
PSGTR changes:
refclk4:psgtr_dp_clock {
compatible = "fixed-clock";
#clock-cells = <0x00>;
clock-frequency = <27000000>;
};
refclk3:psgtr_usb_clock {
compatible = "fixed-clock";
#clock-cells = <0x00>;
clock-frequency = <26000000>;
};
refclk2:psgtr_sata_clock {
compatible = "fixed-clock";
#clock-cells = <0x00>;
clock-frequency = <125000000>;
};
refclk1:psgtr_pcie_clock {
compatible = "fixed-clock";
#clock-cells = <0x00>;
clock-frequency = <150000000>;
};
psgtr: phy@fd400000 {
compatible = "xlnx,zynqmp-psgtr-v1.1";
reg = <0x00 0xfd400000 0x00 0x40000 0x00 0xfd3d0000 0x00 0x1000>;
reg-names = "serdes\0siou";
#clock-cells = <0x01>;
clocks = <&refclk1 &refclk2 &refclk3 &refclk4>;
/* refclk instances used per lane */
clock-names = "ref0\0ref1\0ref2\0ref3";
#phy-cells = <0x04>;
status = "okay";
};SATA instance 1 using lane 3 refclk 125 MHz:
ahci@fd0c0000 {
compatible = "ceva,ahci-1v84";
status = "okay";
reg = <0x00 0xfd0c0000 0x00 0x2000>;
.....
/* psgtr_phandle....lane number... controller_type...instance....refclk */
phys = <&psgtr 0x3 PHY_TYPE_SATA 0x01 0x1>;
reset-names = "sata_rst";
resets = <0x1a 0x10>;
};USB instance 0 using lane 2 refclk 26 MHz:
usb0@ff9d0000 {
#address-cells = <0x02>;
#size-cells = <0x02>;
status = "okay";
compatible = "xlnx,zynqmp-dwc3";
reg = <0x00 0xff9d0000 0x00 0x100>;
clock-names = "bus_clk\0ref_clk";
....
resets = <0x1a 0x3b 0x1a 0x3d 0x1a 0x3f>;
reset-names = "usb_crst\0usb_hibrst\0usb_apbrst";
......
dwc3@fe200000 {
compatible = "snps,dwc3";
status = "okay";
reg = <0x00 0xfe200000 0x00 0x40000>;
interrupt-parent = <0x04>;
interrupt-names = "dwc_usb3\0otg\0hiber";
interrupts = <0x00 0x41 0x04 0x00 0x45 0x04 0x00 0x4b 0x04>;
#stream-id-cells = <0x01>;
.....
dr_mode = "host";
maximum-speed = "super-speed";
phy-names = "usb3-phy";
/* psgtr_phandle....lane number... controller_type...instance....refclk */
phys = <&psgtr 0x2 PHY_TYPE_USB 0x00 0x02>;
};
};Test Procedure
As this driver is used by SATA, USB, PCIe, SGMII, and DP protocols, testing the functionality of any of those protocols will automatically test this IP.
Expected Output
Once Linux is booted, type "dmesg | grep gtr" and check whether PLL lock is happening. The output below is expected:
root@Xilinx-ZCU102-2016_3:~# dmesg | grep gtr
[ 6.575387] xilinx-psgtr fd400000.zynqmp_phy: Lane:3 type:3 protocol:2 pll_locked:yes
[ 6.808627] xilinx-psgtr fd400000.zynqmp_phy: Lane:2 type:0 protocol:3 pll_locked:yes
[ 7.570858] xilinx-psgtr fd400000.zynqmp_phy: Lane:1 type:8 protocol:4 pll_locked:yesMainline Status
The current driver available in the Xilinx Linux git is in sync (except one suspend/resume fix for USB) with the open-source kernel.
Change log
2026.1
Kernel upgrade to 6.18, fix USB enumeration failure on suspend/resume.
a743371c36f2 phy: zynqmp: keep SERDES scrambler and 8b/10b enabled for USB
066fd30275f9 phy: zynqmp: use read-modify-write for SERDES scrambler bypass
af1f75b10e07 phy: zynqmp: fix L0_TM_DISABLE_SCRAMBLE_ENCODER mask
2025.2
None
2025.1
Kernel upgrade to 6.12
2024.2
phy: xilinx: phy-zynqmp: Fix SGMII linkup failure on resume 4dd8383fcbe1
2024.1
Kernel upgrade to 6.6
2023.2
None
2023.1
Kernel upgrade to 6.1
Updated comment description: SGMII is validated on SOM KR260. 7f2f1a1
2022.2
None
2022.1
Kernel upgrade to 5.15
Fix bus width setting for SGMII 5d691d
2021.2
None
2021.1
ZynqMP: Add PHY driver for the Xilinx ZynqMP Gigabit Transceiver
Fix unused-function compiler warning
Handle the clock enable/disable properly
Skip PHY initialization and PLL lock for USB
Note: This new PSGTR configuration is applicable from Xilinx 2021.1 release onward.