* [PATCH v5 4/5] arm64: dts: qcom: Add Shikra IQ2390S SoM platform
From: Komal Bajaj @ 2026-06-11 10:10 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Neil Armstrong, Wesley Cheng,
Ulf Hansson
Cc: linux-arm-msm, devicetree, linux-kernel, linux-phy, linux-mmc,
monish.chunara, Komal Bajaj
In-Reply-To: <20260611-shikra-dt-v5-0-103ed26a8529@oss.qualcomm.com>
Add device tree include for the IQ2390S variant of the Shikra
System-on-Module, an industrial compute module integrating the Shikra
SoC and PMIC for industrial IoT applications, designed to mount on
carrier boards.
- shikra-iqs-som.dtsi: Industrial SoM without modem (PM8150 PMIC)
The DTSI includes the common shikra.dtsi and adds PM8150 PMIC regulator
definitions specific to this variant.
Signed-off-by: Komal Bajaj <komal.bajaj@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi | 170 +++++++++++++++++++++++++++
1 file changed, 170 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi
new file mode 100644
index 000000000000..73945bf42112
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+
+#include "shikra.dtsi"
+#include "pm8150.dtsi"
+
+/ {
+ gpio-key {
+ compatible = "gpio-keys";
+ label = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&vol_up_n>;
+
+ key-volume-up {
+ label = "Volume Up";
+ gpios = <&pm8150_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <KEY_VOLUMEUP>;
+ wakeup-source;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+ };
+};
+
+&pm8150_gpios {
+ vol_up_n: vol-up-n-state {
+ pins = "gpio6";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ input-enable;
+ bias-pull-up;
+ power-source = <0>;
+ };
+
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&rpm_requests {
+ regulators {
+ compatible = "qcom,rpm-pm8150-regulators";
+
+ pm8150_s4: s4 {
+ regulator-min-microvolt = <1080000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ pm8150_s5: s5 {
+ regulator-min-microvolt = <1574000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ pm8150_s6: s6 {
+ regulator-min-microvolt = <382000>;
+ regulator-max-microvolt = <1352000>;
+ };
+
+ pm8150_s7: s7 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8150_s8: s8 {
+ regulator-min-microvolt = <570000>;
+ regulator-max-microvolt = <650000>;
+ };
+
+ pm8150_l1: l1 {
+ regulator-min-microvolt = <312000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ pm8150_l2: l2 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8150_l3: l3 {
+ regulator-min-microvolt = <312000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ pm8150_l4: l4 {
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <975000>;
+ };
+
+ pm8150_l5: l5 {
+ regulator-min-microvolt = <788000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ pm8150_l6: l6 {
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ pm8150_l7: l7 {
+ regulator-min-microvolt = <1504000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ pm8150_l8: l8 {
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ pm8150_l9: l9 {
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ pm8150_l10: l10 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ };
+
+ pm8150_l11: l11 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ pm8150_l12: l12 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <1950000>;
+ };
+
+ pm8150_l13: l13 {
+ regulator-min-microvolt = <2921000>;
+ regulator-max-microvolt = <3230000>;
+ };
+
+ pm8150_l14: l14 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1910000>;
+ };
+
+ pm8150_l15: l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1900000>;
+ };
+
+ pm8150_l16: l16 {
+ regulator-min-microvolt = <1504000>;
+ regulator-max-microvolt = <3544000>;
+ };
+
+ pm8150_l17: l17 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ };
+
+ pm8150_l18: l18 {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <728000>;
+ };
+ };
+};
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v5 3/5] arm64: dts: qcom: Add Shikra CQ2390M SoM platform
From: Komal Bajaj @ 2026-06-11 10:10 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Neil Armstrong, Wesley Cheng,
Ulf Hansson
Cc: linux-arm-msm, devicetree, linux-kernel, linux-phy, linux-mmc,
monish.chunara, Komal Bajaj, Rakesh Kota
In-Reply-To: <20260611-shikra-dt-v5-0-103ed26a8529@oss.qualcomm.com>
Add device tree include for the CQ2390M variant of the Shikra
System-on-Module, a compact compute module integrating the Shikra SoC
and PMIC for IoT applications, designed to mount on carrier boards.
- shikra-cqm-som.dtsi: Retail SoM with modem (PM4125 and PM8005 PMIC)
The DTSI includes the common shikra.dtsi, adds PM4125 and PM8005 PMIC
peripheral definitions specific to this variant. Since PM8005 regulators
are controlled by rpmpd, so disabling the pm8005 regulators.
Co-developed-by: Rakesh Kota <rakesh.kota@oss.qualcomm.com>
Signed-off-by: Rakesh Kota <rakesh.kota@oss.qualcomm.com>
Signed-off-by: Komal Bajaj <komal.bajaj@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 156 +++++++++++++++++++++++++++
1 file changed, 156 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi
new file mode 100644
index 000000000000..dc3861489f64
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+
+#include "shikra.dtsi"
+#include "pm4125.dtsi"
+#include "pm8005.dtsi"
+
+/ {
+ gpio-keys {
+ compatible = "gpio-keys";
+ label = "gpio-keys";
+ pinctrl-0 = <&vol_up_n>;
+ pinctrl-names = "default";
+
+ key-volume-up {
+ label = "Volume Up";
+ gpios = <&pm4125_gpios 9 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <KEY_VOLUMEUP>;
+ wakeup-source;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+ };
+};
+
+&pm4125_gpios {
+ vol_up_n: vol-up-n-state {
+ pins = "gpio9";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ input-enable;
+ bias-pull-up;
+ power-source = <0>;
+ };
+};
+
+&pm4125_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+
+ status = "okay";
+};
+
+&pm8005_regulators {
+ status = "disabled";
+};
+
+&rpm_requests {
+ regulators {
+ compatible = "qcom,rpm-pm2250-regulators";
+
+ pm4125_s2: s2 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm4125_l3: l3 {
+ regulator-min-microvolt = <624000>;
+ regulator-max-microvolt = <650000>;
+ };
+
+ pm4125_l4: l4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ };
+
+ pm4125_l5: l5 {
+ regulator-min-microvolt = <1232000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ pm4125_l6: l6 {
+ regulator-min-microvolt = <788000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ pm4125_l7: l7 {
+ regulator-min-microvolt = <664000>;
+ regulator-max-microvolt = <664000>;
+ };
+
+ pm4125_l8: l8 {
+ regulator-min-microvolt = <928000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ pm4125_l9: l9 {
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ pm4125_l10: l10 {
+ regulator-min-microvolt = <1304000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ pm4125_l12: l12 {
+ regulator-min-microvolt = <928000>;
+ regulator-max-microvolt = <975000>;
+ };
+
+ pm4125_l13: l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm4125_l14: l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm4125_l15: l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm4125_l16: l16 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm4125_l17: l17 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3544000>;
+ };
+
+ pm4125_l18: l18 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ };
+
+ pm4125_l19: l19 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ };
+
+ pm4125_l20: l20 {
+ regulator-min-microvolt = <2952000>;
+ regulator-max-microvolt = <2952000>;
+ };
+
+ pm4125_l21: l21 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3056000>;
+ };
+
+ pm4125_l22: l22 {
+ regulator-min-microvolt = <3304000>;
+ regulator-max-microvolt = <3304000>;
+ };
+ };
+};
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v5 2/5] arm64: dts: qcom: Introduce Shikra SoC base dtsi
From: Komal Bajaj @ 2026-06-11 10:10 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Neil Armstrong, Wesley Cheng,
Ulf Hansson
Cc: linux-arm-msm, devicetree, linux-kernel, linux-phy, linux-mmc,
monish.chunara, Komal Bajaj, Imran Shaik, Monish Chunara,
Rakesh Kota, Raviteja Laggyshetty, Sneh Mankad, Vishnu Santhosh,
Xueyao An, Konrad Dybcio
In-Reply-To: <20260611-shikra-dt-v5-0-103ed26a8529@oss.qualcomm.com>
Add initial device tree support for the Qualcomm Shikra SoC,
an IoT-focused platform built around a heterogeneous CPU cluster
(Cortex-A55 + Cortex-A78C) with RPM-based power and clock management.
Enable support for the following peripherals:
- CPU nodes
- Global Clock Controller (GCC)
- RPM-based clock controller (RPMCC) and power domains (RPMPD)
- Interrupt controller
- Top Level Mode Multiplexer (TLMM)
- Debug UART
- eMMC host controller
- System timer and watchdog
Co-developed-by: Imran Shaik <imran.shaik@oss.qualcomm.com>
Signed-off-by: Imran Shaik <imran.shaik@oss.qualcomm.com>
Co-developed-by: Monish Chunara <quic_mchunara@quicinc.com>
Signed-off-by: Monish Chunara <quic_mchunara@quicinc.com>
Co-developed-by: Rakesh Kota <rakesh.kota@oss.qualcomm.com>
Signed-off-by: Rakesh Kota <rakesh.kota@oss.qualcomm.com>
Co-developed-by: Raviteja Laggyshetty <raviteja.laggyshetty@oss.qualcomm.com>
Signed-off-by: Raviteja Laggyshetty <raviteja.laggyshetty@oss.qualcomm.com>
Co-developed-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
Signed-off-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
Co-developed-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com>
Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com>
Co-developed-by: Xueyao An <xueyao.an@oss.qualcomm.com>
Signed-off-by: Xueyao An <xueyao.an@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Komal Bajaj <komal.bajaj@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/shikra.dtsi | 842 +++++++++++++++++++++++++++++++++++
1 file changed, 842 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi
new file mode 100644
index 000000000000..cc3de21c1ff9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/shikra.dtsi
@@ -0,0 +1,842 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/clock/qcom,shikra-gcc.h>
+#include <dt-bindings/interconnect/qcom,icc.h>
+#include <dt-bindings/interconnect/qcom,rpm-icc.h>
+#include <dt-bindings/interconnect/qcom,shikra.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+/ {
+ interrupt-parent = <&intc>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clocks {
+ xo_board: xo-board {
+ compatible = "fixed-clock";
+ clock-frequency = <38400000>;
+ #clock-cells = <0>;
+ };
+
+ sleep_clk: sleep-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <32764>;
+ #clock-cells = <0>;
+ };
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ next-level-cache = <&l3>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
+ };
+
+ cpu1: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ next-level-cache = <&l3>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
+ };
+
+ cpu2: cpu@200 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0 0x200>;
+ enable-method = "psci";
+ next-level-cache = <&l3>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
+ };
+
+ cpu3: cpu@300 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a78c";
+ reg = <0x0 0x300>;
+ enable-method = "psci";
+ next-level-cache = <&l2_3>;
+ capacity-dmips-mhz = <1946>;
+ dynamic-power-coefficient = <489>;
+
+ l2_3: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3>;
+ cache-size = <0x40000>;
+ };
+ };
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+
+ core1 {
+ cpu = <&cpu1>;
+ };
+
+ core2 {
+ cpu = <&cpu2>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu3>;
+ };
+ };
+ };
+
+ l3: l3-cache {
+ compatible = "cache";
+ cache-level = <3>;
+ cache-unified;
+ cache-size = <0x80000>;
+ };
+ };
+
+ firmware {
+ scm {
+ compatible = "qcom,scm-shikra", "qcom,scm";
+ clocks = <&rpmcc RPM_SMD_CE1_CLK>;
+ clock-names = "core";
+ qcom,dload-mode = <&tcsr_regs 0x13000>;
+ #reset-cells = <1>;
+ interconnects = <&system_noc MASTER_CRYPTO_CORE0 RPM_ALWAYS_TAG
+ &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ /* We expect the bootloader to fill in the size */
+ reg = <0x0 0x80000000 0x0 0x0>;
+ };
+
+ pmu-a55 {
+ compatible = "arm,cortex-a55-pmu";
+ interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH &ppi_cluster0>;
+ };
+
+ pmu-a78c {
+ compatible = "arm,cortex-a78-pmu";
+ interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH &ppi_cluster1>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ rpm: remoteproc {
+ compatible = "qcom,shikra-rpm-proc", "qcom,rpm-proc";
+
+ glink-edge {
+ compatible = "qcom,glink-rpm";
+ interrupts = <GIC_SPI 194 IRQ_TYPE_EDGE_RISING 0>;
+ qcom,rpm-msg-ram = <&rpm_msg_ram>;
+ mboxes = <&apcs_glb 0>;
+
+ rpm_requests: rpm-requests {
+ compatible = "qcom,rpm-shikra", "qcom,glink-smd-rpm";
+ qcom,glink-channels = "rpm_requests";
+
+ rpmcc: clock-controller {
+ compatible = "qcom,rpmcc-shikra", "qcom,rpmcc-qcm2290", "qcom,rpmcc";
+ clocks = <&xo_board>;
+ clock-names = "xo";
+ #clock-cells = <1>;
+ };
+
+ rpmpd: power-controller {
+ compatible = "qcom,shikra-rpmpd";
+ #power-domain-cells = <1>;
+ operating-points-v2 = <&rpmpd_opp_table>;
+
+ rpmpd_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ rpmpd_opp_min_svs: opp1 {
+ opp-level = <RPM_SMD_LEVEL_MIN_SVS>;
+ };
+
+ rpmpd_opp_low_svs: opp2 {
+ opp-level = <RPM_SMD_LEVEL_LOW_SVS>;
+ };
+
+ rpmpd_opp_svs: opp3 {
+ opp-level = <RPM_SMD_LEVEL_SVS>;
+ };
+
+ rpmpd_opp_svs_plus: opp4 {
+ opp-level = <RPM_SMD_LEVEL_SVS_PLUS>;
+ };
+
+ rpmpd_opp_nom: opp5 {
+ opp-level = <RPM_SMD_LEVEL_NOM>;
+ };
+
+ rpmpd_opp_nom_plus: opp6 {
+ opp-level = <RPM_SMD_LEVEL_NOM_PLUS>;
+ };
+
+ rpmpd_opp_turbo: opp7 {
+ opp-level = <RPM_SMD_LEVEL_TURBO>;
+ };
+
+ rpmpd_opp_turbo_plus: opp8 {
+ opp-level = <RPM_SMD_LEVEL_TURBO_NO_CPR>;
+ };
+ };
+ };
+ };
+ };
+
+ mpm: interrupt-controller {
+ compatible = "qcom,mpm";
+ qcom,rpm-msg-ram = <&apss_mpm>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING 0>;
+ mboxes = <&apcs_glb 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ #power-domain-cells = <0>;
+ interrupt-parent = <&intc>;
+ qcom,mpm-pin-count = <96>;
+ qcom,mpm-pin-map = <2 275>, /* TSENS0 uplow */
+ <12 422>, /* DWC3 ss_phy_irq */
+ <58 272>, /* QUSB2_PHY dmse_hv_vddmx */
+ <59 273>, /* QUSB2_PHY dpse_hv_vddmx */
+ <86 183>, /* MPM wake, SPMI */
+ <90 157>, /* QUSB2_PHY DM */
+ <91 158>; /* QUSB2_PHY DP */
+ };
+ };
+
+ reserved_memory: reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ hyp_mem: hyp@80000000 {
+ reg = <0x0 0x80000000 0x0 0x1600000>;
+ no-map;
+ };
+
+ xblboot_mem: xblboot@85e00000 {
+ reg = <0x0 0x85e00000 0x0 0x100000>;
+ no-map;
+ };
+
+ secdata_apss_mem: secdata-apss@85fff000 {
+ reg = <0x0 0x85fff000 0x0 0x1000>;
+ no-map;
+ };
+
+ smem_mem: smem@86000000 {
+ compatible = "qcom,smem";
+ reg = <0x0 0x86000000 0x0 0x200000>;
+ no-map;
+
+ hwlocks = <&tcsr_mutex 3>;
+ };
+
+ audio_heap_mem: audio-heap@86200000 {
+ reg = <0x0 0x86200000 0x0 0x100000>;
+ no-map;
+ };
+
+ tz_stat_mem: tz-stat@a0000000 {
+ reg = <0x0 0xa0000000 0x0 0x100000>;
+ no-map;
+ };
+
+ qtee_mem: qtee@a1300000 {
+ reg = <0x0 0xa1300000 0x0 0x500000>;
+ no-map;
+ };
+
+ tz_apps_mem: tz-apps@a1800000 {
+ reg = <0x0 0xa1800000 0x0 0x2100000>;
+ no-map;
+ };
+
+ mpss_wlan_mem: mpss-wlan@ab000000 {
+ reg = <0x0 0xab000000 0x0 0x6e00000>;
+ no-map;
+ };
+
+ wlan_mem: wlan@b2300000 {
+ reg = <0x0 0xb2300000 0x0 0x100000>;
+ no-map;
+ };
+
+ cdsp_mem: cdsp@b2400000 {
+ reg = <0x0 0xb2400000 0x0 0x1900000>;
+ no-map;
+ };
+
+ gpu_micro_code_mem: gpu-micro-code@b3d00000 {
+ reg = <0x0 0xb3d00000 0x0 0x2000>;
+ no-map;
+ };
+
+ video_mem: video@b3d02000 {
+ reg = <0x0 0xb3d02000 0x0 0x700000>;
+ no-map;
+ };
+
+ lmcu_mem: lmcu@b4402000 {
+ reg = <0x0 0xb4402000 0x0 0x300000>;
+ no-map;
+ };
+
+ lmcu_dtb_mem: lmcu-dtb@b4702000 {
+ reg = <0x0 0xb4702000 0x0 0x40000>;
+ no-map;
+ };
+ };
+
+ soc: soc@0 {
+ compatible = "simple-bus";
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dma-ranges = <0x0 0x0 0x0 0x0 0x10 0x0>;
+ ranges = <0x0 0x0 0x0 0x0 0x10 0x0>;
+
+ tcsr_mutex: syscon@340000 {
+ compatible = "qcom,tcsr-mutex";
+ reg = <0x0 0x00340000 0x0 0x20000>;
+ #hwlock-cells = <1>;
+ };
+
+ tcsr_regs: syscon@3c0000 {
+ compatible = "qcom,shikra-tcsr", "syscon";
+ reg = <0x0 0x003c0000 0x0 0x40000>;
+ };
+
+ tlmm: pinctrl@500000 {
+ compatible = "qcom,shikra-tlmm";
+ reg = <0x0 0x00500000 0x0 0x700000>;
+
+ interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH 0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ gpio-ranges = <&tlmm 0 0 165>;
+ wakeup-parent = <&mpm>;
+
+ qup_uart0_default: qup-uart0-default-state {
+ pins = "gpio0", "gpio1";
+ function = "qup0_se0";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ sdc1_state_on: sdc1-on-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ rclk-pins {
+ pins = "sdc1_rclk";
+ bias-pull-down;
+ };
+ };
+
+ sdc1_state_off: sdc1-off-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ drive-strength = <2>;
+ bias-bus-hold;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ drive-strength = <2>;
+ bias-bus-hold;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ drive-strength = <2>;
+ bias-bus-hold;
+ };
+
+ rclk-pins {
+ pins = "sdc1_rclk";
+ bias-bus-hold;
+ };
+ };
+ };
+
+ mem_noc: interconnect@d00000 {
+ compatible = "qcom,shikra-mem-noc-core";
+ reg = <0x0 0x00d00000 0x0 0x43080>;
+ clocks = <&gcc GCC_DDRSS_GPU_AXI_CLK>;
+ clock-names = "gpu_axi";
+ #interconnect-cells = <2>;
+ };
+
+ llcc: system-cache-controller@e00000 {
+ compatible = "qcom,shikra-llcc";
+ reg = <0x0 0x00e00000 0x0 0x80000>,
+ <0x0 0x00f00000 0x0 0x80000>,
+ <0x0 0x01000000 0x0 0x80000>;
+ reg-names = "llcc0_base",
+ "llcc1_base",
+ "llcc_broadcast_base";
+ interrupts = <GIC_SPI 539 IRQ_TYPE_LEVEL_HIGH 0>;
+ };
+
+ gcc: clock-controller@1400000 {
+ compatible = "qcom,shikra-gcc";
+ reg = <0x0 0x01400000 0x0 0x1f0000>;
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&sleep_clk>,
+ <0>,
+ <0>,
+ <0>,
+ <0>,
+ <0>,
+ <0>;
+ power-domains = <&rpmpd RPMPD_VDDCX>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ system_noc: interconnect@1880000 {
+ compatible = "qcom,shikra-sys-noc";
+ reg = <0x0 0x01880000 0x0 0x6a080>;
+ clocks = <&gcc GCC_EMAC0_AXI_SYS_NOC_CLK>,
+ <&gcc GCC_EMAC1_AXI_SYS_NOC_CLK>,
+ <&gcc GCC_SYS_NOC_USB2_PRIM_AXI_CLK>,
+ <&gcc GCC_SYS_NOC_USB3_PRIM_AXI_CLK>;
+ clock-names = "emac0_axi",
+ "emac1_axi",
+ "usb2_axi",
+ "usb3_axi";
+ #interconnect-cells = <2>;
+
+ clk_virt: interconnect-clk {
+ compatible = "qcom,shikra-clk-virt";
+ #interconnect-cells = <2>;
+ };
+
+ mc_virt: interconnect-mc {
+ compatible = "qcom,shikra-mc-virt";
+ #interconnect-cells = <2>;
+ };
+
+ mmrt_virt: interconnect-mmrt {
+ compatible = "qcom,shikra-mmrt-virt";
+ #interconnect-cells = <2>;
+ };
+
+ mmnrt_virt: interconnect-mmnrt {
+ compatible = "qcom,shikra-mmnrt-virt";
+ #interconnect-cells = <2>;
+ };
+ };
+
+ config_noc: interconnect@1900000 {
+ compatible = "qcom,shikra-config-noc";
+ reg = <0x0 0x01900000 0x0 0x8080>;
+ #interconnect-cells = <2>;
+ };
+
+ qfprom: efuse@1b44000 {
+ compatible = "qcom,shikra-qfprom", "qcom,qfprom";
+ reg = <0x0 0x01b44000 0x0 0x3000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qusb2_hstx_trim_1: hstx-trim@25b {
+ reg = <0x25b 0x1>;
+ bits = <1 4>;
+ };
+
+ gpu_speed_bin: gpu-speed-bin@2006 {
+ reg = <0x2006 0x2>;
+ bits = <5 8>;
+ };
+ };
+
+ spmi_bus: spmi@1c40000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x0 0x01c40000 0x0 0x1100>,
+ <0x0 0x01e00000 0x0 0x2000000>,
+ <0x0 0x03e00000 0x0 0x100000>,
+ <0x0 0x03f00000 0x0 0xa0000>,
+ <0x0 0x01c0a000 0x0 0x26000>;
+ reg-names = "core",
+ "chnls",
+ "obsrvr",
+ "intr",
+ "cnfg";
+ interrupts-extended = <&mpm 86 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "periph_irq";
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ qcom,channel = <0>;
+ qcom,ee = <0>;
+ };
+
+ rpm_msg_ram: sram@45f0000 {
+ compatible = "qcom,rpm-msg-ram", "mmio-sram";
+ reg = <0x0 0x045f0000 0x0 0x7000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x0 0x045f0000 0x7000>;
+
+ apss_mpm: sram@1b8 {
+ reg = <0x1b8 0x48>;
+ };
+ };
+
+ sram@4690000 {
+ compatible = "qcom,rpm-stats";
+ reg = <0x0 0x04690000 0x0 0x14000>;
+ };
+
+ sdhc_1: mmc@4744000 {
+ compatible = "qcom,shikra-sdhci", "qcom,sdhci-msm-v5";
+
+ reg = <0x0 0x04744000 0x0 0x1000>,
+ <0x0 0x04745000 0x0 0x1000>;
+ reg-names = "hc",
+ "cqhci";
+
+ iommus = <&apps_smmu 0xc0 0x0>;
+
+ interrupts = <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "hc_irq",
+ "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC1_AHB_CLK>,
+ <&gcc GCC_SDCC1_APPS_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface",
+ "core",
+ "xo";
+
+ interconnects = <&system_noc MASTER_SDCC_1 RPM_ALWAYS_TAG
+ &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>,
+ <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG
+ &config_noc SLAVE_SDCC_1 RPM_ACTIVE_TAG>;
+ interconnect-names = "sdhc-ddr",
+ "cpu-sdhc";
+
+ power-domains = <&rpmpd RPMPD_VDDCX>;
+ operating-points-v2 = <&sdhc1_opp_table>;
+
+ qcom,dll-config = <0x000f642c>;
+ qcom,ddr-config = <0x80040868>;
+
+ bus-width = <8>;
+
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+
+ resets = <&gcc GCC_SDCC1_BCR>;
+
+ status = "disabled";
+
+ sdhc1_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ opp-peak-kBps = <250000 133320>;
+ opp-avg-kBps = <104000 0>;
+ };
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ opp-peak-kBps = <800000 300000>;
+ opp-avg-kBps = <400000 0>;
+ };
+ };
+ };
+
+ qupv3_0: geniqup@4ac0000 {
+ compatible = "qcom,geni-se-qup";
+ reg = <0x0 0x04ac0000 0x0 0x2000>;
+
+ clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+ <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+ clock-names = "m-ahb",
+ "s-ahb";
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ uart0: serial@4a80000 {
+ compatible = "qcom,geni-debug-uart";
+ reg = <0x0 0x04a80000 0x0 0x4000>;
+
+ interrupts = <GIC_SPI 527 IRQ_TYPE_LEVEL_HIGH 0>;
+
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ clock-names = "se";
+
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG
+ &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>,
+ <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG
+ &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>;
+ interconnect-names = "qup-core",
+ "qup-config";
+
+ pinctrl-0 = <&qup_uart0_default>;
+ pinctrl-names = "default";
+
+ status = "disabled";
+ };
+ };
+
+ sram@c11e000 {
+ compatible = "qcom,shikra-imem", "mmio-sram";
+ reg = <0x0 0x0c11e000 0x0 0x1000>;
+ ranges = <0x0 0x0 0x0c11e000 0x1000>;
+
+ no-memory-wc;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pil-sram@94c {
+ compatible = "qcom,pil-reloc-info";
+ reg = <0x94c 0xc8>;
+ };
+ };
+
+ apps_smmu: iommu@c600000 {
+ compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500";
+ reg = <0x0 0x0c600000 0x0 0x80000>;
+ #iommu-cells = <2>;
+ #global-interrupts = <1>;
+
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH 0>;
+ };
+
+ intc: interrupt-controller@f200000 {
+ compatible = "arm,gic-v3";
+ reg = <0x0 0xf200000 0x0 0x10000>,
+ <0x0 0xf240000 0x0 0x80000>;
+
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>;
+
+ #interrupt-cells = <4>;
+ interrupt-controller;
+
+ #redistributor-regions = <1>;
+ redistributor-stride = <0x0 0x20000>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ppi-partitions {
+ ppi_cluster0: interrupt-partition-0 {
+ affinity = <&cpu0 &cpu1 &cpu2>;
+ };
+
+ ppi_cluster1: interrupt-partition-1 {
+ affinity = <&cpu3>;
+ };
+ };
+ };
+
+ apcs_glb: mailbox@f400000 {
+ compatible = "qcom,shikra-apss-shared", "qcom,sdm845-apss-shared";
+ reg = <0x0 0x0f400000 0x0 0x1000>;
+ #mbox-cells = <1>;
+ };
+
+ watchdog@f410000 {
+ compatible = "qcom,apss-wdt-shikra", "qcom,kpss-wdt";
+ reg = <0x0 0x0f410000 0x0 0x1000>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&sleep_clk>;
+ };
+
+ timer@f420000 {
+ compatible = "arm,armv7-timer-mem";
+ reg = <0x0 0x0f420000 0x0 0x1000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x0 0x10000000>;
+
+ frame@f421000 {
+ reg = <0x0f421000 0x1000>,
+ <0x0f422000 0x1000>;
+ frame-number = <0>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH 0>;
+ };
+
+ frame@f423000 {
+ reg = <0x0f423000 0x1000>;
+ frame-number = <1>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH 0>;
+ status = "disabled";
+ };
+
+ frame@f425000 {
+ reg = <0x0f425000 0x1000>;
+ frame-number = <2>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH 0>;
+ status = "disabled";
+ };
+
+ frame@f427000 {
+ reg = <0x0f427000 0x1000>;
+ frame-number = <3>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH 0>;
+ status = "disabled";
+ };
+
+ frame@f429000 {
+ reg = <0x0f429000 0x1000>;
+ frame-number = <4>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH 0>;
+ status = "disabled";
+ };
+
+ frame@f42b000 {
+ reg = <0x0f42b000 0x1000>;
+ frame-number = <5>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH 0>;
+ status = "disabled";
+ };
+
+ frame@f42d000 {
+ reg = <0x0f42d000 0x1000>;
+ frame-number = <6>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH 0>;
+ status = "disabled";
+ };
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+
+ interrupts = <GIC_PPI 1 IRQ_TYPE_LEVEL_LOW 0>,
+ <GIC_PPI 2 IRQ_TYPE_LEVEL_LOW 0>,
+ <GIC_PPI 3 IRQ_TYPE_LEVEL_LOW 0>,
+ <GIC_PPI 0 IRQ_TYPE_LEVEL_LOW 0>;
+ };
+};
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v5 1/5] dt-bindings: arm: qcom: Document Shikra and its EVK boards
From: Komal Bajaj @ 2026-06-11 10:10 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Neil Armstrong, Wesley Cheng,
Ulf Hansson
Cc: linux-arm-msm, devicetree, linux-kernel, linux-phy, linux-mmc,
monish.chunara, Komal Bajaj
In-Reply-To: <20260611-shikra-dt-v5-0-103ed26a8529@oss.qualcomm.com>
Shikra is a Qualcomm IoT SoC available in a System-on-Module (SoM)
form factor. The SoM integrates the Shikra SoC, PMICs, and essential
passives, and is designed to be mounted on carrier boards.
Three eSoM variant are introduced:
- CQM: retail variant with integrated modem (PM4125 and PM8005 PMIC)
- CQS: retail variant without modem (PM4125 and PM8005 PMIC)
- IQS: industrial-grade variant without modem (PM8150 PMIC)
Each SoM variant pairs with a common EVK carrier board provides debug
UART, USB, and other peripheral interfaces.
Add compatible strings for the CQ2390M, CQ2390S, IQ2390S SoM variant and
its corresponding EVK boards.
Signed-off-by: Komal Bajaj <komal.bajaj@oss.qualcomm.com>
---
Documentation/devicetree/bindings/arm/qcom.yaml | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index 50cc18a6ec5e..cf7d241f8107 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -989,6 +989,24 @@ properties:
- xiaomi,polaris
- const: qcom,sdm845
+ - items:
+ - enum:
+ - qcom,shikra-cqm-evk
+ - const: qcom,shikra-cqm-som
+ - const: qcom,shikra
+
+ - items:
+ - enum:
+ - qcom,shikra-cqs-evk
+ - const: qcom,shikra-cqs-som
+ - const: qcom,shikra
+
+ - items:
+ - enum:
+ - qcom,shikra-iqs-evk
+ - const: qcom,shikra-iqs-som
+ - const: qcom,shikra
+
- items:
- enum:
- oneplus,billie2
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v5 0/5] arm64: dts: qcom: Add initial device tree support for Shikra
From: Komal Bajaj @ 2026-06-11 10:10 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Neil Armstrong, Wesley Cheng,
Ulf Hansson
Cc: linux-arm-msm, devicetree, linux-kernel, linux-phy, linux-mmc,
monish.chunara, Komal Bajaj, Imran Shaik, Monish Chunara,
Rakesh Kota, Raviteja Laggyshetty, Sneh Mankad, Vishnu Santhosh,
Xueyao An, Konrad Dybcio
Add initial device tree support for the Qualcomm Shikra SoC.
Shikra ships in a SoM form factor; this series covers the CQ2390M,
CQ2390S and IQ2390S SoM variants and their EVK boards.
The series adds:
- dt-bindings for the Shikra SoC, CQ2390M/CQ2390S/IQ2390S EVK boards
- SoC base DTSI
- CQ2390M SoM DTSI with PM4125 and PM8005 PMIC regulator definitions
- IQ2390S SoM DTSI with PM8150 PMIC regulator definitions
- EVK DTS files enabling UART and eMMC on the carrier board
Note: USB support is intentionally dropped from this series. It will be
sent separately once the USB driver changes for Shikra are concluded.
Signed-off-by: Komal Bajaj <komal.bajaj@oss.qualcomm.com>
---
Changes in v5:
- Add qcom,rpmcc-qcm2290 fallback compatible to rpmcc node in shikra.dtsi
- Link to v4: https://lore.kernel.org/r/20260527-shikra-dt-v4-0-b5ca1fa0b392@oss.qualcomm.com
Changes in v4:
- Updated commit message for 1/5 and 3/5 (Krzysztof, Konrad)
- Incorporated Konrad's comment
- Collected Reviewed-By tags
- Link to v3: https://lore.kernel.org/r/20260522-shikra-dt-v3-0-80ffde8a3dc4@oss.qualcomm.com
Changes in v3:
- Drop USB nodes from this series; will be sent separately pending
conclusion of USB driver changes for Shikra
- Fix memory base (0xa0000000 -> 0x80000000) (sashiko-bot)
- Fix power-domain macro: QCM2290_VDDCX -> RPMPD_VDDCX for sdhc (sashiko-bot)
- Fix INTC GIC_PPI number from 8 to GIC_PPI 9 (sashiko-bot)
- Rename SoM variant CQ7790M to CQ2390M (Konrad)
- Add PMIC DTSI includes to CQ2390M and IQ2390S SoM
- Link to v2: https://lore.kernel.org/r/20260519-shikra-dt-v2-0-c01b90fb4395@oss.qualcomm.com
Changes in v2:
- Update SoM/EVK combination bindings (Krzysztof)
- Add per-CPU-type PMU nodes with PPI partitions for the heterogeneous
cluster (Cortex-A55 + Cortex-A78C) (Konrad)
- Use full product names CQ2390M/CQ2390S in commit messages (Krzysztof)
- Update RPM interconnect tags and power-domain to RPMPD for sdhc (sashiko-bot)
- Update to use MPM for ss_phy_irq instead of direct GIC for usb (sashiko-bot)
- Add IQ2390S SoM (PM8150 PMIC) and IQS EVK board support
- Link to v1: https://lore.kernel.org/r/20260512-shikra-dt-v1-0-716438330dd0@oss.qualcomm.com
---
Komal Bajaj (5):
dt-bindings: arm: qcom: Document Shikra and its EVK boards
arm64: dts: qcom: Introduce Shikra SoC base dtsi
arm64: dts: qcom: Add Shikra CQ2390M SoM platform
arm64: dts: qcom: Add Shikra IQ2390S SoM platform
arm64: dts: qcom: Add Shikra EVK boards
Documentation/devicetree/bindings/arm/qcom.yaml | 18 +
arch/arm64/boot/dts/qcom/Makefile | 3 +
arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 40 ++
arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 156 +++++
arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 40 ++
arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 15 +
arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 40 ++
arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi | 170 +++++
arch/arm64/boot/dts/qcom/shikra.dtsi | 842 ++++++++++++++++++++++++
9 files changed, 1324 insertions(+)
---
base-commit: abe651837cb394f76d738a7a747322fca3bf17ba
change-id: 20260511-shikra-dt-d75d97454646
prerequisite-change-id: 20260429-shikra-gcc-rpmcc-clks-2094edfff3b0:v5
prerequisite-patch-id: 59bb0a7828e41f546f734f127d81da83c0adcda9
prerequisite-patch-id: 197da6bcb15cadc47869dba88c8020987b25c335
prerequisite-patch-id: 8ec9c1eb03f052ae232ed54117abed38672c23f6
prerequisite-patch-id: 350db4f4bcdfc0fad9ed57cd5b1723f85ad44f5d
prerequisite-message-id: 20260508-shikra_mailbox_and_rpm_changes-v3-1-698f8e5fb339@oss.qualcomm.com
prerequisite-patch-id: e80ea7940b9817449cec21afa6e9e443e007166f
prerequisite-patch-id: 2526e0507d3b5c065eafd75a657d7f903af8488f
prerequisite-patch-id: c3b7e18cd60d1f779b88ace2fae1227d3d37d83e
prerequisite-message-id: 20260508-shikra_mailbox_and_rpm_changes-v3-2-698f8e5fb339@oss.qualcomm.com
prerequisite-patch-id: e80ea7940b9817449cec21afa6e9e443e007166f
prerequisite-patch-id: 2526e0507d3b5c065eafd75a657d7f903af8488f
prerequisite-patch-id: c3b7e18cd60d1f779b88ace2fae1227d3d37d83e
prerequisite-change-id: 20260430-shikra-imem-binding-a7bb9d2f16d2:v1
prerequisite-patch-id: 80d8ab865b7b0663c5b2878b45b55e2e4fde9c19
prerequisite-change-id: 20260501-shikra-scm-binding-a7ff5fabd0f2:v1
prerequisite-patch-id: 8e645e1c6ad6182de4813a726c293654324de1df
prerequisite-change-id: 20260501-shikra-tcsr-binding-fff1689e4097:v1
prerequisite-patch-id: f6781d2cf0829ccb32f1400623c95739972f2ee2
Best regards,
--
Komal Bajaj <komal.bajaj@oss.qualcomm.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 0/9] media/arm64: HM1092 IR camera and ASUS Zenbook A14 (X1P42100) camera support
From: Vladimir Zapolskiy @ 2026-06-11 10:01 UTC (permalink / raw)
To: Ramshouriesh, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Mauro Carvalho Chehab,
Bryan O'Donoghue, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy
In-Reply-To: <20260610-a14-himax-hm1092-v1-0-0c9907da47ed@gmail.com>
On 6/10/26 14:09, Ramshouriesh wrote:
> The ASUS Zenbook A14 (Qualcomm X1P42100, "Purwa") has two front cameras
> behind the SoC CAMSS: an OV02C10 RGB sensor and a Himax HM1092 mono NIR
> sensor used for face unlock. This series adds a driver for the HM1092 and
> the device tree to wire both sensors up on the A14.
>
> The HM1092 binding, driver and MAINTAINERS entry do not depend on the
> rest of the series and can go through the media tree on their own.
>
> The remaining DTS and PHY patches are the A14 camera enablement. They sit
> on top of several series that are not in mainline yet, listed below. With
> those applied the series builds on next-20260609: the A14 dtb and every
> module it touches (hm1092, qcom-camss including csiphy, and the
> qcom-mipi-csi2 phy) compile and work: both sensors probe and stream
> frames on the A14.
>
> Prerequisites, in the order they apply:
>
> 1. phy: dphy: Extend phy_configure_opts_mipi_dphy to support position
> and polarity (Bryan O'Donoghue, v1)
> https://lore.kernel.org/all/20260325-dphy-params-extension-v1-0-c6df5599284a@linaro.org/
> 2. clk: qcom: videocc and camcc for X1P42100 (Jagadeesh Kona, v5)
> https://lore.kernel.org/all/20260507-purwa-videocc-camcc-v5-0-fc3af4130282@oss.qualcomm.com/
> 3. phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver (Bryan O'Donoghue, v8)
> https://lore.kernel.org/all/20260523-x1e-csi2-phy-v8-0-a85668459521@linaro.org/
> 4. media: dt-bindings and PHY updates for CAMSS on x1e80100 (Bryan O'Donoghue, v11)
> https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-0-5b93415be6dd@linaro.org/
> 5. arm64: dts: qcom: x1e/Hamoa camera DTSI (Bryan O'Donoghue, v3)
> https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-0-1d5a9306116a@linaro.org/
> 6. media: qcom: camss: Add support for X1P42100 camss (Wenmeng Liu, v2)
> https://lore.kernel.org/all/20260511-purwa_camss-v2-0-22608ab9126c@oss.qualcomm.com/
That's a long list.
>
> From the videocc/camcc series only the CAMCC block (patch 6/6) is still
> needed; its clock drivers and bindings are already in linux-next. That
> patch adds the camcc node and sets the Purwa camcc and videocc compatibles.
>
> From the x1e/Hamoa camera DTSI series only the CCI and CAMSS-block patches
> are needed; its CAMCC block duplicates the videocc/camcc series, and the
> x1e80100 board patches do not apply to the A14.
>
> Patch 1 adds the OV02C10 node. It is Aleksandrs Vinarskis' work, carried
> here with his Signed-off-by so the A14 camera support stays one chain.
This patch should be removed from consideration, since it is not based on
the upstream codebase.
I'd suggest you to upstream the sensor driver only through linux-media, which
is patches 2/9 and 3/8, all other changes should go only after it.
--
Best wishes,
Vladimir
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 8/9] dt-bindings: phy: qcom: add MIPI CSI2 mode constants
From: Krzysztof Kozlowski @ 2026-06-11 9:15 UTC (permalink / raw)
To: Ramshouriesh
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong, Aleksandrs Vinarskis, linux-arm-msm,
devicetree, linux-kernel, linux-media, linux-phy
In-Reply-To: <20260610-a14-himax-hm1092-v1-8-0c9907da47ed@gmail.com>
On Wed, Jun 10, 2026 at 04:39:33PM +0530, Ramshouriesh wrote:
> The CSI2-PHY binding references <dt-bindings/phy/phy-qcom-mipi-csi2.h>
No, it does not reference it.
$ git grep phy-qcom-mipi-csi2.h
Zero results.
Best regards,
Krzysztof
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 3/9] media: i2c: hm1092: add Himax HM1092 mono NIR sensor driver
From: Krzysztof Kozlowski @ 2026-06-11 9:13 UTC (permalink / raw)
To: Ramshouriesh
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong, Aleksandrs Vinarskis, linux-arm-msm,
devicetree, linux-kernel, linux-media, linux-phy
In-Reply-To: <20260610-a14-himax-hm1092-v1-3-0c9907da47ed@gmail.com>
On Wed, Jun 10, 2026 at 04:39:28PM +0530, Ramshouriesh wrote:
> +module_i2c_driver(hm1092_i2c_driver);
> +
> +MODULE_DESCRIPTION("Himax HM1092 sensor driver draft");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/media/i2c/hm1092_regs.h b/drivers/media/i2c/hm1092_regs.h
> new file mode 100644
> index 000000000000..4df2d5b49d81
> --- /dev/null
> +++ b/drivers/media/i2c/hm1092_regs.h
> @@ -0,0 +1,223 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* HM1092 register tables extracted from Qualcomm Chromatix sensor module.
> + * Source: com.qti.sensormodule.hm1092.bin
> + * Generator: hm1092-re/gen_hm1092_regs.py
> + * DO NOT HAND EDIT — regenerate from the bin.
> + */
> +
> +struct hm1092_reg {
> + u16 address;
> + u8 val;
> +};
> +
> +static const struct hm1092_reg hm1092_init_regs[] = {
You must NOT define data in headers. This is not how C is written - you
invite data duplication without any gains/benefits.
Best regards,
Krzysztof
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 2/9] media: dt-bindings: Add Himax HM1092 NIR sensor
From: Krzysztof Kozlowski @ 2026-06-11 9:11 UTC (permalink / raw)
To: Ramshouriesh
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong, Aleksandrs Vinarskis, linux-arm-msm,
devicetree, linux-kernel, linux-media, linux-phy
In-Reply-To: <20260610-a14-himax-hm1092-v1-2-0c9907da47ed@gmail.com>
On Wed, Jun 10, 2026 at 04:39:27PM +0530, Ramshouriesh wrote:
> Add a dt-binding schema for the Himax HM1092 1MP monochrome
> near-infrared CMOS sensor, used as the face-authentication IR camera on
> Snapdragon X laptops such as the ASUS Zenbook A14. The sensor streams
> 10-bit RAW over 1 or 2 MIPI CSI-2 data lanes.
>
> The optional generic "leds" property (video-interface-devices.yaml)
> associates an IR illuminator flash LED with the sensor, which the
> driver strobes while streaming.
>
> Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
> ---
> .../bindings/media/i2c/himax,hm1092.yaml | 118 +++++++++++++++++++++
> 1 file changed, 118 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/media/i2c/himax,hm1092.yaml b/Documentation/devicetree/bindings/media/i2c/himax,hm1092.yaml
> new file mode 100644
> index 000000000000..085001493a20
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/i2c/himax,hm1092.yaml
> @@ -0,0 +1,118 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/i2c/himax,hm1092.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Himax HM1092 Monochrome NIR Sensor
> +
> +maintainers:
> + - Ramshouriesh <rshouriesh@gmail.com>
> +
> +description:
> + The Himax HM1092 is a 1 megapixel monochrome near-infrared CMOS image
> + sensor with a MIPI CSI-2 interface, commonly used as the IR camera for
> + face authentication on laptops. It supports 10 bit RAW output at
> + 1288x728 over 1 or 2 CSI-2 data lanes. An optional infrared
> + illuminator LED may be associated with the sensor through the generic
> + "leds" property; the driver strobes it while the sensor is streaming
> + so the scene stays lit for IR capture.
> +
> +allOf:
> + - $ref: /schemas/media/video-interface-devices.yaml#
> +
> +properties:
> + compatible:
> + const: himax,hm1092
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> +
> + avdd-supply:
> + description: Analogue circuit voltage supply.
> +
> + dovdd-supply:
> + description: I/O circuit voltage supply.
> +
> + dvdd-supply:
> + description: Digital circuit voltage supply.
> +
> + reset-gpios:
> + maxItems: 1
> + description: Active low GPIO connected to the XSHUTDOWN pad.
> +
> + leds:
Drop, unevaluatedPropertes already allows that.
> + description:
> + Optional phandle to an infrared illuminator flash LED strobed by
> + the driver while streaming.
> +
> + port:
> + $ref: /schemas/graph.yaml#/$defs/port-base
> + additionalProperties: false
> +
> + properties:
> + endpoint:
> + $ref: /schemas/media/video-interfaces.yaml#
> + additionalProperties: false
use unevaluatedProperties here
> +
> + properties:
> + data-lanes:
> + minItems: 1
> + maxItems: 2
> + link-frequencies: true
> + remote-endpoint: true
And drop these two
> +
> + required:
> + - data-lanes
> + - link-frequencies
> + - remote-endpoint
Why do you need this? Which other binding did you take as an
example/starting point?
> +
> +required:
> + - compatible
> + - reg
> + - clocks
Supplies are required
> + - port
> +
> +unevaluatedProperties: false
Best regards,
Krzysztof
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom,ipq8074-qmp-pcie: Document the ipq5210 QMP PCIe PHY
From: Krzysztof Kozlowski @ 2026-06-11 8:21 UTC (permalink / raw)
To: Varadarajan Narayanan
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-arm-msm, linux-phy, devicetree, linux-kernel
In-Reply-To: <20260610-pcie-phy-v3-1-334011b378d6@oss.qualcomm.com>
On Wed, Jun 10, 2026 at 04:46:08PM +0530, Varadarajan Narayanan wrote:
> Document the PCIe phys on the ipq5210 platform. The 2 lane phy uses the
> ipq9574 as fallback. The single lane phy is documented separately.
Drop
>
> The ipq5210 has one dual lane and one single lane PCIe phy.
>
> The dual lane phy is similar to the dual lane phy present in ipq9574. Hence
> qcom,ipq5210-qmp-gen3x2-pcie-phy is documented with ipq9574's dual lane phy
> as fallback compatible.
You are repeating the first paragraph.
>
> The single lane phy (qcom,ipq5210-qmp-gen3x1-pcie-phy) is documented as
> specific compatible.
Because? I asked last time - do not repeat the diff. You explain here
why it is not using fallback.
Best regards,
Krzysztof
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 6/9] arm64: dts/media: qcom: keep PLL8 out of Purwa camss hot path
From: Konrad Dybcio @ 2026-06-11 8:04 UTC (permalink / raw)
To: Ramshouriesh, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Mauro Carvalho Chehab,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Bryan O'Donoghue, Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy
In-Reply-To: <20260610-a14-himax-hm1092-v1-6-0c9907da47ed@gmail.com>
On 6/10/26 1:09 PM, Ramshouriesh wrote:
> cam_cc_pll8 (defined in camcc-x1e80100.c) doesn't latch on Purwa
> silicon. "Lucid PLL latch failed. Output may be unstable!" fires from
> wait_for_pll() whenever something asks for a PLL8-sourced rate, and
> the camera pipeline ends up dead with "Failed to start media
> pipeline: -32" even after the qcom,x1p42100-camss compatible is in
> place.
This patch is not right, seems like you're missing the hunk to override
the compatible for purwa, the tail end of:
https://lore.kernel.org/linux-arm-msm/20260507-purwa-videocc-camcc-v5-6-fc3af4130282@oss.qualcomm.com/
diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi
index 9ab4f26b35f298ad7c6c361b3e232edf07baf223..25cd547caab8fa64eb1a134068b77f5178f5c248 100644
--- a/arch/arm64/boot/dts/qcom/purwa.dtsi
+++ b/arch/arm64/boot/dts/qcom/purwa.dtsi
@@ -6,6 +6,8 @@
/* X1P42100 is heavily based on hamoa, with some meaningful differences */
#include "hamoa.dtsi"
+#include <dt-bindings/clock/qcom,x1p42100-videocc.h>
+
/delete-node/ &bwmon_cluster0;
/delete-node/ &cluster_pd2;
/delete-node/ &cpu_map_cluster2;
@@ -36,6 +38,10 @@
/delete-node/ &thermal_gpuss_6;
/delete-node/ &thermal_gpuss_7;
+&camcc {
+ compatible = "qcom,x1p42100-camcc";
+};
+
&gcc {
compatible = "qcom,x1p42100-gcc", "qcom,x1e80100-gcc";
};
Konrad
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* Re: [PATCH v2] dt-bindings: phy: sc8280xp-qmp-pcie: Disallow bifurcation register on Purwa
From: Rob Herring (Arm) @ 2026-06-10 20:00 UTC (permalink / raw)
To: Konrad Dybcio
Cc: linux-phy, Neil Armstrong, linux-arm-msm, Krzysztof Kozlowski,
Konrad Dybcio, Vinod Koul, YijieYang, Krzysztof Kozlowski,
Conor Dooley, devicetree, linux-kernel
In-Reply-To: <20260610-topic-purwa_phy_shutup_warning-v2-1-951c1fbfe9b2@oss.qualcomm.com>
On Wed, 10 Jun 2026 11:45:12 +0200, Konrad Dybcio wrote:
> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>
> Neither of the two Gen4x4 PHYs found on Purwa supports bifurcation.
> The PHY is however physically laid out as if it were to, since there
> are two separate ports (A/B).
>
> Split out a new if-then block to un-require the bifurcation register
> handle to squash this warning:
>
> purwa-iot-evk.dtb: phy@1bd4000 (qcom,x1p42100-qmp-gen4x4-pcie-phy): 'qcom,4ln-config-sel' is a required property
>
> Fixes: 2e1ffd4c1805 ("dt-bindings: phy: qcom,qmp-pcie: Add X1P42100 PCIe Gen4x4 PHY")
> Reported-by: Rob Herring <robh@kernel.org>
> Closes: https://lore.kernel.org/linux-arm-msm/176857775469.1631885.16133311938753588148.robh@kernel.org/
> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> ---
> Changes in v2:
> - Rebase
> - Don't drop the mention of the warning, as it now actually exists in
> the tree..
> - Link to v1: https://lore.kernel.org/r/20260119-topic-purwa_phy_shutup_warning-v1-1-997a692b31c6@oss.qualcomm.com
>
> To: Vinod Koul <vkoul@kernel.org>
> To: Neil Armstrong <neil.armstrong@linaro.org>
> To: Rob Herring <robh@kernel.org>
> To: Krzysztof Kozlowski <krzk+dt@kernel.org>
> To: Conor Dooley <conor+dt@kernel.org>
> To: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Cc: Krzysztof Kozlowski <krzk@kernel.org>
> Cc: linux-arm-msm@vger.kernel.org
> Cc: linux-phy@lists.infradead.org
> Cc: devicetree@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
> .../devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 13 +++++++++++--
> 1 file changed, 11 insertions(+), 2 deletions(-)
>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v1] phy: nxp-ptn3222: Use named initializers for struct i2c_device_id
From: Uwe Kleine-König (The Capable Hub) @ 2026-06-10 17:21 UTC (permalink / raw)
To: Vinod Koul; +Cc: Neil Armstrong, linux-phy, linux-kernel
In-Reply-To: <20260519151957.1593214-2-u.kleine-koenig@baylibre.com>
[-- Attachment #1.1: Type: text/plain, Size: 1485 bytes --]
Hello Vinod,
On Tue, May 19, 2026 at 05:19:57PM +0200, Uwe Kleine-König (The Capable Hub) wrote:
> While being less compact, using named initializers allows to more easily
> see which members of the structs are assigned which value without having
> to lookup the declaration of the struct. And it's also more robust
> against changes to the struct definition.
>
> This patch doesn't modify the compiled arrays, only their representation
> in source form benefits. The former was confirmed with x86 and arm64
> builds.
>
> Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
> ---
> Hello,
>
> this patch is part of a bigger quest to use named initializers for
> mainly struct i2c_device_id::driver_data to be able to modify
> i2c_device_id. See e.g.
> https://lore.kernel.org/all/20260518111203.639603-2-u.kleine-koenig@baylibre.com/
> for the details.
>
> This patch here isn't critical for this quest, as the driver doesn't
> make use of .driver_data, so apart from the better readability this is
> only about consistency with other subsystems.
Given that this patch isn't necessary for my onging patch quest, I don't
care much, but I still think this is an improvement so it would be sad
if this patch wasn't applied just because it's on nobody's radar any
more.
Do you consider to apply this patch? If you don't like it, that's fine,
but then please say so, then I drop it from my trackine.
Best regards
UWe
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
[-- Attachment #2: Type: text/plain, Size: 112 bytes --]
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: (subset) [PATCH v3 0/3] PCI: qcom: Add support for Eliza
From: Manivannan Sadhasivam @ 2026-06-10 16:34 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Lorenzo Pieralisi, Krzysztof Wilczyński,
Bjorn Helgaas, Bjorn Andersson, Krishna Chaitanya Chundru
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, linux-pci,
Krzysztof Kozlowski, Dmitry Baryshkov
In-Reply-To: <20260608-eliza-v3-0-9bdeb7434b28@oss.qualcomm.com>
On Mon, 08 Jun 2026 14:18:12 +0530, Krishna Chaitanya Chundru wrote:
> This series adds PCIe support for the Qualcomm Eliza SoC. Eliza includes
> two PCIe root complex controllers capable of 8GT/s x1 and 8GT/s x2.
>
> The QMP PCIe PHY support adds a new Gen3x1 PHY configuration with
> Eliza-specific initialization tables, and reuses the existing SM8550
> Gen3x2 configuration for the x2 PHY instance.
>
> [...]
Applied, thanks!
[2/3] dt-bindings: PCI: qcom,pcie-sm8550: Add Eliza compatible
commit: d233626c009a515fb3ed823fcd78cee432701d1e
Best regards,
--
Manivannan Sadhasivam <mani@kernel.org>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v5 phy-next 11/16] phy: lynx-28g: add support for big endian register maps
From: sashiko-bot @ 2026-06-10 16:33 UTC (permalink / raw)
To: Vladimir Oltean; +Cc: vkoul, neil.armstrong, linux-phy, olteanv
In-Reply-To: <20260610151952.2141019-12-vladimir.oltean@nxp.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Returning a void expression from a function with a void return type in `lynx_write` violates the C standard and kernel coding best practices, and can cause hard build failures on certain architectures.
--
commit 97dc5602d0955a0da9682236d3dfbc2339be7452
Author: Vladimir Oltean <vladimir.oltean@nxp.com>
phy: lynx-28g: add support for big endian register maps
This commit adds support for big-endian register maps in the Lynx 28G PHY
driver. It introduces endian-aware lynx_read() and lynx_write() helpers that
conditionally apply byte-swapping based on a device tree property.
> diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.h b/drivers/phy/freescale/phy-fsl-lynx-core.h
> --- a/drivers/phy/freescale/phy-fsl-lynx-core.h
> +++ b/drivers/phy/freescale/phy-fsl-lynx-core.h
[ ... ]
> +static inline void lynx_write(struct lynx_priv *priv, unsigned long off, u32 val)
> +{
> + void __iomem *reg = priv->base + off;
> +
> + if (priv->big_endian)
> + return iowrite32be(val, reg);
> +
> + return iowrite32(val, reg);
> +}
[Severity: Low]
Is it safe to use the return keyword for these void I/O accessors?
While the compiler might permit returning a void expression, it technically
violates the C standard. If iowrite32be() or iowrite32() are implemented as
non-expression macros (such as a do { ... } while(0) block) on certain
architectures, couldn't this expand into a syntax error and cause a build
regression?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610151952.2141019-1-vladimir.oltean@nxp.com?part=11
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v3 3/3] phy: qcom: qmp-pcie: Add QMP PCIe PHY support for Eliza
From: Manivannan Sadhasivam @ 2026-06-10 16:32 UTC (permalink / raw)
To: Krishna Chaitanya Chundru
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Lorenzo Pieralisi, Krzysztof Wilczyński,
Bjorn Helgaas, Bjorn Andersson, linux-arm-msm, linux-phy,
devicetree, linux-kernel, linux-pci, Dmitry Baryshkov
In-Reply-To: <20260608-eliza-v3-3-9bdeb7434b28@oss.qualcomm.com>
On Mon, Jun 08, 2026 at 02:18:15PM +0530, Krishna Chaitanya Chundru wrote:
> Add QMP PCIe PHY support for the Eliza SoC. Introduce a new Gen3x1 PHY
> configuration with Eliza-specific initialization tables, and reuse the
> existing sm8550 Gen3x2 configuration for the Gen3x2 PHY instance.
>
> Also add the missing QPHY_PCIE_V6_PCS_PCIE_INT_AUX_CLK_CONFIG1 register
> definition to the PCIe V6 PCS header.
>
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
- Mani
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 139 ++++++++++++++++++++++++
> drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h | 1 +
> 2 files changed, 140 insertions(+)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
> index fed2fc9bb311..257b4df965c3 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
> @@ -198,6 +198,112 @@ static const struct qmp_phy_init_tbl msm8998_pcie_pcs_tbl[] = {
> QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03),
> };
>
> +static const struct qmp_phy_init_tbl eliza_qmp_gen3x1_pcie_serdes_tbl[] = {
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x93),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x01),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x02),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x0a),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x1a),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x34),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0x55),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0x55),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x01),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x01),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE1_MODE1, 0xb4),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE2_MODE1, 0x03),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x02),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x04),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0d),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xaa),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x01),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE1_MODE0, 0x24),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x07),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x42),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0xa0),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
> + QMP_PHY_INIT_CFG(QSERDES_V6_COM_ADDITIONAL_MISC_3, 0x0f),
> +};
> +
> +static const struct qmp_phy_init_tbl eliza_qmp_gen3x1_pcie_pcs_tbl[] = {
> + QMP_PHY_INIT_CFG(QPHY_V6_PCS_REFGEN_REQ_CONFIG1, 0x05),
> + QMP_PHY_INIT_CFG(QPHY_V6_PCS_G3S2_PRE_GAIN, 0x2e),
> + QMP_PHY_INIT_CFG(QPHY_V6_PCS_RX_SIGDET_LVL, 0x77),
> + QMP_PHY_INIT_CFG(QPHY_V6_PCS_RATE_SLEW_CNTRL1, 0x0b),
> + QMP_PHY_INIT_CFG(QPHY_V6_PCS_PCS_TX_RX_CONFIG, 0x0c),
> + QMP_PHY_INIT_CFG(QPHY_V6_PCS_EQ_CONFIG2, 0x0f),
> +};
> +
> +static const struct qmp_phy_init_tbl eliza_qmp_gen3x1_pcie_misc_pcs_tbl[] = {
> + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG2, 0x1d),
> + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
> + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00),
> + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
> + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_RXEQEVAL_TIME, 0x27),
> +};
> +
> +static const struct qmp_phy_init_tbl eliza_qmp_gen3x1_pcie_tx_tbl[] = {
> + QMP_PHY_INIT_CFG(QSERDES_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x17),
> + QMP_PHY_INIT_CFG(QSERDES_V6_TX_RES_CODE_LANE_OFFSET_RX, 0x06),
> + QMP_PHY_INIT_CFG(QSERDES_V6_TX_LANE_MODE_1, 0x15),
> + QMP_PHY_INIT_CFG(QSERDES_V6_TX_LANE_MODE_4, 0x3f),
> + QMP_PHY_INIT_CFG(QSERDES_V6_TX_RCV_DETECT_LVL_2, 0x12),
> + QMP_PHY_INIT_CFG(QSERDES_V6_TX_PI_QEC_CTRL, 0x02),
> +};
> +
> +static const struct qmp_phy_init_tbl eliza_qmp_gen3x1_pcie_rx_tbl[] = {
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_FO_GAIN, 0x09),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SO_GAIN, 0x05),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_PI_CONTROLS, 0xf0),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH1, 0x08),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH2, 0x08),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_AUX_DATA_TCOARSE_TFINE, 0x30),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_TX_ADAPT_POST_THRESH, 0xf0),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_VGA_CAL_CNTRL1, 0x04),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_VGA_CAL_CNTRL2, 0x0f),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_GM_CAL, 0x0d),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_IDAC_TSETTLE_LOW, 0x07),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIDGET_ENABLES, 0x0c),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_LOW, 0x3f),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH, 0xbf),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH2, 0xbf),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH3, 0xb7),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH4, 0xea),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_LOW, 0xdc),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH, 0x5c),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH2, 0x9c),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH3, 0x1a),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH4, 0x89),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH, 0x94),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH2, 0x5b),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH3, 0x1a),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH4, 0x89),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
> + QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIGDET_CAL_TRIM, 0x08),
> +};
> +
> static const struct qmp_phy_init_tbl ipq6018_pcie_serdes_tbl[] = {
> QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d),
> QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01),
> @@ -3532,6 +3638,33 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v8_50 = {
> .txrxz = 0xd000,
> };
>
> +static const struct qmp_phy_cfg eliza_qmp_gen3x1_pciephy_cfg = {
> + .lanes = 1,
> +
> + .offsets = &qmp_pcie_offsets_v5,
> +
> + .tbls = {
> + .serdes = eliza_qmp_gen3x1_pcie_serdes_tbl,
> + .serdes_num = ARRAY_SIZE(eliza_qmp_gen3x1_pcie_serdes_tbl),
> + .tx = eliza_qmp_gen3x1_pcie_tx_tbl,
> + .tx_num = ARRAY_SIZE(eliza_qmp_gen3x1_pcie_tx_tbl),
> + .rx = eliza_qmp_gen3x1_pcie_rx_tbl,
> + .rx_num = ARRAY_SIZE(eliza_qmp_gen3x1_pcie_rx_tbl),
> + .pcs = eliza_qmp_gen3x1_pcie_pcs_tbl,
> + .pcs_num = ARRAY_SIZE(eliza_qmp_gen3x1_pcie_pcs_tbl),
> + .pcs_misc = eliza_qmp_gen3x1_pcie_misc_pcs_tbl,
> + .pcs_misc_num = ARRAY_SIZE(eliza_qmp_gen3x1_pcie_misc_pcs_tbl),
> + },
> + .reset_list = sdm845_pciephy_reset_l,
> + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
> + .vreg_list = qmp_phy_vreg_l,
> + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
> + .regs = pciephy_v6_regs_layout,
> +
> + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
> + .phy_status = PHYSTATUS,
> +};
> +
> static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
> .lanes = 1,
>
> @@ -5399,6 +5532,12 @@ static int qmp_pcie_probe(struct platform_device *pdev)
>
> static const struct of_device_id qmp_pcie_of_match_table[] = {
> {
> + .compatible = "qcom,eliza-qmp-gen3x1-pcie-phy",
> + .data = &eliza_qmp_gen3x1_pciephy_cfg,
> + }, {
> + .compatible = "qcom,eliza-qmp-gen3x2-pcie-phy",
> + .data = &sm8550_qmp_gen3x2_pciephy_cfg,
> + }, {
> .compatible = "qcom,glymur-qmp-gen4x2-pcie-phy",
> .data = &glymur_qmp_gen4x2_pciephy_cfg,
> }, {
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h
> index 45397cb3c0c6..17a0f9d18acf 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h
> @@ -12,6 +12,7 @@
> #define QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG2 0x0c
> #define QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG4 0x14
> #define QPHY_PCIE_V6_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x20
> +#define QPHY_PCIE_V6_PCS_PCIE_INT_AUX_CLK_CONFIG1 0x54
> #define QPHY_PCIE_V6_PCS_PCIE_OSC_DTCT_ACTIONS 0x94
>
> #define QPHY_PCIE_V6_PCS_LANE1_INSIG_SW_CTRL2 0x024
>
> --
> 2.34.1
>
--
மணிவண்ணன் சதாசிவம்
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v3 1/3] dt-bindings: phy: sc8280xp-qmp-pcie: Document Eliza PCIe phy
From: Manivannan Sadhasivam @ 2026-06-10 16:31 UTC (permalink / raw)
To: Krishna Chaitanya Chundru
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Lorenzo Pieralisi, Krzysztof Wilczyński,
Bjorn Helgaas, Bjorn Andersson, linux-arm-msm, linux-phy,
devicetree, linux-kernel, linux-pci, Krzysztof Kozlowski
In-Reply-To: <20260608-eliza-v3-1-9bdeb7434b28@oss.qualcomm.com>
On Mon, Jun 08, 2026 at 02:18:13PM +0530, Krishna Chaitanya Chundru wrote:
> Add compatibles for the Eliza PCIe QMP PHY's, which supports Gen3x1 and
> Gen3x2 configurations.
>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
- Mani
> ---
> .../devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
> index 3a35120a77ec..be4bbc327982 100644
> --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
> +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
> @@ -16,6 +16,8 @@ description:
> properties:
> compatible:
> enum:
> + - qcom,eliza-qmp-gen3x1-pcie-phy
> + - qcom,eliza-qmp-gen3x2-pcie-phy
> - qcom,glymur-qmp-gen4x2-pcie-phy
> - qcom,glymur-qmp-gen5x4-pcie-phy
> - qcom,kaanapali-qmp-gen3x2-pcie-phy
> @@ -181,6 +183,8 @@ allOf:
> compatible:
> contains:
> enum:
> + - qcom,eliza-qmp-gen3x1-pcie-phy
> + - qcom,eliza-qmp-gen3x2-pcie-phy
> - qcom,glymur-qmp-gen4x2-pcie-phy
> - qcom,glymur-qmp-gen5x4-pcie-phy
> - qcom,qcs8300-qmp-gen4x2-pcie-phy
> @@ -206,6 +210,8 @@ allOf:
> compatible:
> contains:
> enum:
> + - qcom,eliza-qmp-gen3x1-pcie-phy
> + - qcom,eliza-qmp-gen3x2-pcie-phy
> - qcom,glymur-qmp-gen4x2-pcie-phy
> - qcom,glymur-qmp-gen5x4-pcie-phy
> - qcom,kaanapali-qmp-gen3x2-pcie-phy
>
> --
> 2.34.1
>
--
மணிவண்ணன் சதாசிவம்
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v5 phy-next 03/16] phy: lynx-28g: move lane mode helpers to new core module
From: sashiko-bot @ 2026-06-10 15:44 UTC (permalink / raw)
To: Vladimir Oltean; +Cc: neil.armstrong, vkoul, olteanv, linux-phy
In-Reply-To: <20260610151952.2141019-4-vladimir.oltean@nxp.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] The enum constants for `lynx_lane_mode` lack a subsystem or driver prefix, polluting the global namespace.
- [Low] The newly exported function `phy_interface_to_lane_mode` lacks a driver-specific prefix.
--
commit fb931a9e09ebe42d6f769c59cd1a8698e01312c9
Author: Vladimir Oltean <vladimir.oltean@nxp.com>
phy: lynx-28g: move lane mode helpers to new core module
This commit introduces a new core module for the Lynx SerDes PHY to share
code between the 28G and upcoming 10G drivers. It moves the lane mode
definitions to a public header and exports helper functions.
> diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.c b/drivers/phy/freescale/phy-fsl-lynx-core.c
> new file mode 100644
> index 0000000000000..d56f189c162dc
> --- /dev/null
> +++ b/drivers/phy/freescale/phy-fsl-lynx-core.c
[ ... ]
> +enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf)
> +{
> + switch (intf) {
[Severity: Low]
Does this function name need a driver-specific prefix now that it is exported?
Previously, phy_interface_to_lane_mode() was a static function, but since it
is now exported with a generic name, could this cause linker collisions if
another driver implements a function with the same name?
> + case PHY_INTERFACE_MODE_SGMII:
> + case PHY_INTERFACE_MODE_1000BASEX:
> + return LANE_MODE_1000BASEX_SGMII;
[ ... ]
> diff --git a/include/soc/fsl/phy-fsl-lynx.h b/include/soc/fsl/phy-fsl-lynx.h
> new file mode 100644
> index 0000000000000..92e8272d5ae15
> --- /dev/null
> +++ b/include/soc/fsl/phy-fsl-lynx.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/* Copyright 2023-2026 NXP */
> +
> +#ifndef __PHY_FSL_LYNX_H_
> +#define __PHY_FSL_LYNX_H_
> +
> +enum lynx_lane_mode {
> + LANE_MODE_UNKNOWN,
> + LANE_MODE_1000BASEX_SGMII,
[Severity: Low]
Would it be safer to add a prefix to these enum constants (like LYNX_ or
FSL_LYNX_) since they are now exposed in a global header?
Generic names like LANE_MODE_UNKNOWN and LANE_MODE_MAX might conflict with
other definitions in the global namespace.
> + LANE_MODE_10GBASER,
> + LANE_MODE_USXGMII,
> + LANE_MODE_25GBASER,
> + LANE_MODE_MAX,
> +};
> +
> +#endif /* __PHY_FSL_LYNX_H_ */
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610151952.2141019-1-vladimir.oltean@nxp.com?part=3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v5 phy-next 02/16] phy: lynx-28g: reject probing on devices with unsupported OF nodes
From: sashiko-bot @ 2026-06-10 15:38 UTC (permalink / raw)
To: Vladimir Oltean; +Cc: vkoul, neil.armstrong, olteanv, linux-phy
In-Reply-To: <20260610151952.2141019-3-vladimir.oltean@nxp.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Missing check for the return value of `of_device_get_match_data()` in `imx8_pcie_phy_probe` and `imx_hsio_probe` leads to NULL pointer dereference.
--
commit 11cd1431079ad06a01704502129a0983e1f3e992
Author: Vladimir Oltean <vladimir.oltean@nxp.com>
phy: lynx-28g: reject probing on devices with unsupported OF nodes
This commit fixes a potential NULL pointer dereference in the lynx-28g
driver when bound to arbitrary devices via driver_override. It adds a
check to ensure of_device_get_match_data() does not return NULL before
dereferencing the match data.
> diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c
> index cacc128dc96a1..1f5cb02931f56 100644
> --- a/drivers/phy/freescale/phy-fsl-lynx-28g.c
> +++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c
> @@ -1477,6 +1477,9 @@ static int lynx_28g_probe(struct platform_device *pdev)
>
> priv->dev = dev;
> priv->info = of_device_get_match_data(dev);
> + if (!priv->info)
> + return -ENODEV;
> +
> dev_set_drvdata(dev, priv);
[Severity: High]
This isn't a bug introduced by this patch, but it appears the exact same
missing check exists in other drivers within the same subsystem.
Do we need to add similar NULL checks for of_device_get_match_data() in
imx8_pcie_phy_probe() to avoid a crash?
drivers/phy/freescale/phy-fsl-imx8m-pcie.c:imx8_pcie_phy_probe() {
...
imx8_phy->drvdata = of_device_get_match_data(dev);
...
imx8_phy->iomuxc_gpr =
syscon_regmap_lookup_by_compatible(imx8_phy->drvdata->gpr);
...
}
And also in imx_hsio_probe() where it accesses the lane_num field?
drivers/phy/freescale/phy-fsl-imx8qm-hsio.c:imx_hsio_probe() {
...
priv->drvdata = of_device_get_match_data(dev);
...
for (i = 0; i < priv->drvdata->lane_num; i++) {
...
}
Without a check, could these drivers similarly crash with a NULL pointer
dereference when bound to a device with a different compatible string via
the driver_override interface?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610151952.2141019-1-vladimir.oltean@nxp.com?part=2
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH v5 phy-next 16/16] MAINTAINERS: expand Lynx 28G entry to cover Lynx 10G SerDes
From: Vladimir Oltean @ 2026-06-10 15:19 UTC (permalink / raw)
To: linux-phy
Cc: Ioana Ciornei, Vinod Koul, Neil Armstrong, Tanjeff Moos,
linux-kernel, devicetree, Conor Dooley, Krzysztof Kozlowski,
Rob Herring
In-Reply-To: <20260610151952.2141019-1-vladimir.oltean@nxp.com>
The lynx-28g and lynx-10g drivers share code and hardware architecture,
so let them be covered by a single MAINTAINERS entry.
Add myself as a second maintainer alongside Ioana Ciornei.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
Cc: devicetree@vger.kernel.org
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Rob Herring <robh@kernel.org>
v1->v5: none
---
MAINTAINERS | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index a727d4920fae..ecc2f4a0baed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15415,12 +15415,18 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/light/liteon,ltr390.yaml
F: drivers/iio/light/ltr390.c
-LYNX 28G SERDES PHY DRIVER
+LYNX SERDES PHY DRIVERS
M: Ioana Ciornei <ioana.ciornei@nxp.com>
+M: Vladimir Oltean <vladimir.oltean@nxp.com>
L: netdev@vger.kernel.org
S: Supported
+F: Documentation/devicetree/bindings/phy/fsl,lynx-10g.yaml
F: Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml
+F: drivers/phy/freescale/phy-fsl-lynx-10g.c
F: drivers/phy/freescale/phy-fsl-lynx-28g.c
+F: drivers/phy/freescale/phy-fsl-lynx-core.c
+F: drivers/phy/freescale/phy-fsl-lynx-core.h
+F: include/soc/fsl/phy-fsl-lynx.h
LYNX PCS MODULE
M: Ioana Ciornei <ioana.ciornei@nxp.com>
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v5 phy-next 15/16] phy: lynx-10g: new driver
From: Vladimir Oltean @ 2026-06-10 15:19 UTC (permalink / raw)
To: linux-phy
Cc: Ioana Ciornei, Vinod Koul, Neil Armstrong, Tanjeff Moos,
linux-kernel, devicetree, Conor Dooley, Krzysztof Kozlowski,
Rob Herring, linux-arm-kernel, chleroy, linuxppc-dev
In-Reply-To: <20260610151952.2141019-1-vladimir.oltean@nxp.com>
Introduce a driver for the networking lanes of the 10G Lynx SerDes
block, present on the majority of Layerscape and QorIQ (Freescale/NXP)
SoCs.
As with the 28G Lynx, the SerDes lanes come pre-initialized out of
reset and the consumers use them that way outside the Generic PHY
framework (for networking, the static configuration remains for the
entire SoC lifetime, whereas for SATA and PCIe, the hardware
reconfigures itself automatically for other link speeds).
The need for the Generic PHY framework comes specifically for networking
use cases where a static lane configuration is not sufficient. For
example a network MAC is connected to an SFP cage, where various SFP or
SFP+ modules can be connected. Each of them may require a different
SerDes protocol (SGMII, 1000Base-X, 10GBase-R), which phylink + sfp-bus
are responsible of figuring out. The phylink drivers are:
- enetc
- felix
- dpaa_eth (fman_memac)
- dpaa2-eth
- dpaa2-switch
and they all need to reconfigure the SerDes for the requested link mode,
using phy_set_mode_ext() (and phy_validate() to see if it is supported
in the first place).
Note that SerDes 2 on LS1088A is exclusively non-networking, so there is
currently no need for this driver. Therefore we skip matching on its
compatible string and do not probe on that device.
Co-developed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
Cc: devicetree@vger.kernel.org
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: chleroy@kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
v4->v5:
- add comments around default_pccr so that Sashiko understands what is
the idea and why the code is correct (and the assumptions being made)
- replace testing of the non-zero quality of lane->default_pccr[mode]
with the lynx_10g_pccr_val_enabled() helper which ignores the KX bit.
A lane starting with PCCR8_SGMIIa_KX=1 and PCCR8_SGMIIa_CFG=0 is
disabled, not enabled (although this is unusual and never a hardware
reset value).
- express PCCR8_SGMIIa_CFG(), PCCR9_QSGMIIa_CFG(), PCCR9_QXGMIIa_CFG(),
PCCRB_XFIa_CFG(), PCCRB_SXGMIIa_CFG() using GENMASK(2, 0) to make it
clear that the field width is not 1
v3->v4:
- none
v2->v3:
- fix lynx_10g_power_on() procedure
- include <linux/of.h> instead of <linux/of_device.h>
- fix build warning introduced in v2 in lynx_10g_lane_set_nrate()
v1->v2:
- move lynx_lane_restrict_fixed_mode_change() to lynx-core, even though
the 28G Lynx as instantiated in LX2 does not have QSGMII.
- lynx_10g_validate() now calls the new lynx_phy_mode_to_lane_mode()
which does verify that the current lane mode is supported
- avoid line size checkpatch warnings in lynx_10g_lane_set_nrate() by
saving the nrate to a variable and calling lynx_lane_rmw() only once
- remove redundant "if (!lane->powered_up)" checks from
lynx_10g_lane_halt() and lynx_10g_lane_reset() - also checked at
the only call site, lynx_10g_set_mode(), as in lynx-28g
- expand CC list (flagged by Patchwork)
---
drivers/phy/freescale/Kconfig | 10 +
drivers/phy/freescale/Makefile | 1 +
drivers/phy/freescale/phy-fsl-lynx-10g.c | 1321 +++++++++++++++++++++
drivers/phy/freescale/phy-fsl-lynx-core.c | 38 +
drivers/phy/freescale/phy-fsl-lynx-core.h | 4 +
include/soc/fsl/phy-fsl-lynx.h | 27 +
6 files changed, 1401 insertions(+)
create mode 100644 drivers/phy/freescale/phy-fsl-lynx-10g.c
diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
index ac575d531db7..5bf3864fbe64 100644
--- a/drivers/phy/freescale/Kconfig
+++ b/drivers/phy/freescale/Kconfig
@@ -54,6 +54,16 @@ endif
config PHY_FSL_LYNX_CORE
tristate
+config PHY_FSL_LYNX_10G
+ tristate "Freescale Layerscape Lynx 10G SerDes PHY support"
+ depends on OF
+ depends on ARCH_LAYERSCAPE || COMPILE_TEST
+ select GENERIC_PHY
+ select PHY_FSL_LYNX_CORE
+ help
+ Enable this to add support for the Lynx 10G SerDes PHY as found on
+ NXP's Layerscape platform such as LS1088A or LS1028A.
+
config PHY_FSL_LYNX_28G
tristate "Freescale Layerscape Lynx 28G SerDes PHY support"
depends on OF
diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
index d7aa62cdeb39..5b0e180d6972 100644
--- a/drivers/phy/freescale/Makefile
+++ b/drivers/phy/freescale/Makefile
@@ -5,5 +5,6 @@ obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o
obj-$(CONFIG_PHY_FSL_IMX8M_PCIE) += phy-fsl-imx8m-pcie.o
obj-$(CONFIG_PHY_FSL_IMX8QM_HSIO) += phy-fsl-imx8qm-hsio.o
obj-$(CONFIG_PHY_FSL_LYNX_CORE) += phy-fsl-lynx-core.o
+obj-$(CONFIG_PHY_FSL_LYNX_10G) += phy-fsl-lynx-10g.o
obj-$(CONFIG_PHY_FSL_LYNX_28G) += phy-fsl-lynx-28g.o
obj-$(CONFIG_PHY_FSL_SAMSUNG_HDMI_PHY) += phy-fsl-samsung-hdmi.o
diff --git a/drivers/phy/freescale/phy-fsl-lynx-10g.c b/drivers/phy/freescale/phy-fsl-lynx-10g.c
new file mode 100644
index 000000000000..38def160ef1a
--- /dev/null
+++ b/drivers/phy/freescale/phy-fsl-lynx-10g.c
@@ -0,0 +1,1321 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2021-2026 NXP */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+
+#include "phy-fsl-lynx-core.h"
+
+/* SoC IP wrapper for protocol converters */
+#define PCCR8 0x220
+#define PCCR8_SGMIIa_KX BIT(3)
+#define PCCR8_SGMIIa_CFG GENMASK(2, 0)
+
+#define PCCR9 0x224
+#define PCCR9_QSGMIIa_CFG GENMASK(2, 0)
+#define PCCR9_QXGMIIa_CFG GENMASK(2, 0)
+
+#define PCCRB 0x22c
+#define PCCRB_XFIa_CFG GENMASK(2, 0)
+#define PCCRB_SXGMIIa_CFG GENMASK(2, 0)
+
+#define SGMII_CFG(id) (28 - (id) * 4)
+#define QSGMII_CFG(id) (28 - (id) * 4)
+#define SXGMII_CFG(id) (28 - (id) * 4)
+#define QXGMII_CFG(id) (12 - (id) * 4)
+#define XFI_CFG(id) (28 - (id) * 4)
+
+#define CR(x) ((x) * 4)
+
+#define A 0
+#define B 1
+#define C 2
+#define D 3
+#define E 4
+#define F 5
+#define G 6
+#define H 7
+
+#define SGMIIaCR0(id) (0x1800 + (id) * 0x10)
+#define QSGMIIaCR0(id) (0x1880 + (id) * 0x10)
+#define XAUIaCR0(id) (0x1900 + (id) * 0x10)
+#define XFIaCR0(id) (0x1980 + (id) * 0x10)
+#define SXGMIIaCR0(id) (0x1a80 + (id) * 0x10)
+#define QXGMIIaCR0(id) (0x1b00 + (id) * 0x20)
+
+#define SGMIIaCR0_RST_SGM BIT(31)
+#define SGMIIaCR0_RST_SGM_OFF SGMIIaCR0_RST_SGM
+#define SGMIIaCR0_RST_SGM_ON 0
+#define SGMIIaCR0_PD_SGM BIT(30)
+#define SGMIIaCR1_SGPCS_EN BIT(11)
+#define SGMIIaCR1_SGPCS_DIS 0x0
+
+#define QSGMIIaCR0_RST_QSGM BIT(31)
+#define QSGMIIaCR0_RST_QSGM_OFF QSGMIIaCR0_RST_QSGM
+#define QSGMIIaCR0_RST_QSGM_ON 0
+#define QSGMIIaCR0_PD_QSGM BIT(30)
+
+/* Per PLL registers */
+#define PLLnCR0(pll) ((pll) * 0x20 + 0x4)
+
+#define PLLnCR0_POFF BIT(31)
+
+#define PLLnCR0_REFCLK_SEL GENMASK(30, 28)
+#define PLLnCR0_REFCLK_SEL_100MHZ 0x0
+#define PLLnCR0_REFCLK_SEL_125MHZ 0x1
+#define PLLnCR0_REFCLK_SEL_156MHZ 0x2
+#define PLLnCR0_REFCLK_SEL_150MHZ 0x3
+#define PLLnCR0_REFCLK_SEL_161MHZ 0x4
+#define PLLnCR0_PLL_LCK BIT(23)
+#define PLLnCR0_FRATE_SEL GENMASK(19, 16)
+#define PLLnCR0_FRATE_5G 0x0
+#define PLLnCR0_FRATE_5_15625G 0x6
+#define PLLnCR0_FRATE_4G 0x7
+#define PLLnCR0_FRATE_3_125G 0x9
+#define PLLnCR0_FRATE_3G 0xa
+
+/* Per SerDes lane registers */
+
+/* Lane a Protocol Select status register */
+#define LNaPSSR0(lane) (0x100 + (lane) * 0x20)
+#define LNaPSSR0_TYPE GENMASK(30, 26)
+#define LNaPSSR0_IS_QUAD GENMASK(25, 24)
+#define LNaPSSR0_MAC GENMASK(19, 16)
+#define LNaPSSR0_PCS GENMASK(10, 8)
+#define LNaPSSR0_LANE GENMASK(2, 0)
+
+/* Lane a General Control Register */
+#define LNaGCR0(lane) (0x800 + (lane) * 0x40 + 0x0)
+#define LNaGCR0_RPLL_PLLF BIT(31)
+#define LNaGCR0_RPLL_PLLS 0x0
+#define LNaGCR0_RPLL_MSK BIT(31)
+#define LNaGCR0_RRAT_SEL GENMASK(29, 28)
+#define LNaGCR0_TRAT_SEL GENMASK(25, 24)
+#define LNaGCR0_TPLL_PLLF BIT(27)
+#define LNaGCR0_TPLL_PLLS 0x0
+#define LNaGCR0_TPLL_MSK BIT(27)
+#define LNaGCR0_RRST_OFF LNaGCR0_RRST
+#define LNaGCR0_TRST_OFF LNaGCR0_TRST
+#define LNaGCR0_RRST_ON 0x0
+#define LNaGCR0_TRST_ON 0x0
+#define LNaGCR0_RRST BIT(22)
+#define LNaGCR0_TRST BIT(21)
+#define LNaGCR0_RX_PD BIT(20)
+#define LNaGCR0_TX_PD BIT(19)
+#define LNaGCR0_IF20BIT_EN BIT(18)
+#define LNaGCR0_PROTS GENMASK(11, 7)
+
+#define LNaGCR1(lane) (0x800 + (lane) * 0x40 + 0x4)
+#define LNaGCR1_RDAT_INV BIT(31)
+#define LNaGCR1_TDAT_INV BIT(30)
+#define LNaGCR1_OPAD_CTL BIT(26)
+#define LNaGCR1_REIDL_TH GENMASK(22, 20)
+#define LNaGCR1_REIDL_EX_SEL GENMASK(19, 18)
+#define LNaGCR1_REIDL_ET_SEL GENMASK(17, 16)
+#define LNaGCR1_REIDL_EX_MSB BIT(15)
+#define LNaGCR1_REIDL_ET_MSB BIT(14)
+#define LNaGCR1_REQ_CTL_SNP BIT(13)
+#define LNaGCR1_REQ_CDR_SNP BIT(12)
+#define LNaGCR1_TRSTDIR BIT(7)
+#define LNaGCR1_REQ_BIN_SNP BIT(6)
+#define LNaGCR1_ISLEW_RCTL GENMASK(5, 4)
+#define LNaGCR1_OSLEW_RCTL GENMASK(1, 0)
+
+#define LNaRECR0(lane) (0x800 + (lane) * 0x40 + 0x10)
+#define LNaRECR0_RXEQ_BST BIT(28)
+#define LNaRECR0_GK2OVD GENMASK(27, 24)
+#define LNaRECR0_GK3OVD GENMASK(19, 16)
+#define LNaRECR0_GK2OVD_EN BIT(15)
+#define LNaRECR0_GK3OVD_EN BIT(14)
+#define LNaRECR0_OSETOVD_EN BIT(13)
+#define LNaRECR0_BASE_WAND GENMASK(11, 10)
+#define LNaRECR0_OSETOVD GENMASK(6, 0)
+
+#define LNaTECR0(lane) (0x800 + (lane) * 0x40 + 0x18)
+#define LNaTECR0_TEQ_TYPE GENMASK(29, 28)
+#define LNaTECR0_SGN_PREQ BIT(26)
+#define LNaTECR0_RATIO_PREQ GENMASK(25, 22)
+#define LNaTECR0_SGN_POST1Q BIT(21)
+#define LNaTECR0_RATIO_PST1Q GENMASK(20, 16)
+#define LNaTECR0_ADPT_EQ GENMASK(13, 8)
+#define LNaTECR0_AMP_RED GENMASK(5, 0)
+
+#define LNaTTLCR0(lane) (0x800 + (lane) * 0x40 + 0x20)
+#define LNaTTLCR1(lane) (0x800 + (lane) * 0x40 + 0x24)
+#define LNaTTLCR2(lane) (0x800 + (lane) * 0x40 + 0x28)
+
+#define LNaTCSR3(lane) (0x800 + (lane) * 0x40 + 0x3C)
+#define LNaTCSR3_CDR_LCK BIT(27)
+
+enum lynx_10g_rat_sel {
+ RAT_SEL_FULL = 0x0,
+ RAT_SEL_HALF = 0x1,
+ RAT_SEL_QUARTER = 0x2,
+ RAT_SEL_DOUBLE = 0x3,
+};
+
+enum lynx_10g_eq_type {
+ EQ_TYPE_NO_EQ = 0,
+ EQ_TYPE_2TAP = 1,
+ EQ_TYPE_3TAP = 2,
+};
+
+enum lynx_10g_proto_sel {
+ PROTO_SEL_PCIE = 0,
+ PROTO_SEL_SGMII_BASEX_KX_QSGMII = 1,
+ PROTO_SEL_SATA = 2,
+ PROTO_SEL_XAUI = 4,
+ PROTO_SEL_XFI_10GBASER_KR_SXGMII = 0xa,
+};
+
+struct lynx_10g_proto_conf {
+ int proto_sel;
+ int if20bit_en;
+ int reidl_th;
+ int reidl_et_msb;
+ int reidl_et_sel;
+ int reidl_ex_msb;
+ int reidl_ex_sel;
+ int islew_rctl;
+ int oslew_rctl;
+ int rxeq_bst;
+ int gk2ovd;
+ int gk3ovd;
+ int gk2ovd_en;
+ int gk3ovd_en;
+ int base_wand;
+ int teq_type;
+ int sgn_preq;
+ int ratio_preq;
+ int sgn_post1q;
+ int ratio_post1q;
+ int adpt_eq;
+ int amp_red;
+ int ttlcr0;
+};
+
+static const struct lynx_10g_proto_conf lynx_10g_proto_conf[LANE_MODE_MAX] = {
+ [LANE_MODE_1000BASEX_SGMII] = {
+ .proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
+ .reidl_th = 1,
+ .reidl_ex_sel = 3,
+ .reidl_et_msb = 1,
+ .islew_rctl = 1,
+ .oslew_rctl = 1,
+ .gk2ovd = 15,
+ .gk3ovd = 15,
+ .gk2ovd_en = 1,
+ .gk3ovd_en = 1,
+ .teq_type = EQ_TYPE_NO_EQ,
+ .adpt_eq = 48,
+ .amp_red = 6,
+ .ttlcr0 = 0x39000400,
+ },
+ [LANE_MODE_2500BASEX] = {
+ .proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
+ .islew_rctl = 2,
+ .oslew_rctl = 2,
+ .teq_type = EQ_TYPE_2TAP,
+ .sgn_post1q = 1,
+ .ratio_post1q = 6,
+ .adpt_eq = 48,
+ .ttlcr0 = 0x00000400,
+ },
+ [LANE_MODE_QSGMII] = {
+ .proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
+ .islew_rctl = 1,
+ .oslew_rctl = 1,
+ .teq_type = EQ_TYPE_2TAP,
+ .sgn_post1q = 1,
+ .ratio_post1q = 6,
+ .adpt_eq = 48,
+ .amp_red = 2,
+ .ttlcr0 = 0x00000400,
+ },
+ [LANE_MODE_10G_QXGMII] = {
+ .proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
+ .if20bit_en = 1,
+ .islew_rctl = 1,
+ .oslew_rctl = 1,
+ .base_wand = 1,
+ .teq_type = EQ_TYPE_NO_EQ,
+ .adpt_eq = 48,
+ .ttlcr0 = 0x00000400,
+ },
+ [LANE_MODE_USXGMII] = {
+ .proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
+ .if20bit_en = 1,
+ .islew_rctl = 1,
+ .oslew_rctl = 1,
+ .base_wand = 1,
+ .teq_type = EQ_TYPE_NO_EQ,
+ .sgn_post1q = 1,
+ .adpt_eq = 48,
+ .ttlcr0 = 0x00000400,
+ },
+ [LANE_MODE_10GBASER] = {
+ .proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
+ .if20bit_en = 1,
+ .islew_rctl = 2,
+ .oslew_rctl = 2,
+ .rxeq_bst = 1,
+ .base_wand = 1,
+ .teq_type = EQ_TYPE_2TAP,
+ .sgn_post1q = 1,
+ .ratio_post1q = 3,
+ .adpt_eq = 48,
+ .amp_red = 7,
+ .ttlcr0 = 0x00000400,
+ },
+};
+
+static void lynx_10g_cdr_lock_check(struct lynx_lane *lane)
+{
+ u32 tcsr3 = lynx_lane_read(lane, LNaTCSR3);
+
+ if (tcsr3 & LNaTCSR3_CDR_LCK)
+ return;
+
+ dev_dbg(&lane->phy->dev,
+ "Lane %c CDR unlocked, resetting receiver...\n",
+ 'A' + lane->id);
+
+ lynx_lane_rmw(lane, LNaGCR0, LNaGCR0_RRST_ON, LNaGCR0_RRST);
+ usleep_range(1, 2);
+ lynx_lane_rmw(lane, LNaGCR0, LNaGCR0_RRST_OFF, LNaGCR0_RRST);
+
+ usleep_range(1, 2);
+}
+
+static void lynx_10g_pll_read_configuration(struct lynx_pll *pll)
+{
+ u32 val;
+
+ val = lynx_pll_read(pll, PLLnCR0);
+ pll->frate_sel = FIELD_GET(PLLnCR0_FRATE_SEL, val);
+ pll->refclk_sel = FIELD_GET(PLLnCR0_REFCLK_SEL, val);
+ pll->enabled = !(val & PLLnCR0_POFF);
+ pll->locked = !!(val & PLLnCR0_PLL_LCK);
+
+ if (!pll->enabled)
+ return;
+
+ switch (pll->frate_sel) {
+ case PLLnCR0_FRATE_5G:
+ /* 5GHz clock net */
+ __set_bit(LANE_MODE_1000BASEX_SGMII, pll->supported);
+ __set_bit(LANE_MODE_QSGMII, pll->supported);
+ break;
+ case PLLnCR0_FRATE_3_125G:
+ __set_bit(LANE_MODE_2500BASEX, pll->supported);
+ break;
+ case PLLnCR0_FRATE_5_15625G:
+ /* 10.3125GHz clock net */
+ __set_bit(LANE_MODE_10GBASER, pll->supported);
+ __set_bit(LANE_MODE_USXGMII, pll->supported);
+ __set_bit(LANE_MODE_10G_QXGMII, pll->supported);
+ break;
+ default:
+ break;
+ }
+}
+
+/* On LS1028A, SGMIIA_CFG, SGMIIB_CFG, and SGMIIC_CFG from PCCR8 have the
+ * ability to map either an ENETC PCS (PCCR8_SGMIIa_CFG=2) or a Felix switch
+ * PCS (PCCR8_SGMIIa_CFG=1) to the same lane.
+ *
+ * On LS1088A, the same QSGMII PCS B can be connected to SerDes lane 1
+ * (PCCR9_QSGMIIa_CFG=1) or to lane 3 (PCCR9_QSGMIIa_CFG=2).
+ *
+ * The PHY API lacks the capability to distinguish anything about the consumer,
+ * so we don't support changing the initial muxing done by the RCW.
+ *
+ * However, after disabling a PCS through PCCR8, we need to properly restore
+ * the original value to keep the same muxing, and for that we need to back
+ * it up (here).
+ */
+static void lynx_10g_backup_pccr_val(struct lynx_lane *lane)
+{
+ u32 val;
+ int err;
+
+ if (lane->mode == LANE_MODE_UNKNOWN)
+ return;
+
+ err = lynx_pccr_read(lane, lane->mode, &val);
+ if (err) {
+ dev_warn(&lane->phy->dev,
+ "The driver doesn't know how to access the PCCR for lane mode %s\n",
+ lynx_lane_mode_str(lane->mode));
+ lane->mode = LANE_MODE_UNKNOWN;
+ return;
+ }
+
+ lane->default_pccr[lane->mode] = val;
+
+ /* 1000Base-X, 1000Base-KX, 2500Base-KX and SGMII use the same PCCR8.
+ * Only the KX bit differs (set for 1000Base-KX). Since we back up PCCR
+ * values per lane mode, make sure to not back up the PCCR8 value with
+ * the KX bit set for the non-KX modes, if the lane was in KX mode at
+ * boot time. Just preserve bits 2:0, which tell whether the (and
+ * which) 1G PCS was enabled.
+ */
+ switch (lane->mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ lane->default_pccr[LANE_MODE_1000BASEX_SGMII] = val & ~PCCR8_SGMIIa_KX;
+ lane->default_pccr[LANE_MODE_2500BASEX] = val & ~PCCR8_SGMIIa_KX;
+ break;
+ default:
+ break;
+ }
+}
+
+/* Is the PCS enabled, according to the value backed up from the PCCR register
+ * for this lane mode?
+ *
+ * Normally we'd need to ask "what lane mode are we talking about?", but the
+ * answer is invariably the same regardless - PCCR8_SGMIIa_CFG has the same
+ * layout as PCCR9_QSGMIIa_CFG, PCCRB_XFIa_CFG etc etc, and the value 0
+ * universally means "PCS disabled". So this is just a shorthand answer.
+ */
+static bool lynx_10g_pccr_val_enabled(u32 pccr)
+{
+ return FIELD_PREP(PCCR8_SGMIIa_CFG, pccr) != 0;
+}
+
+static bool lynx_10g_lane_is_3_125g(struct lynx_lane *lane)
+{
+ struct lynx_priv *priv = lane->priv;
+ struct lynx_pll *pll;
+ u32 gcr0;
+
+ gcr0 = lynx_lane_read(lane, LNaGCR0);
+
+ if (gcr0 & LNaGCR0_TPLL_PLLF)
+ pll = &priv->pll[0];
+ else
+ pll = &priv->pll[1];
+
+ if (pll->frate_sel != PLLnCR0_FRATE_3_125G)
+ return false;
+
+ if (FIELD_GET(LNaGCR0_TRAT_SEL, gcr0) != RAT_SEL_FULL ||
+ FIELD_GET(LNaGCR0_RRAT_SEL, gcr0) != RAT_SEL_FULL)
+ return false;
+
+ return true;
+}
+
+static void lynx_10g_lane_read_configuration(struct lynx_lane *lane)
+{
+ u32 pssr0 = lynx_lane_read(lane, LNaPSSR0);
+ struct lynx_priv *priv = lane->priv;
+ int proto;
+
+ proto = FIELD_GET(LNaPSSR0_TYPE, pssr0);
+ switch (proto) {
+ case PROTO_SEL_SGMII_BASEX_KX_QSGMII:
+ if (lynx_10g_lane_is_3_125g(lane))
+ lane->mode = LANE_MODE_2500BASEX;
+ else if (FIELD_GET(LNaPSSR0_IS_QUAD, pssr0))
+ lane->mode = LANE_MODE_QSGMII;
+ else
+ lane->mode = LANE_MODE_1000BASEX_SGMII;
+ break;
+ case PROTO_SEL_XFI_10GBASER_KR_SXGMII:
+ if (FIELD_GET(LNaPSSR0_IS_QUAD, pssr0))
+ lane->mode = LANE_MODE_10G_QXGMII;
+ else if (priv->info->quirks & LYNX_QUIRK_HAS_HARDCODED_USXGMII)
+ lane->mode = LANE_MODE_USXGMII;
+ else
+ lane->mode = LANE_MODE_10GBASER;
+ break;
+ case PROTO_SEL_PCIE:
+ case PROTO_SEL_SATA:
+ case PROTO_SEL_XAUI:
+ break;
+ default:
+ dev_warn(&lane->phy->dev, "Unknown lane protocol 0x%x\n",
+ proto);
+ }
+
+ lynx_10g_backup_pccr_val(lane);
+}
+
+static int ls1028a_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(lane);
+ break;
+ case LANE_MODE_QSGMII:
+ if (lane != 1)
+ return -EINVAL;
+
+ pccr->offset = PCCR9;
+ pccr->width = 3;
+ pccr->shift = QSGMII_CFG(A);
+ break;
+ case LANE_MODE_10G_QXGMII:
+ if (lane != 1)
+ return -EINVAL;
+
+ pccr->offset = PCCR9;
+ pccr->width = 3;
+ pccr->shift = QXGMII_CFG(A);
+ break;
+ case LANE_MODE_USXGMII:
+ if (lane != 0)
+ return -EINVAL;
+
+ pccr->offset = PCCRB;
+ pccr->width = 3;
+ pccr->shift = SXGMII_CFG(A);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls1028a_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ return SGMIIaCR0(lane);
+ case LANE_MODE_QSGMII:
+ return lane == 1 ? QSGMIIaCR0(A) : -EINVAL;
+ case LANE_MODE_USXGMII:
+ return lane == 0 ? SXGMIIaCR0(A) : -EINVAL;
+ case LANE_MODE_10G_QXGMII:
+ return lane == 1 ? QXGMIIaCR0(A) : -EINVAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls1028a = {
+ .get_pccr = ls1028a_get_pccr,
+ .get_pcvt_offset = ls1028a_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 4,
+ .index = 1,
+ .quirks = LYNX_QUIRK_HAS_HARDCODED_USXGMII,
+};
+
+static int ls1046a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(lane);
+ break;
+ case LANE_MODE_QSGMII:
+ if (lane != 1)
+ return -EINVAL;
+
+ pccr->offset = PCCR9;
+ pccr->width = 3;
+ pccr->shift = QSGMII_CFG(B);
+ break;
+ case LANE_MODE_10GBASER:
+ switch (lane) {
+ case 2:
+ pccr->shift = XFI_CFG(A);
+ break;
+ case 3:
+ pccr->shift = XFI_CFG(B);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pccr->offset = PCCRB;
+ pccr->width = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls1046a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ return SGMIIaCR0(lane);
+ case LANE_MODE_QSGMII:
+ if (lane != 1)
+ return -EINVAL;
+
+ return QSGMIIaCR0(B);
+ case LANE_MODE_10GBASER:
+ switch (lane) {
+ case 2:
+ return XFIaCR0(A);
+ case 3:
+ return XFIaCR0(B);
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls1046a_serdes1 = {
+ .get_pccr = ls1046a_serdes1_get_pccr,
+ .get_pcvt_offset = ls1046a_serdes1_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 4,
+ .index = 1,
+};
+
+static int ls1046a_serdes2_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ if (lane != 1)
+ return -EINVAL;
+
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(B);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls1046a_serdes2_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ if (lane != 1)
+ return -EINVAL;
+
+ return SGMIIaCR0(B);
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls1046a_serdes2 = {
+ .get_pccr = ls1046a_serdes2_get_pccr,
+ .get_pcvt_offset = ls1046a_serdes2_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 4,
+ .index = 2,
+};
+
+static int ls1088a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(lane);
+ break;
+ case LANE_MODE_QSGMII:
+ switch (lane) {
+ case 0:
+ pccr->shift = QSGMII_CFG(A);
+ break;
+ case 1:
+ case 3:
+ pccr->shift = QSGMII_CFG(B);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pccr->offset = PCCR9;
+ pccr->width = 3;
+ break;
+ case LANE_MODE_10GBASER:
+ switch (lane) {
+ case 2:
+ pccr->shift = XFI_CFG(A);
+ break;
+ case 3:
+ pccr->shift = XFI_CFG(B);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pccr->offset = PCCRB;
+ pccr->width = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls1088a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ return SGMIIaCR0(lane);
+ case LANE_MODE_QSGMII:
+ switch (lane) {
+ case 0:
+ return QSGMIIaCR0(A);
+ case 1:
+ case 3:
+ return QSGMIIaCR0(B);
+ default:
+ return -EINVAL;
+ }
+ case LANE_MODE_10GBASER:
+ switch (lane) {
+ case 2:
+ return XFIaCR0(A);
+ case 3:
+ return XFIaCR0(B);
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls1088a_serdes1 = {
+ .get_pccr = ls1088a_serdes1_get_pccr,
+ .get_pcvt_offset = ls1088a_serdes1_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 4,
+ .index = 1,
+};
+
+static int ls2088a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(lane);
+ break;
+ case LANE_MODE_QSGMII:
+ switch (lane) {
+ case 2:
+ case 6:
+ pccr->shift = QSGMII_CFG(A);
+ break;
+ case 7:
+ pccr->shift = QSGMII_CFG(B);
+ break;
+ case 0:
+ case 4:
+ pccr->shift = QSGMII_CFG(C);
+ break;
+ case 1:
+ case 5:
+ pccr->shift = QSGMII_CFG(D);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pccr->offset = PCCR9;
+ pccr->width = 3;
+ break;
+ case LANE_MODE_10GBASER:
+ pccr->offset = PCCRB;
+ pccr->width = 3;
+ pccr->shift = XFI_CFG(lane);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls2088a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ return SGMIIaCR0(lane);
+ case LANE_MODE_QSGMII:
+ switch (lane) {
+ case 2:
+ case 6:
+ return QSGMIIaCR0(A);
+ case 7:
+ return QSGMIIaCR0(B);
+ case 0:
+ case 4:
+ return QSGMIIaCR0(C);
+ case 1:
+ case 5:
+ return QSGMIIaCR0(D);
+ default:
+ return -EINVAL;
+ }
+ case LANE_MODE_10GBASER:
+ return XFIaCR0(lane);
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls2088a_serdes1 = {
+ .get_pccr = ls2088a_serdes1_get_pccr,
+ .get_pcvt_offset = ls2088a_serdes1_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 8,
+ .index = 1,
+};
+
+static int ls2088a_serdes2_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(lane);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls2088a_serdes2_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ return SGMIIaCR0(lane);
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls2088a_serdes2 = {
+ .get_pccr = ls2088a_serdes2_get_pccr,
+ .get_pcvt_offset = ls2088a_serdes2_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 8,
+ .index = 2,
+};
+
+/* Halting puts the lane in a mode in which it can be reconfigured */
+static void lynx_10g_lane_halt(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ /* Issue a reset request */
+ lynx_lane_rmw(lane, LNaGCR0,
+ LNaGCR0_RRST_ON | LNaGCR0_TRST_ON,
+ LNaGCR0_RRST | LNaGCR0_TRST);
+
+ /* The RM says to wait for at least 50ns */
+ usleep_range(1, 2);
+}
+
+static void lynx_10g_lane_reset(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ /* Finalize the reset request */
+ lynx_lane_rmw(lane, LNaGCR0,
+ LNaGCR0_RRST_OFF | LNaGCR0_TRST_OFF,
+ LNaGCR0_RRST | LNaGCR0_TRST);
+}
+
+static int lynx_10g_power_off(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ if (!lane->powered_up)
+ return 0;
+
+ /* Issue a reset request with the power down bits set */
+ lynx_lane_rmw(lane, LNaGCR0,
+ LNaGCR0_RRST_ON | LNaGCR0_TRST_ON |
+ LNaGCR0_RX_PD | LNaGCR0_TX_PD,
+ LNaGCR0_RRST | LNaGCR0_TRST |
+ LNaGCR0_RX_PD | LNaGCR0_TX_PD);
+
+ /* The RM says to wait for at least 50ns */
+ usleep_range(1, 2);
+
+ lane->powered_up = false;
+
+ return 0;
+}
+
+static int lynx_10g_power_on(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ if (lane->powered_up)
+ return 0;
+
+ /* RM says that to enable a previously powered down lane, set
+ * LNmGCR0[{R,T}X_PD]=0, wait 15 us, then set LNmGCR0[{R,T}RST]=1.
+ */
+ lynx_lane_rmw(lane, LNaGCR0, 0, LNaGCR0_RX_PD | LNaGCR0_TX_PD);
+ usleep_range(150, 300);
+ lynx_10g_lane_reset(phy);
+
+ lane->powered_up = true;
+
+ return 0;
+}
+
+static void lynx_10g_lane_set_nrate(struct lynx_lane *lane,
+ struct lynx_pll *pll,
+ enum lynx_lane_mode mode)
+{
+ enum lynx_10g_rat_sel nrate;
+
+ switch (pll->frate_sel) {
+ case PLLnCR0_FRATE_5G:
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ nrate = RAT_SEL_QUARTER;
+ break;
+ case LANE_MODE_QSGMII:
+ nrate = RAT_SEL_FULL;
+ break;
+ default:
+ return;
+ }
+ break;
+ case PLLnCR0_FRATE_3_125G:
+ switch (mode) {
+ case LANE_MODE_2500BASEX:
+ nrate = RAT_SEL_FULL;
+ break;
+ default:
+ return;
+ }
+ break;
+ case PLLnCR0_FRATE_5_15625G:
+ switch (mode) {
+ case LANE_MODE_10GBASER:
+ case LANE_MODE_USXGMII:
+ case LANE_MODE_10G_QXGMII:
+ nrate = RAT_SEL_DOUBLE;
+ break;
+ default:
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+
+ lynx_lane_rmw(lane, LNaGCR0,
+ FIELD_PREP(LNaGCR0_TRAT_SEL, nrate) |
+ FIELD_PREP(LNaGCR0_RRAT_SEL, nrate),
+ LNaGCR0_RRAT_SEL | LNaGCR0_TRAT_SEL);
+}
+
+static void lynx_10g_lane_set_pll(struct lynx_lane *lane,
+ struct lynx_pll *pll)
+{
+ if (pll->id == 0) {
+ lynx_lane_rmw(lane, LNaGCR0,
+ LNaGCR0_RPLL_PLLF | LNaGCR0_TPLL_PLLF,
+ LNaGCR0_RPLL_MSK | LNaGCR0_TPLL_MSK);
+ } else {
+ lynx_lane_rmw(lane, LNaGCR0,
+ LNaGCR0_RPLL_PLLS | LNaGCR0_TPLL_PLLS,
+ LNaGCR0_RPLL_MSK | LNaGCR0_TPLL_MSK);
+ }
+}
+
+static void lynx_10g_lane_remap_pll(struct lynx_lane *lane,
+ enum lynx_lane_mode lane_mode)
+{
+ struct lynx_priv *priv = lane->priv;
+ struct lynx_pll *pll;
+
+ /* Switch to the PLL that works with this interface type */
+ pll = lynx_pll_get(priv, lane_mode);
+ if (unlikely(!pll))
+ return;
+
+ lynx_10g_lane_set_pll(lane, pll);
+
+ /* Choose the portion of clock net to be used on this lane */
+ lynx_10g_lane_set_nrate(lane, pll, lane_mode);
+}
+
+static void lynx_10g_lane_change_proto_conf(struct lynx_lane *lane,
+ enum lynx_lane_mode mode)
+{
+ const struct lynx_10g_proto_conf *conf = &lynx_10g_proto_conf[mode];
+
+ lynx_lane_rmw(lane, LNaGCR0,
+ FIELD_PREP(LNaGCR0_PROTS, conf->proto_sel) |
+ FIELD_PREP(LNaGCR0_IF20BIT_EN, conf->if20bit_en),
+ LNaGCR0_PROTS | LNaGCR0_IF20BIT_EN);
+ lynx_lane_rmw(lane, LNaGCR1,
+ FIELD_PREP(LNaGCR1_REIDL_TH, conf->reidl_th) |
+ FIELD_PREP(LNaGCR1_REIDL_ET_MSB, conf->reidl_et_msb) |
+ FIELD_PREP(LNaGCR1_REIDL_ET_SEL, conf->reidl_et_sel) |
+ FIELD_PREP(LNaGCR1_REIDL_EX_MSB, conf->reidl_ex_msb) |
+ FIELD_PREP(LNaGCR1_REIDL_EX_SEL, conf->reidl_ex_sel) |
+ FIELD_PREP(LNaGCR1_ISLEW_RCTL, conf->islew_rctl) |
+ FIELD_PREP(LNaGCR1_OSLEW_RCTL, conf->oslew_rctl),
+ LNaGCR1_REIDL_TH |
+ LNaGCR1_REIDL_ET_MSB | LNaGCR1_REIDL_ET_SEL |
+ LNaGCR1_REIDL_EX_MSB | LNaGCR1_REIDL_EX_SEL |
+ LNaGCR1_ISLEW_RCTL | LNaGCR1_OSLEW_RCTL);
+ lynx_lane_rmw(lane, LNaRECR0,
+ FIELD_PREP(LNaRECR0_RXEQ_BST, conf->rxeq_bst) |
+ FIELD_PREP(LNaRECR0_GK2OVD, conf->gk2ovd) |
+ FIELD_PREP(LNaRECR0_GK3OVD, conf->gk3ovd) |
+ FIELD_PREP(LNaRECR0_GK2OVD_EN, conf->gk2ovd_en) |
+ FIELD_PREP(LNaRECR0_GK3OVD_EN, conf->gk3ovd_en) |
+ FIELD_PREP(LNaRECR0_BASE_WAND, conf->base_wand),
+ LNaRECR0_RXEQ_BST | LNaRECR0_GK2OVD | LNaRECR0_GK3OVD |
+ LNaRECR0_GK2OVD_EN | LNaRECR0_GK3OVD_EN |
+ LNaRECR0_BASE_WAND);
+ lynx_lane_rmw(lane, LNaTECR0,
+ FIELD_PREP(LNaTECR0_TEQ_TYPE, conf->teq_type) |
+ FIELD_PREP(LNaTECR0_SGN_PREQ, conf->sgn_preq) |
+ FIELD_PREP(LNaTECR0_RATIO_PREQ, conf->ratio_preq) |
+ FIELD_PREP(LNaTECR0_SGN_POST1Q, conf->sgn_post1q) |
+ FIELD_PREP(LNaTECR0_RATIO_PST1Q, conf->ratio_post1q) |
+ FIELD_PREP(LNaTECR0_ADPT_EQ, conf->adpt_eq) |
+ FIELD_PREP(LNaTECR0_AMP_RED, conf->amp_red),
+ LNaTECR0_TEQ_TYPE | LNaTECR0_SGN_PREQ |
+ LNaTECR0_RATIO_PREQ | LNaTECR0_SGN_POST1Q |
+ LNaTECR0_RATIO_PST1Q | LNaTECR0_ADPT_EQ |
+ LNaTECR0_AMP_RED);
+ lynx_lane_write(lane, LNaTTLCR0, conf->ttlcr0);
+}
+
+static int lynx_10g_lane_disable_pcvt(struct lynx_lane *lane,
+ enum lynx_lane_mode mode)
+{
+ struct lynx_priv *priv = lane->priv;
+ int err;
+
+ spin_lock(&priv->pcc_lock);
+
+ err = lynx_pccr_write(lane, mode, 0);
+ if (err)
+ goto out;
+
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ err = lynx_pcvt_rmw(lane, mode, CR(1), SGMIIaCR1_SGPCS_DIS,
+ SGMIIaCR1_SGPCS_EN);
+ if (err)
+ goto out;
+
+ lynx_pcvt_rmw(lane, mode, CR(0),
+ SGMIIaCR0_RST_SGM_ON | SGMIIaCR0_PD_SGM,
+ SGMIIaCR0_RST_SGM | SGMIIaCR0_PD_SGM);
+ break;
+ case LANE_MODE_QSGMII:
+ err = lynx_pcvt_rmw(lane, mode, CR(0),
+ QSGMIIaCR0_RST_QSGM_ON | QSGMIIaCR0_PD_QSGM,
+ QSGMIIaCR0_RST_QSGM | QSGMIIaCR0_PD_QSGM);
+ if (err)
+ goto out;
+ break;
+ default:
+ err = 0;
+ }
+
+out:
+ spin_unlock(&priv->pcc_lock);
+
+ return err;
+}
+
+static int lynx_10g_lane_enable_pcvt(struct lynx_lane *lane,
+ enum lynx_lane_mode mode)
+{
+ struct lynx_priv *priv = lane->priv;
+ u32 val;
+ int err;
+
+ spin_lock(&priv->pcc_lock);
+
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ err = lynx_pcvt_rmw(lane, mode, CR(1), SGMIIaCR1_SGPCS_EN,
+ SGMIIaCR1_SGPCS_EN);
+ if (err)
+ goto out;
+
+ lynx_pcvt_rmw(lane, mode, CR(0), SGMIIaCR0_RST_SGM_OFF,
+ SGMIIaCR0_RST_SGM | SGMIIaCR0_PD_SGM);
+ break;
+ case LANE_MODE_QSGMII:
+ err = lynx_pcvt_rmw(lane, mode, CR(0), QSGMIIaCR0_RST_QSGM_OFF,
+ QSGMIIaCR0_RST_QSGM | QSGMIIaCR0_PD_QSGM);
+ if (err)
+ goto out;
+ break;
+ default:
+ err = 0;
+ }
+
+ /* If the PCS was enabled at boot time, use the backed up PCCR value to
+ * re-enable it here, to preserve the muxing.
+ */
+ if (lynx_10g_pccr_val_enabled(lane->default_pccr[mode])) {
+ err = lynx_pccr_write(lane, mode, lane->default_pccr[mode]);
+ goto out;
+ }
+
+ /* If the PCS was not enabled, set the PCCR to a default value which
+ * enables it (1). The assumption is that this is the only PCS <->
+ * SerDes lane muxing value possible.
+ *
+ * This is mostly useful for SGMII <-> 10GBase-R major protocol
+ * reconfiguration, where at boot time, either the SGMII or the
+ * 10GBase-R PCS is enabled for the lane, but not both.
+ *
+ * In fact, if there are multiple lane muxing options, this function
+ * will most likely not choose the right one. For correct functionality
+ * there, we assume that the PCS we are enabling here was found enabled
+ * at boot time (reset default, or through PBL, or...), and we preserve
+ * its muxing through the default_pccr branch above.
+ */
+ val = 0;
+
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ val |= FIELD_PREP(PCCR8_SGMIIa_CFG, 1);
+ break;
+ case LANE_MODE_QSGMII:
+ val |= FIELD_PREP(PCCR9_QSGMIIa_CFG, 1);
+ break;
+ case LANE_MODE_10G_QXGMII:
+ val |= FIELD_PREP(PCCR9_QXGMIIa_CFG, 1);
+ break;
+ case LANE_MODE_10GBASER:
+ val |= FIELD_PREP(PCCRB_XFIa_CFG, 1);
+ break;
+ case LANE_MODE_USXGMII:
+ val |= FIELD_PREP(PCCRB_SXGMIIa_CFG, 1);
+ break;
+ default:
+ err = 0;
+ goto out;
+ }
+
+ err = lynx_pccr_write(lane, mode, val);
+out:
+ spin_unlock(&priv->pcc_lock);
+
+ return err;
+}
+
+static bool lynx_10g_lane_mode_needs_rcw_override(struct lynx_lane *lane,
+ enum lynx_lane_mode new)
+{
+ enum lynx_lane_mode curr = lane->mode;
+
+ /* Major protocol changes, which involve changing the PCS connection to
+ * the GMII MAC with the one to the XGMII MAC, require an RCW override
+ * procedure to reconfigure an internal mux, as documented here:
+ * https://lore.kernel.org/linux-phy/20230810102631.bvozjer3t67r67iy@skbuf/
+ * This is SoC-specific, and not yet implemented in drivers/soc/fsl/guts.c.
+ *
+ * So the supported set of protocols depends on the initial lane mode.
+ *
+ * Minor protocol changes (SGMII <-> 1000Base-X <-> 2500Base-X or
+ * 10GBase-R <-> USXGMII) are supported.
+ */
+ if ((lynx_lane_mode_uses_gmii_mac(curr) &&
+ lynx_lane_mode_uses_xgmii_mac(new)) ||
+ (lynx_lane_mode_uses_xgmii_mac(curr) &&
+ lynx_lane_mode_uses_gmii_mac(new)))
+ return true;
+
+ return false;
+}
+
+static int lynx_10g_validate(struct phy *phy, enum phy_mode mode, int submode,
+ union phy_configure_opts *opts)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+ enum lynx_lane_mode lane_mode;
+ int err;
+
+ err = lynx_phy_mode_to_lane_mode(phy, mode, submode, &lane_mode);
+ if (err)
+ return err;
+
+ if (lynx_10g_lane_mode_needs_rcw_override(lane, lane_mode))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int lynx_10g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+ bool powered_up = lane->powered_up;
+ enum lynx_lane_mode lane_mode;
+ int err;
+
+ err = lynx_10g_validate(phy, mode, submode, NULL);
+ if (err)
+ return err;
+
+ lane_mode = phy_interface_to_lane_mode(submode);
+ /* lynx_10g_validate() already made sure the lane_mode is supported */
+
+ if (lane_mode == lane->mode)
+ return 0;
+
+ /* If the lane is powered up, put the lane into the halt state while
+ * the reconfiguration is being done.
+ */
+ if (powered_up)
+ lynx_10g_lane_halt(phy);
+
+ err = lynx_10g_lane_disable_pcvt(lane, lane->mode);
+ if (err)
+ goto out;
+
+ lynx_10g_lane_change_proto_conf(lane, lane_mode);
+ lynx_10g_lane_remap_pll(lane, lane_mode);
+ WARN_ON(lynx_10g_lane_enable_pcvt(lane, lane_mode));
+
+ lane->mode = lane_mode;
+
+out:
+ if (powered_up) {
+ /* The RM says to wait for at least 120 ns */
+ usleep_range(1, 2);
+ lynx_10g_lane_reset(phy);
+ }
+
+ return err;
+}
+
+static int lynx_10g_init(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ /* Mark the fact that the lane was init */
+ lane->init = true;
+
+ /* SerDes lanes are powered on at boot time. Any lane that is
+ * managed by this driver will get powered off when its consumer
+ * calls phy_init().
+ */
+ lane->powered_up = true;
+ lynx_10g_power_off(phy);
+
+ return 0;
+}
+
+static int lynx_10g_exit(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ /* The lane returns to the state where it isn't managed by the
+ * consumer, so we must treat is as if it isn't initialized, and always
+ * powered on.
+ */
+ lane->init = false;
+ lane->powered_up = false;
+ lynx_10g_power_on(phy);
+
+ return 0;
+}
+
+static const struct phy_ops lynx_10g_ops = {
+ .init = lynx_10g_init,
+ .exit = lynx_10g_exit,
+ .power_on = lynx_10g_power_on,
+ .power_off = lynx_10g_power_off,
+ .set_mode = lynx_10g_set_mode,
+ .validate = lynx_10g_validate,
+ .owner = THIS_MODULE,
+};
+
+static int lynx_10g_probe(struct platform_device *pdev)
+{
+ return lynx_probe(pdev, of_device_get_match_data(&pdev->dev),
+ &lynx_10g_ops);
+}
+
+static const struct of_device_id lynx_10g_of_match_table[] = {
+ { .compatible = "fsl,ls1028a-serdes", .data = &lynx_info_ls1028a },
+ { .compatible = "fsl,ls1046a-serdes1", .data = &lynx_info_ls1046a_serdes1 },
+ { .compatible = "fsl,ls1046a-serdes2", .data = &lynx_info_ls1046a_serdes2 },
+ { .compatible = "fsl,ls1088a-serdes1", .data = &lynx_info_ls1088a_serdes1 },
+ { .compatible = "fsl,ls2088a-serdes1", .data = &lynx_info_ls2088a_serdes1 },
+ { .compatible = "fsl,ls2088a-serdes2", .data = &lynx_info_ls2088a_serdes2 },
+ {}
+};
+MODULE_DEVICE_TABLE(of, lynx_10g_of_match_table);
+
+static struct platform_driver lynx_10g_driver = {
+ .probe = lynx_10g_probe,
+ .remove = lynx_remove,
+ .driver = {
+ .name = "lynx-10g",
+ .of_match_table = lynx_10g_of_match_table,
+ },
+};
+module_platform_driver(lynx_10g_driver);
+
+MODULE_IMPORT_NS("PHY_FSL_LYNX");
+MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>");
+MODULE_AUTHOR("Vladimir Oltean <vladimir.oltean@nxp.com>");
+MODULE_DESCRIPTION("Lynx 10G SerDes PHY driver for Layerscape SoCs");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.c b/drivers/phy/freescale/phy-fsl-lynx-core.c
index 1e411bfab404..2cfe9236ffc5 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.c
@@ -11,6 +11,12 @@ const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode)
switch (lane_mode) {
case LANE_MODE_1000BASEX_SGMII:
return "1000Base-X/SGMII";
+ case LANE_MODE_2500BASEX:
+ return "2500Base-X";
+ case LANE_MODE_QSGMII:
+ return "QSGMII";
+ case LANE_MODE_10G_QXGMII:
+ return "10G-QXGMII";
case LANE_MODE_10GBASER:
return "10GBase-R";
case LANE_MODE_USXGMII:
@@ -29,6 +35,12 @@ enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf)
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_1000BASEX:
return LANE_MODE_1000BASEX_SGMII;
+ case PHY_INTERFACE_MODE_2500BASEX:
+ return LANE_MODE_2500BASEX;
+ case PHY_INTERFACE_MODE_QSGMII:
+ return LANE_MODE_QSGMII;
+ case PHY_INTERFACE_MODE_10G_QXGMII:
+ return LANE_MODE_10G_QXGMII;
case PHY_INTERFACE_MODE_10GBASER:
return LANE_MODE_10GBASER;
case PHY_INTERFACE_MODE_USXGMII:
@@ -89,6 +101,29 @@ bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode)
}
EXPORT_SYMBOL_NS_GPL(lynx_lane_supports_mode, "PHY_FSL_LYNX");
+/* The quad protocols are fixed because the lane has multiple consumers, and
+ * one phy_set_mode_ext() affects the other consumers as well. We have no use
+ * case for dynamic protocol changing here, so disallow it.
+ */
+static enum lynx_lane_mode lynx_fixed_protocols[] = {
+ LANE_MODE_QSGMII,
+ LANE_MODE_10G_QXGMII,
+};
+
+static bool lynx_lane_restrict_fixed_mode_change(struct lynx_lane *lane,
+ enum lynx_lane_mode new)
+{
+ enum lynx_lane_mode curr = lane->mode;
+
+ for (int i = 0; i < ARRAY_SIZE(lynx_fixed_protocols); i++)
+ if ((curr == lynx_fixed_protocols[i] ||
+ new == lynx_fixed_protocols[i]) &&
+ curr != new)
+ return true;
+
+ return false;
+}
+
/* Translate the mode/submode from phy_validate() and phy_set_mode_ext() to a
* lane_mode and return 0 if it is supported and we can transition to it from
* the current lane mode, or return negative error otherwise.
@@ -112,6 +147,9 @@ int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode,
if (!lynx_lane_supports_mode(lane, tmp_lane_mode))
return -EINVAL;
+ if (lynx_lane_restrict_fixed_mode_change(lane, tmp_lane_mode))
+ return -EINVAL;
+
if (lane_mode)
*lane_mode = tmp_lane_mode;
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.h b/drivers/phy/freescale/phy-fsl-lynx-core.h
index 37fa4b544faa..a60429ba9324 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.h
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.h
@@ -9,6 +9,7 @@
#include <soc/fsl/phy-fsl-lynx.h>
#define LYNX_NUM_PLL 2
+#define LYNX_QUIRK_HAS_HARDCODED_USXGMII BIT(0)
struct lynx_priv;
struct lynx_lane;
@@ -36,6 +37,7 @@ struct lynx_lane {
bool init;
unsigned int id;
enum lynx_lane_mode mode;
+ u32 default_pccr[LANE_MODE_MAX];
};
struct lynx_info {
@@ -48,6 +50,8 @@ struct lynx_info {
void (*cdr_lock_check)(struct lynx_lane *lane);
int first_lane;
int num_lanes;
+ int index;
+ unsigned long quirks;
};
struct lynx_priv {
diff --git a/include/soc/fsl/phy-fsl-lynx.h b/include/soc/fsl/phy-fsl-lynx.h
index 92e8272d5ae1..ff5a7d1835b5 100644
--- a/include/soc/fsl/phy-fsl-lynx.h
+++ b/include/soc/fsl/phy-fsl-lynx.h
@@ -7,10 +7,37 @@
enum lynx_lane_mode {
LANE_MODE_UNKNOWN,
LANE_MODE_1000BASEX_SGMII,
+ LANE_MODE_2500BASEX,
+ LANE_MODE_QSGMII,
+ LANE_MODE_10G_QXGMII,
LANE_MODE_10GBASER,
LANE_MODE_USXGMII,
LANE_MODE_25GBASER,
LANE_MODE_MAX,
};
+static inline bool lynx_lane_mode_uses_gmii_mac(enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ case LANE_MODE_QSGMII:
+ case LANE_MODE_10G_QXGMII:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool lynx_lane_mode_uses_xgmii_mac(enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_10GBASER:
+ case LANE_MODE_USXGMII:
+ return true;
+ default:
+ return false;
+ }
+}
+
#endif /* __PHY_FSL_LYNX_H_ */
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v5 phy-next 14/16] dt-bindings: phy: lynx-10g: initial document
From: Vladimir Oltean @ 2026-06-10 15:19 UTC (permalink / raw)
To: linux-phy
Cc: Ioana Ciornei, Vinod Koul, Neil Armstrong, Tanjeff Moos,
linux-kernel, Rob Herring, devicetree, Conor Dooley,
Krzysztof Kozlowski
In-Reply-To: <20260610151952.2141019-1-vladimir.oltean@nxp.com>
Add a schema for the 10G Lynx SerDes. This is very similar to the modern
form of the 28G Lynx SerDes, which is very much the intention.
There is intentionally no generic fsl,lynx-10g compatible string due to
the hardware inability to report its capabilities, despite having a
common register map.
We allow both forms of #phy-cells = <1> in the top-level provider
and #phy-cells = <0> in the per-lane provider for more flexibility to
consumers, and because the kernel code is shared with the 28G Lynx which
already has that support for compatibility reasons.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
Cc: devicetree@vger.kernel.org
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Rob Herring <robh@kernel.org>
v4->v5:
- return "big-endian: true" as a global constraint, add "big-endian:
false" in case the compatible is not LS1046A (Conor)
v3->v4:
- avoid relying on dtschema fixup to turn "properties: compatible: enum:"
into valid json-schema syntax ("properties: compatible: items: enum:"),
instead use "properties: compatible: contains: enum:" (Rob)
- move "big-endian: true" under allOf constraint for LS1046A, same place
as "required: big-endian"
- add Rob's review tag
v2->v3:
- move fsl,lynx-10g compatible comment to commit message from schema
property description
- make big-endian required for LS1046A
v1->v2:
- move patch later in series, right before driver
- deliberately ignoring this Sashiko feedback:
https://lore.kernel.org/linux-phy/20260529125017.ifqunh52gdzhthdg@skbuf/
---
.../devicetree/bindings/phy/fsl,lynx-10g.yaml | 139 ++++++++++++++++++
1 file changed, 139 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/fsl,lynx-10g.yaml
diff --git a/Documentation/devicetree/bindings/phy/fsl,lynx-10g.yaml b/Documentation/devicetree/bindings/phy/fsl,lynx-10g.yaml
new file mode 100644
index 000000000000..2e7d0abfa71a
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/fsl,lynx-10g.yaml
@@ -0,0 +1,139 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/fsl,lynx-10g.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale Lynx 10G SerDes PHY
+
+maintainers:
+ - Vladimir Oltean <vladimir.oltean@nxp.com>
+
+description:
+ The 10G Lynx is a multi-protocol SerDes block which handles networking, PCIe,
+ SATA and other high-speed interfaces. It is present on most QorIQ and
+ Layerscape SoCs. The register map is common, but the integration is
+ SoC-specific, with the differences consisting in register endianness, the
+ number of lanes, protocol converters available per lane and their location in
+ the PCCR registers. Some SoCs have multiple SerDes blocks and those differ in
+ their protocol capabilities per lane.
+
+properties:
+ compatible:
+ enum:
+ - fsl,ls1028a-serdes
+ - fsl,ls1046a-serdes1
+ - fsl,ls1046a-serdes2
+ - fsl,ls1088a-serdes1
+ - fsl,ls1088a-serdes2
+ - fsl,ls2088a-serdes1
+ - fsl,ls2088a-serdes2
+
+ reg:
+ maxItems: 1
+
+ big-endian: true
+
+ "#phy-cells":
+ const: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+patternProperties:
+ "^phy@[0-7]$":
+ type: object
+ description: SerDes lane (single RX/TX differential pair)
+
+ properties:
+ reg:
+ minimum: 0
+ maximum: 7
+ description: Lane index as seen in register map
+
+ "#phy-cells":
+ const: 0
+
+ required:
+ - reg
+ - "#phy-cells"
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - "#phy-cells"
+ - "#address-cells"
+ - "#size-cells"
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,ls1028a-serdes
+ - fsl,ls1046a-serdes1
+ - fsl,ls1046a-serdes2
+ - fsl,ls1088a-serdes1
+ - fsl,ls1088a-serdes2
+ then:
+ patternProperties:
+ "^phy@[0-7]$":
+ properties:
+ reg:
+ minimum: 0
+ maximum: 3
+ - if:
+ properties:
+ compatible:
+ enum:
+ - fsl,ls1046a-serdes1
+ - fsl,ls1046a-serdes2
+ then:
+ required:
+ - big-endian
+ else:
+ properties:
+ big-endian: false
+
+additionalProperties: false
+
+examples:
+ - |
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ serdes@1ea0000 {
+ compatible = "fsl,ls1028a-serdes";
+ reg = <0x0 0x1ea0000 0x0 0xffff>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #phy-cells = <1>;
+
+ phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ };
+
+ phy@1 {
+ reg = <1>;
+ #phy-cells = <0>;
+ };
+
+ phy@2 {
+ reg = <2>;
+ #phy-cells = <0>;
+ };
+
+ phy@3 {
+ reg = <3>;
+ #phy-cells = <0>;
+ };
+ };
+ };
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v5 phy-next 13/16] phy: lynx-28g: improve phy_validate() procedure
From: Vladimir Oltean @ 2026-06-10 15:19 UTC (permalink / raw)
To: linux-phy
Cc: Ioana Ciornei, Vinod Koul, Neil Armstrong, Tanjeff Moos,
linux-kernel
In-Reply-To: <20260610151952.2141019-1-vladimir.oltean@nxp.com>
lynx_28g_validate() suffers from the following shortcomings:
- Changing the protocol should not be possible if the source protocol of
the lane is unsupported. This is because lynx_28g_proto_conf[] only
covers the register deltas between any pair of supported lane modes,
but that delta is probably incomplete if the source protocol is, say,
PCIe (which is currently assimilated by the driver to
LANE_MODE_UNKNOWN).
lynx_28g_proto_conf() does refuse changing the protocol if the current
one is unsupported, but we shouldn't advertise it via phy_validate()
at all.
The phy_set_mode_ext() call should perform the exact same
verifications as phy_validate() did, in case the caller bypassed
phy_validate(). So we need to centralize the logic into a common
validation. But lynx_28g_set_mode() later needs the lane_mode that
this validation needs to compute anyway, so name the common helper
lynx_phy_mode_to_lane_mode() and let it return that lane_mode.
- Future core sanity checks on phy_validate() will want to differentiate
the case where this optional method is not implemented from the case
where the mode/submode is really not supported. So we shouldn't return
-EOPNOTSUPP from lynx_28g_validate(), but -EINVAL to signal that we do
implement the operation:
https://lore.kernel.org/linux-phy/aY2lFTIALH7qEJmM@shell.armlinux.org.uk/
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v2->v5: none
v1->v2: patch is new
---
drivers/phy/freescale/phy-fsl-lynx-28g.c | 38 +++++++----------------
drivers/phy/freescale/phy-fsl-lynx-core.c | 30 ++++++++++++++++++
drivers/phy/freescale/phy-fsl-lynx-core.h | 2 ++
3 files changed, 43 insertions(+), 27 deletions(-)
diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c
index 50b991870edb..38afcd081a2a 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-28g.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c
@@ -968,22 +968,22 @@ static int lynx_28g_lane_enable_pcvt(struct lynx_28g_lane *lane,
return err;
}
+static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode,
+ union phy_configure_opts *opts)
+{
+ return lynx_phy_mode_to_lane_mode(phy, mode, submode, NULL);
+}
+
static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
{
- struct lynx_28g_lane *lane = phy_get_drvdata(phy);
+ struct lynx_lane *lane = phy_get_drvdata(phy);
int powered_up = lane->powered_up;
enum lynx_lane_mode lane_mode;
- int err = 0;
-
- if (mode != PHY_MODE_ETHERNET)
- return -EOPNOTSUPP;
-
- if (lane->mode == LANE_MODE_UNKNOWN)
- return -EOPNOTSUPP;
+ int err;
- lane_mode = phy_interface_to_lane_mode(submode);
- if (!lynx_lane_supports_mode(lane, lane_mode))
- return -EOPNOTSUPP;
+ err = lynx_phy_mode_to_lane_mode(phy, mode, submode, &lane_mode);
+ if (err)
+ return err;
if (lane_mode == lane->mode)
return 0;
@@ -1014,22 +1014,6 @@ static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
return err;
}
-static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode,
- union phy_configure_opts *opts __always_unused)
-{
- struct lynx_28g_lane *lane = phy_get_drvdata(phy);
- enum lynx_lane_mode lane_mode;
-
- if (mode != PHY_MODE_ETHERNET)
- return -EOPNOTSUPP;
-
- lane_mode = phy_interface_to_lane_mode(submode);
- if (!lynx_lane_supports_mode(lane, lane_mode))
- return -EOPNOTSUPP;
-
- return 0;
-}
-
static int lynx_28g_init(struct phy *phy)
{
struct lynx_28g_lane *lane = phy_get_drvdata(phy);
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.c b/drivers/phy/freescale/phy-fsl-lynx-core.c
index 226b2af2b599..1e411bfab404 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.c
@@ -89,6 +89,36 @@ bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode)
}
EXPORT_SYMBOL_NS_GPL(lynx_lane_supports_mode, "PHY_FSL_LYNX");
+/* Translate the mode/submode from phy_validate() and phy_set_mode_ext() to a
+ * lane_mode and return 0 if it is supported and we can transition to it from
+ * the current lane mode, or return negative error otherwise.
+ */
+int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode,
+ int submode, enum lynx_lane_mode *lane_mode)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+ enum lynx_lane_mode tmp_lane_mode;
+
+ /* The protocol configuration tables are incomplete for full lane
+ * reconfiguration from an arbitrary protocol.
+ */
+ if (lane->mode == LANE_MODE_UNKNOWN)
+ return -EINVAL;
+
+ if (mode != PHY_MODE_ETHERNET)
+ return -EINVAL;
+
+ tmp_lane_mode = phy_interface_to_lane_mode(submode);
+ if (!lynx_lane_supports_mode(lane, tmp_lane_mode))
+ return -EINVAL;
+
+ if (lane_mode)
+ *lane_mode = tmp_lane_mode;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(lynx_phy_mode_to_lane_mode, "PHY_FSL_LYNX");
+
struct lynx_pll *lynx_pll_get(struct lynx_priv *priv, enum lynx_lane_mode mode)
{
struct lynx_pll *pll;
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.h b/drivers/phy/freescale/phy-fsl-lynx-core.h
index 3d9508dfb2c1..37fa4b544faa 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.h
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.h
@@ -113,6 +113,8 @@ void lynx_remove(struct platform_device *pdev);
const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode);
enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf);
bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode);
+int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode,
+ int submode, enum lynx_lane_mode *lane_mode);
struct lynx_pll *lynx_pll_get(struct lynx_priv *priv, enum lynx_lane_mode mode);
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v5 phy-next 12/16] phy: lynx-28g: optimize read-modify-write operation
From: Vladimir Oltean @ 2026-06-10 15:19 UTC (permalink / raw)
To: linux-phy
Cc: Ioana Ciornei, Vinod Koul, Neil Armstrong, Tanjeff Moos,
linux-kernel
In-Reply-To: <20260610151952.2141019-1-vladimir.oltean@nxp.com>
It is unnecessary to rewrite a register if the masked field already
contains the desired value upon reading. The hardware behaviour does not
depend upon register writes with identical values.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v1->v5: none
---
drivers/phy/freescale/phy-fsl-lynx-core.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.h b/drivers/phy/freescale/phy-fsl-lynx-core.h
index d82e529fa65a..3d9508dfb2c1 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.h
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.h
@@ -93,7 +93,8 @@ static inline void lynx_rmw(struct lynx_priv *priv, unsigned long off, u32 val,
orig = lynx_read(priv, off);
tmp = orig & ~mask;
tmp |= val;
- lynx_write(priv, off, tmp);
+ if (orig != tmp)
+ lynx_write(priv, off, tmp);
}
#define lynx_lane_rmw(lane, reg, val, mask) \
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v5 phy-next 11/16] phy: lynx-28g: add support for big endian register maps
From: Vladimir Oltean @ 2026-06-10 15:19 UTC (permalink / raw)
To: linux-phy
Cc: Ioana Ciornei, Vinod Koul, Neil Armstrong, Tanjeff Moos,
linux-kernel
In-Reply-To: <20260610151952.2141019-1-vladimir.oltean@nxp.com>
Some 10G Lynx SerDes blocks are big endian and require byte swapping
because the CPUs are little endian armv8 (LS1046A). Parse the
"big-endian" device tree property, and modify the base lynx_read() and
lynx_write() accessors to test this property before issuing either the
ioread32() or ioread32be() variants (as per
Documentation/driver-api/device-io.rst).
All other accessors - lynx_rmw(), lynx_lane_read(), lynx_lane_write(),
lynx_lane_rmw(), lynx_pll_read() - need to go through these endian-aware
helpers.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v2->v5: none
v1->v2:
- none. Deliberately ignoring the Sashiko feedback that "return
<function that returns void>()" is an antipattern:
https://lore.kernel.org/linux-phy/20260529120005.icj44ffdvdk25fjm@skbuf/
---
drivers/phy/freescale/phy-fsl-lynx-core.c | 1 +
drivers/phy/freescale/phy-fsl-lynx-core.h | 36 ++++++++++++++++-------
2 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.c b/drivers/phy/freescale/phy-fsl-lynx-core.c
index 3fb89bb4b0d6..226b2af2b599 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.c
@@ -295,6 +295,7 @@ int lynx_probe(struct platform_device *pdev, const struct lynx_info *info,
priv->dev = dev;
priv->info = info;
+ priv->big_endian = device_property_read_bool(dev, "big-endian");
dev_set_drvdata(dev, priv);
spin_lock_init(&priv->pcc_lock);
INIT_DELAYED_WORK(&priv->cdr_check, lynx_cdr_lock_check);
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.h b/drivers/phy/freescale/phy-fsl-lynx-core.h
index e8b280cc9b38..d82e529fa65a 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.h
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.h
@@ -58,36 +58,52 @@ struct lynx_priv {
* like PCCn
*/
spinlock_t pcc_lock;
+ bool big_endian;
struct lynx_pll pll[LYNX_NUM_PLL];
struct lynx_lane *lane;
struct delayed_work cdr_check;
};
+static inline u32 lynx_read(struct lynx_priv *priv, unsigned long off)
+{
+ void __iomem *reg = priv->base + off;
+
+ if (priv->big_endian)
+ return ioread32be(reg);
+
+ return ioread32(reg);
+}
+
+static inline void lynx_write(struct lynx_priv *priv, unsigned long off, u32 val)
+{
+ void __iomem *reg = priv->base + off;
+
+ if (priv->big_endian)
+ return iowrite32be(val, reg);
+
+ return iowrite32(val, reg);
+}
+
static inline void lynx_rmw(struct lynx_priv *priv, unsigned long off, u32 val,
u32 mask)
{
- void __iomem *reg = priv->base + off;
u32 orig, tmp;
- orig = ioread32(reg);
+ orig = lynx_read(priv, off);
tmp = orig & ~mask;
tmp |= val;
- iowrite32(tmp, reg);
+ lynx_write(priv, off, tmp);
}
-#define lynx_read(priv, off) \
- ioread32((priv)->base + (off))
-#define lynx_write(priv, off, val) \
- iowrite32(val, (priv)->base + (off))
#define lynx_lane_rmw(lane, reg, val, mask) \
lynx_rmw((lane)->priv, reg(lane->id), val, mask)
#define lynx_lane_read(lane, reg) \
- ioread32((lane)->priv->base + reg((lane)->id))
+ lynx_read((lane)->priv, reg((lane)->id))
#define lynx_lane_write(lane, reg, val) \
- iowrite32(val, (lane)->priv->base + reg((lane)->id))
+ lynx_write((lane)->priv, reg((lane)->id), val)
#define lynx_pll_read(pll, reg) \
- ioread32((pll)->priv->base + reg((pll)->id))
+ lynx_read((pll)->priv, reg((pll)->id))
int lynx_probe(struct platform_device *pdev, const struct lynx_info *info,
const struct phy_ops *phy_ops);
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox