linux-rockchip.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 0/4] Add Naneng combo PHY support for RK3568
@ 2021-12-30  8:48 Yifeng Zhao
  2021-12-30  8:48 ` [PATCH v7 1/4] dt-bindings: mfd: syscon: add naneng combo phy register compatible Yifeng Zhao
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Yifeng Zhao @ 2021-12-30  8:48 UTC (permalink / raw)
  To: heiko
  Cc: robh+dt, jbx6244, devicetree, vkoul, michael.riesch,
	linux-rockchip, linux-arm-kernel, linux-kernel, linux-phy,
	kishon, p.zabel, cl, kever.yang, lee.jones, wulf, Yifeng Zhao


This phy can be used as pcie-phy, usb3-phy, sata-phy or sgmii-phy.

Changes in v7:
- remove u3otg0_port_en, u3otg1_port_en and pipe_sgmii_mac_sel
- rename regs

Changes in v5:
- modify description for ssc and ext-refclk
- remove apb reset
- add rockchip_combphy_updatel()
- restyle

Changes in v4:
- restyle
- remove some minItems
- add more properties
- remove reset-names
- move #phy-cells
- add rockchip,rk3568-pipe-grf
- add rockchip,rk3568-pipe-phy-grf
- add devm_reset_control_array_get()
- remove clk structure
- change refclk DT parse
- change dev_err message
- add dot to phrase
- add ext_refclk variable
- add enable_ssc variable
- rename rockchip_combphy_param_write
- remove param_read
- replace rockchip-naneng-combphy driver name
- rename node name

Changes in v3:
- Using api devm_reset_control_get_optional_exclusive and dev_err_probe.
- Remove apb_rst.
- Redefine registers address.
- Move pipe_phy_grf0 to rk3568.dtsi

Changes in v2:
- Fix dtschema/dtc warnings/errors
- Using api devm_platform_get_and_ioremap_resource.
- Modify rockchip_combphy_set_Mode.
- Add some PHY registers definition.
- Move phy0 to rk3568.dtsi

Johan Jonker (1):
  dt-bindings: mfd: syscon: add naneng combo phy register compatible

Yifeng Zhao (3):
  dt-bindings: phy: rockchip: Add Naneng combo PHY bindings
  phy: rockchip: add naneng combo phy for RK3568
  arm64: dts: rockchip: add naneng combo phy nodes for rk3568

 .../devicetree/bindings/mfd/syscon.yaml       |   2 +
 .../phy/phy-rockchip-naneng-combphy.yaml      | 109 ++++
 arch/arm64/boot/dts/rockchip/rk3568.dtsi      |  21 +
 arch/arm64/boot/dts/rockchip/rk356x.dtsi      |  47 ++
 drivers/phy/rockchip/Kconfig                  |   8 +
 drivers/phy/rockchip/Makefile                 |   1 +
 .../rockchip/phy-rockchip-naneng-combphy.c    | 589 ++++++++++++++++++
 7 files changed, 777 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-rockchip-naneng-combphy.yaml
 create mode 100644 drivers/phy/rockchip/phy-rockchip-naneng-combphy.c

-- 
2.17.1




_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v7 1/4] dt-bindings: mfd: syscon: add naneng combo phy register compatible
  2021-12-30  8:48 [PATCH v7 0/4] Add Naneng combo PHY support for RK3568 Yifeng Zhao
@ 2021-12-30  8:48 ` Yifeng Zhao
  2021-12-31  0:12   ` Heiko Stübner
  2021-12-31  8:22   ` [PATCH v7] dt-bindings: soc: grf: " Johan Jonker
  2021-12-30  8:48 ` [PATCH v7 2/4] dt-bindings: phy: rockchip: Add Naneng combo PHY bindings Yifeng Zhao
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 12+ messages in thread
From: Yifeng Zhao @ 2021-12-30  8:48 UTC (permalink / raw)
  To: heiko
  Cc: robh+dt, jbx6244, devicetree, vkoul, michael.riesch,
	linux-rockchip, linux-arm-kernel, linux-kernel, linux-phy,
	kishon, p.zabel, cl, kever.yang, lee.jones, wulf, Yifeng Zhao

From: Johan Jonker <jbx6244@gmail.com>

Add naneng combo phy register compatible.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Johan Jonker <jbx6244@gmail.com>
Signed-off-by: Yifeng Zhao <yifeng.zhao@rock-chips.com>
---

Changes in v7: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index fdd96e378df0..e9bb96ab9446 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -52,6 +52,8 @@ properties:
               - rockchip,rk3288-qos
               - rockchip,rk3368-qos
               - rockchip,rk3399-qos
+              - rockchip,rk3568-pipe-grf
+              - rockchip,rk3568-pipe-phy-grf
               - rockchip,rk3568-qos
               - samsung,exynos3-sysreg
               - samsung,exynos4-sysreg
-- 
2.17.1




_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v7 2/4] dt-bindings: phy: rockchip: Add Naneng combo PHY bindings
  2021-12-30  8:48 [PATCH v7 0/4] Add Naneng combo PHY support for RK3568 Yifeng Zhao
  2021-12-30  8:48 ` [PATCH v7 1/4] dt-bindings: mfd: syscon: add naneng combo phy register compatible Yifeng Zhao
@ 2021-12-30  8:48 ` Yifeng Zhao
  2021-12-30  8:48 ` [PATCH v7 3/4] phy: rockchip: add naneng combo phy for RK3568 Yifeng Zhao
  2021-12-30  8:48 ` [PATCH v7 4/4] arm64: dts: rockchip: add naneng combo phy nodes for rk3568 Yifeng Zhao
  3 siblings, 0 replies; 12+ messages in thread
From: Yifeng Zhao @ 2021-12-30  8:48 UTC (permalink / raw)
  To: heiko
  Cc: robh+dt, jbx6244, devicetree, vkoul, michael.riesch,
	linux-rockchip, linux-arm-kernel, linux-kernel, linux-phy,
	kishon, p.zabel, cl, kever.yang, lee.jones, wulf, Yifeng Zhao

Add the compatible strings for the Naneng combo PHY found on rockchip SoC.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Yifeng Zhao <yifeng.zhao@rock-chips.com>
Signed-off-by: Johan Jonker <jbx6244@gmail.com>
---

Changes in v7:
- remove u3otg0_port_en, u3otg1_port_en and pipe_sgmii_mac_sel

Changes in v5:
- modify description for ssc and ext-refclk
- remove apb reset

Changes in v4:
- restyle
- remove some minItems
- add more properties
- remove reset-names
- move #phy-cells
- add rockchip,rk3568-pipe-grf
- add rockchip,rk3568-pipe-phy-grf

Changes in v3: None
Changes in v2:
- Fix dtschema/dtc warnings/errors

 .../phy/phy-rockchip-naneng-combphy.yaml      | 109 ++++++++++++++++++
 1 file changed, 109 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-rockchip-naneng-combphy.yaml

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-naneng-combphy.yaml b/Documentation/devicetree/bindings/phy/phy-rockchip-naneng-combphy.yaml
new file mode 100644
index 000000000000..f14454401419
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-naneng-combphy.yaml
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/phy-rockchip-naneng-combphy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip SoC Naneng Combo Phy Device Tree Bindings
+
+maintainers:
+  - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+  compatible:
+    enum:
+      - rockchip,rk3568-naneng-combphy
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: reference clock
+      - description: apb clock
+      - description: pipe clock
+
+  clock-names:
+    items:
+      - const: ref
+      - const: apb
+      - const: pipe
+
+  resets:
+    items:
+      - description: exclusive PHY reset line
+
+  rockchip,enable-ssc:
+    type: boolean
+    description:
+      The option SSC can be enabled for U3, SATA and PCIE.
+      Most commercially available platforms use SSC to reduce EMI.
+
+  rockchip,ext-refclk:
+    type: boolean
+    description:
+      Many PCIe connections, especially backplane connections,
+      require a synchronous reference clock between the two link partners.
+      To achieve this a common clock source, referred to as REFCLK in
+      the PCI Express Card Electromechanical Specification,
+      should be used by both ends of the PCIe link.
+      In PCIe mode one can choose to use an internal or an external reference
+      clock.
+      By default the internal clock is selected. The PCIe PHY provides a 100MHz
+      differential clock output(optional with SSC) for system applications.
+      When selecting this option an externally 100MHz differential
+      reference clock needs to be provided to the PCIe PHY.
+
+  rockchip,pipe-grf:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Some additional phy settings are accessed through GRF regs.
+
+  rockchip,pipe-phy-grf:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Some additional pipe settings are accessed through GRF regs.
+
+  "#phy-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - resets
+  - rockchip,pipe-grf
+  - rockchip,pipe-phy-grf
+  - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3568-cru.h>
+
+    pipegrf: syscon@fdc50000 {
+      compatible = "rockchip,rk3568-pipe-grf", "syscon";
+      reg = <0xfdc50000 0x1000>;
+    };
+
+    pipe_phy_grf0: syscon@fdc70000 {
+      compatible = "rockchip,rk3568-pipe-phy-grf", "syscon";
+      reg = <0xfdc70000 0x1000>;
+    };
+
+    combphy0: phy@fe820000 {
+      compatible = "rockchip,rk3568-naneng-combphy";
+      reg = <0xfe820000 0x100>;
+      clocks = <&pmucru CLK_PCIEPHY0_REF>,
+               <&cru PCLK_PIPEPHY0>,
+               <&cru PCLK_PIPE>;
+      clock-names = "ref", "apb", "pipe";
+      assigned-clocks = <&pmucru CLK_PCIEPHY0_REF>;
+      assigned-clock-rates = <100000000>;
+      resets = <&cru SRST_PIPEPHY0>;
+      rockchip,pipe-grf = <&pipegrf>;
+      rockchip,pipe-phy-grf = <&pipe_phy_grf0>;
+      #phy-cells = <1>;
+    };
-- 
2.17.1




_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v7 3/4] phy: rockchip: add naneng combo phy for RK3568
  2021-12-30  8:48 [PATCH v7 0/4] Add Naneng combo PHY support for RK3568 Yifeng Zhao
  2021-12-30  8:48 ` [PATCH v7 1/4] dt-bindings: mfd: syscon: add naneng combo phy register compatible Yifeng Zhao
  2021-12-30  8:48 ` [PATCH v7 2/4] dt-bindings: phy: rockchip: Add Naneng combo PHY bindings Yifeng Zhao
@ 2021-12-30  8:48 ` Yifeng Zhao
  2022-01-03 18:26   ` Johan Jonker
  2022-01-05 10:43   ` Philipp Zabel
  2021-12-30  8:48 ` [PATCH v7 4/4] arm64: dts: rockchip: add naneng combo phy nodes for rk3568 Yifeng Zhao
  3 siblings, 2 replies; 12+ messages in thread
From: Yifeng Zhao @ 2021-12-30  8:48 UTC (permalink / raw)
  To: heiko
  Cc: robh+dt, jbx6244, devicetree, vkoul, michael.riesch,
	linux-rockchip, linux-arm-kernel, linux-kernel, linux-phy,
	kishon, p.zabel, cl, kever.yang, lee.jones, wulf, Yifeng Zhao

This patch implements a combo phy driver for Rockchip SoCs
with NaNeng IP block. This phy can be used as pcie-phy, usb3-phy,
sata-phy or sgmii-phy.

Signed-off-by: Yifeng Zhao <yifeng.zhao@rock-chips.com>
Signed-off-by: Johan Jonker <jbx6244@gmail.com>
---

Changes in v7:
- rename regs
- remove pipe_sgmii_mac_sel, u3otg0_port_en and u3otg1_port_en

Changes in v5:
- add rockchip_combphy_updatel()
- restyle

Changes in v4:
- restyle
- add devm_reset_control_array_get()
- remove clk structure
- change refclk DT parse
- change dev_err message
- add dot to phrase
- add ext_refclk variable
- add enable_ssc variable
- rename rockchip_combphy_param_write
- remove param_read
- replace rockchip-naneng-combphy driver name

Changes in v3:
- Using api devm_reset_control_get_optional_exclusive and dev_err_probe.
- Remove apb_rst.
- Redefine registers address.

Changes in v2:
- Using api devm_platform_get_and_ioremap_resource.
- Modify rockchip_combphy_set_Mode.
- Add some PHY registers definition.

 drivers/phy/rockchip/Kconfig                  |   8 +
 drivers/phy/rockchip/Makefile                 |   1 +
 .../rockchip/phy-rockchip-naneng-combphy.c    | 589 ++++++++++++++++++
 3 files changed, 598 insertions(+)
 create mode 100644 drivers/phy/rockchip/phy-rockchip-naneng-combphy.c

diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index e812adad7242..9022e395c056 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -66,6 +66,14 @@ config PHY_ROCKCHIP_INNO_DSIDPHY
 	  Enable this to support the Rockchip MIPI/LVDS/TTL PHY with
 	  Innosilicon IP block.
 
+config PHY_ROCKCHIP_NANENG_COMBO_PHY
+	tristate "Rockchip NANENG COMBO PHY Driver"
+	depends on ARCH_ROCKCHIP && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the Rockchip PCIe/USB3.0/SATA/QSGMII
+	  combo PHY with NaNeng IP block.
+
 config PHY_ROCKCHIP_PCIE
 	tristate "Rockchip PCIe PHY Driver"
 	depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
index f0eec212b2aa..a5041efb5b8f 100644
--- a/drivers/phy/rockchip/Makefile
+++ b/drivers/phy/rockchip/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY)	+= phy-rockchip-inno-csidphy.o
 obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY)	+= phy-rockchip-inno-dsidphy.o
 obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI)	+= phy-rockchip-inno-hdmi.o
 obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2)	+= phy-rockchip-inno-usb2.o
+obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY)	+= phy-rockchip-naneng-combphy.o
 obj-$(CONFIG_PHY_ROCKCHIP_PCIE)		+= phy-rockchip-pcie.o
 obj-$(CONFIG_PHY_ROCKCHIP_TYPEC)	+= phy-rockchip-typec.o
 obj-$(CONFIG_PHY_ROCKCHIP_USB)		+= phy-rockchip-usb.o
diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
new file mode 100644
index 000000000000..47137a5c448a
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip PIPE USB3.0 PCIE SATA Combo Phy driver
+ *
+ * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/units.h>
+
+#define BIT_WRITEABLE_SHIFT		16
+#define REF_CLOCK_24MHz			(24 * HZ_PER_MHZ)
+#define REF_CLOCK_25MHz			(25 * HZ_PER_MHZ)
+#define REF_CLOCK_100MHz		(100 * HZ_PER_MHZ)
+
+/* COMBO PHY REG */
+#define PHYREG6				0x14
+#define PHYREG6_PLL_DIV_MASK		GENMASK(7, 6)
+#define PHYREG6_PLL_DIV_SHIFT		6
+#define PHYREG6_PLL_DIV_2		1
+
+#define PHYREG7				0x18
+#define PHYREG7_TX_RTERM_MASK		GENMASK(7, 4)
+#define PHYREG7_TX_RTERM_SHIFT		4
+#define PHYREG7_TX_RTERM_50OHM		8
+#define PHYREG7_RX_RTERM_MASK		GENMASK(3, 0)
+#define PHYREG7_RX_RTERM_SHIFT		0
+#define PHYREG7_RX_RTERM_44OHM		15
+
+#define PHYREG8				0x1C
+#define PHYREG8_SSC_EN			BIT(4)
+
+#define PHYREG11			0x28
+#define PHYREG11_SU_TRIM_0_7		0xF0
+
+#define PHYREG12			0x2C
+#define PHYREG12_PLL_LPF_ADJ_VALUE	4
+
+#define PHYREG13			0x30
+#define PHYREG13_RESISTER_MASK		GENMASK(5, 4)
+#define PHYREG13_RESISTER_SHIFT		0x4
+#define PHYREG13_RESISTER_HIGH_Z	3
+#define PHYREG13_CKRCV_AMP0		BIT(7)
+
+#define PHYREG14			0x34
+#define PHYREG14_CKRCV_AMP1		BIT(0)
+
+#define PHYREG15			0x38
+#define PHYREG15_CTLE_EN		BIT(0)
+#define PHYREG15_SSC_CNT_MASK		GENMASK(7, 6)
+#define PHYREG15_SSC_CNT_SHIFT		6
+#define PHYREG15_SSC_CNT_VALUE		1
+
+#define PHYREG16			0x3C
+#define PHYREG16_SSC_CNT_VALUE		0x5f
+
+#define PHYREG18			0x44
+#define PHYREG18_PLL_LOOP		0x32
+
+#define PHYREG32			0x7C
+#define PHYREG32_SSC_MASK		GENMASK(7, 4)
+#define PHYREG32_SSC_DIR_SHIFT		4
+#define PHYREG32_SSC_UPWARD		0
+#define PHYREG32_SSC_DOWNWARD		1
+#define PHYREG32_SSC_OFFSET_SHIFT	6
+#define PHYREG32_SSC_OFFSET_500PPM	1
+
+#define PHYREG33			0x80
+#define PHYREG33_PLL_KVCO_MASK		GENMASK(4, 2)
+#define PHYREG33_PLL_KVCO_SHIFT		2
+#define PHYREG33_PLL_KVCO_VALUE		2
+
+struct rockchip_combphy_priv;
+
+struct combphy_reg {
+	u16 offset;
+	u16 bitend;
+	u16 bitstart;
+	u16 disable;
+	u16 enable;
+};
+
+struct rockchip_combphy_grfcfg {
+	struct combphy_reg pcie_mode_set;
+	struct combphy_reg usb_mode_set;
+	struct combphy_reg sgmii_mode_set;
+	struct combphy_reg qsgmii_mode_set;
+	struct combphy_reg pipe_rxterm_set;
+	struct combphy_reg pipe_txelec_set;
+	struct combphy_reg pipe_txcomp_set;
+	struct combphy_reg pipe_clk_25m;
+	struct combphy_reg pipe_clk_100m;
+	struct combphy_reg pipe_phymode_sel;
+	struct combphy_reg pipe_rate_sel;
+	struct combphy_reg pipe_rxterm_sel;
+	struct combphy_reg pipe_txelec_sel;
+	struct combphy_reg pipe_txcomp_sel;
+	struct combphy_reg pipe_clk_ext;
+	struct combphy_reg pipe_sel_usb;
+	struct combphy_reg pipe_sel_qsgmii;
+	struct combphy_reg pipe_phy_status;
+	struct combphy_reg con0_for_pcie;
+	struct combphy_reg con1_for_pcie;
+	struct combphy_reg con2_for_pcie;
+	struct combphy_reg con3_for_pcie;
+	struct combphy_reg con0_for_sata;
+	struct combphy_reg con1_for_sata;
+	struct combphy_reg con2_for_sata;
+	struct combphy_reg con3_for_sata;
+	struct combphy_reg pipe_con0_for_sata;
+	struct combphy_reg pipe_xpcs_phy_ready;
+};
+
+struct rockchip_combphy_cfg {
+	const struct rockchip_combphy_grfcfg *grfcfg;
+	int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
+};
+
+struct rockchip_combphy_priv {
+	u8 mode;
+	void __iomem *mmio;
+	int num_clks;
+	struct clk_bulk_data *clks;
+	struct device *dev;
+	struct regmap *pipe_grf;
+	struct regmap *phy_grf;
+	struct phy *phy;
+	struct reset_control *phy_rst;
+	const struct rockchip_combphy_cfg *cfg;
+	bool enable_ssc;
+	bool ext_refclk;
+	struct clk *refclk;
+};
+
+static void rockchip_combphy_updatel(struct rockchip_combphy_priv *priv,
+				     int mask, int val, int reg)
+{
+	unsigned int temp;
+
+	temp = readl(priv->mmio + reg);
+	temp = (temp & ~(mask)) | val;
+	writel(temp, priv->mmio + reg);
+}
+
+static int rockchip_combphy_param_write(struct regmap *base,
+					const struct combphy_reg *reg, bool en)
+{
+	u32 val, mask, tmp;
+
+	tmp = en ? reg->enable : reg->disable;
+	mask = GENMASK(reg->bitend, reg->bitstart);
+	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
+
+	return regmap_write(base, reg->offset, val);
+}
+
+static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv)
+{
+	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
+	u32 mask, val;
+
+	mask = GENMASK(cfg->pipe_phy_status.bitend,
+		       cfg->pipe_phy_status.bitstart);
+
+	regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val);
+	val = (val & mask) >> cfg->pipe_phy_status.bitstart;
+
+	return val;
+}
+
+static int rockchip_combphy_set_mode(struct rockchip_combphy_priv *priv)
+{
+	int ret = 0;
+
+	switch (priv->mode) {
+	case PHY_TYPE_PCIE:
+	case PHY_TYPE_USB3:
+	case PHY_TYPE_SATA:
+	case PHY_TYPE_SGMII:
+	case PHY_TYPE_QSGMII:
+		if (priv->cfg->combphy_cfg)
+			ret = priv->cfg->combphy_cfg(priv);
+		break;
+	default:
+		dev_err(priv->dev, "incompatible PHY type\n");
+		return -EINVAL;
+	}
+
+	if (ret)
+		dev_err(priv->dev, "failed to init phy for phy mode %x\n", priv->mode);
+
+	return ret;
+}
+
+static int rockchip_combphy_init(struct phy *phy)
+{
+	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
+	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
+	u32 val;
+	int ret;
+
+	ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
+	if (ret) {
+		dev_err(priv->dev, "failed to enable clks\n");
+		return ret;
+	}
+
+	ret = rockchip_combphy_set_mode(priv);
+	if (ret)
+		goto err_clk;
+
+	ret = reset_control_deassert(priv->phy_rst);
+	if (ret)
+		goto err_clk;
+
+	if (priv->mode == PHY_TYPE_USB3) {
+		ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready,
+						priv, val,
+						val == cfg->pipe_phy_status.enable,
+						10, 1000);
+		if (ret)
+			dev_warn(priv->dev, "wait phy status ready timeout\n");
+	}
+
+	return 0;
+
+err_clk:
+	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
+
+	return ret;
+}
+
+static int rockchip_combphy_exit(struct phy *phy)
+{
+	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
+
+	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
+	reset_control_assert(priv->phy_rst);
+
+	return 0;
+}
+
+static const struct phy_ops rochchip_combphy_ops = {
+	.init = rockchip_combphy_init,
+	.exit = rockchip_combphy_exit,
+	.owner = THIS_MODULE,
+};
+
+static struct phy *rockchip_combphy_xlate(struct device *dev, struct of_phandle_args *args)
+{
+	struct rockchip_combphy_priv *priv = dev_get_drvdata(dev);
+
+	if (args->args_count != 1) {
+		dev_err(dev, "invalid number of arguments\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (priv->mode != PHY_NONE && priv->mode != args->args[0])
+		dev_warn(dev, "phy type select %d overwriting type %d\n",
+			 args->args[0], priv->mode);
+
+	priv->mode = args->args[0];
+
+	return priv->phy;
+}
+
+static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv)
+{
+	int i;
+
+	priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
+	if (priv->num_clks < 1)
+		return -EINVAL;
+
+	priv->refclk = NULL;
+	for (i = 0; i < priv->num_clks; i++) {
+		if (!strncmp(priv->clks[i].id, "ref", 3)) {
+			priv->refclk = priv->clks[i].clk;
+			break;
+		}
+	}
+
+	if (!priv->refclk) {
+		dev_err(dev, "no refclk found\n");
+		return -EINVAL;
+	}
+
+	priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-grf");
+	if (IS_ERR(priv->pipe_grf)) {
+		dev_err(dev, "failed to find peri_ctrl pipe-grf regmap\n");
+		return PTR_ERR(priv->pipe_grf);
+	}
+
+	priv->phy_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-phy-grf");
+	if (IS_ERR(priv->phy_grf)) {
+		dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n");
+		return PTR_ERR(priv->phy_grf);
+	}
+
+	priv->enable_ssc = device_property_present(dev, "rockchip,enable-ssc");
+
+	priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk");
+
+	priv->phy_rst = devm_reset_control_array_get(dev, false, false);
+	if (IS_ERR(priv->phy_rst))
+		return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n");
+
+	return 0;
+}
+
+static int rockchip_combphy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct rockchip_combphy_priv *priv;
+	const struct rockchip_combphy_cfg *phy_cfg;
+	struct resource *res;
+	int ret;
+
+	phy_cfg = of_device_get_match_data(dev);
+	if (!phy_cfg) {
+		dev_err(dev, "no OF match data provided\n");
+		return -EINVAL;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+	if (IS_ERR(priv->mmio)) {
+		ret = PTR_ERR(priv->mmio);
+		return ret;
+	}
+
+	priv->dev = dev;
+	priv->mode = PHY_NONE;
+	priv->cfg = phy_cfg;
+
+	ret = rockchip_combphy_parse_dt(dev, priv);
+	if (ret)
+		return ret;
+
+	ret = reset_control_assert(priv->phy_rst);
+	if (ret) {
+		dev_err(dev, "failed to reset phy\n");
+		return ret;
+	}
+
+	priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops);
+	if (IS_ERR(priv->phy)) {
+		dev_err(dev, "failed to create combphy\n");
+		return PTR_ERR(priv->phy);
+	}
+
+	dev_set_drvdata(dev, priv);
+	phy_set_drvdata(priv->phy, priv);
+
+	phy_provider = devm_of_phy_provider_register(dev, rockchip_combphy_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv)
+{
+	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
+	unsigned long rate;
+	u32 val;
+
+	switch (priv->mode) {
+	case PHY_TYPE_PCIE:
+		/* Set SSC downward spread spectrum. */
+		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
+					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
+					 PHYREG32);
+
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
+		break;
+
+	case PHY_TYPE_USB3:
+		/* Set SSC downward spread spectrum. */
+		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
+					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
+					 PHYREG32);
+
+		/* Enable adaptive CTLE for USB3.0 Rx. */
+		val = readl(priv->mmio + PHYREG15);
+		val |= PHYREG15_CTLE_EN;
+		writel(val, priv->mmio + PHYREG15);
+
+		/* Set PLL KVCO fine tuning signals. */
+		rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
+					 PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT,
+					 PHYREG33);
+
+		/* Enable controlling random jitter. */
+		writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
+
+		/* Set PLL input clock divider 1/2. */
+		rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
+					 PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT,
+					 PHYREG6);
+
+		writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
+		writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
+
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);
+		break;
+
+	case PHY_TYPE_SATA:
+		/* Enable adaptive CTLE for SATA Rx. */
+		val = readl(priv->mmio + PHYREG15);
+		val |= PHYREG15_CTLE_EN;
+		writel(val, priv->mmio + PHYREG15);
+		/*
+		 * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA.
+		 * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm)
+		 */
+		val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;
+		val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;
+		writel(val, priv->mmio + PHYREG7);
+
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);
+		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
+		break;
+
+	case PHY_TYPE_SGMII:
+		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->sgmii_mode_set, true);
+		break;
+
+	case PHY_TYPE_QSGMII:
+		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_rate_sel, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true);
+		break;
+
+	default:
+		dev_err(priv->dev, "incompatible PHY type\n");
+		return -EINVAL;
+	}
+
+	rate = clk_get_rate(priv->refclk);
+
+	switch (rate) {
+	case REF_CLOCK_24MHz:
+		if (priv->mode == PHY_TYPE_USB3 || priv->mode == PHY_TYPE_SATA) {
+			/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */
+			val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT;
+			rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,
+						 val, PHYREG15);
+
+			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
+		}
+		break;
+
+	case REF_CLOCK_25MHz:
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
+		break;
+
+	case REF_CLOCK_100MHz:
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
+		if (priv->mode == PHY_TYPE_PCIE) {
+			/* PLL KVCO  fine tuning. */
+			val = PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT;
+			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
+						 val, PHYREG33);
+
+			/* Enable controlling random jitter. */
+			writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
+
+			val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT;
+			rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
+						 val, PHYREG6);
+
+			writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
+			writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
+		} else if (priv->mode == PHY_TYPE_SATA) {
+			/* downward spread spectrum +500ppm */
+			val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT;
+			val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT;
+			rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
+		}
+		break;
+
+	default:
+		dev_err(priv->dev, "unsupported rate: %lu\n", rate);
+		return -EINVAL;
+	}
+
+	if (priv->ext_refclk) {
+		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
+		if (priv->mode == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {
+			val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT;
+			val |= PHYREG13_CKRCV_AMP0;
+			rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13);
+
+			val = readl(priv->mmio + PHYREG14);
+			val |= PHYREG14_CKRCV_AMP1;
+			writel(val, priv->mmio + PHYREG14);
+		}
+	}
+
+	if (priv->enable_ssc) {
+		val = readl(priv->mmio + PHYREG8);
+		val |= PHYREG8_SSC_EN;
+		writel(val, priv->mmio + PHYREG8);
+	}
+
+	return 0;
+}
+
+static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
+	/* pipe-phy-grf */
+	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
+	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
+	.sgmii_mode_set		= { 0x0000, 5, 0, 0x00, 0x01 },
+	.qsgmii_mode_set	= { 0x0000, 5, 0, 0x00, 0x21 },
+	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
+	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
+	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
+	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
+	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
+	.pipe_phymode_sel	= { 0x0008, 1, 1, 0x00, 0x01 },
+	.pipe_rate_sel		= { 0x0008, 2, 2, 0x00, 0x01 },
+	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
+	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
+	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
+	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
+	.pipe_sel_usb		= { 0x000c, 14, 13, 0x00, 0x01 },
+	.pipe_sel_qsgmii	= { 0x000c, 15, 13, 0x00, 0x07 },
+	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
+	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
+	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
+	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
+	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
+	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0119 },
+	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0040 },
+	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c3 },
+	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x4407 },
+	/* pipe-grf */
+	.pipe_con0_for_sata	= { 0x0000, 15, 0, 0x00, 0x2220 },
+	.pipe_xpcs_phy_ready	= { 0x0040, 2, 2, 0x00, 0x01 },
+};
+
+static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
+	.grfcfg		= &rk3568_combphy_grfcfgs,
+	.combphy_cfg	= rk3568_combphy_cfg,
+};
+
+static const struct of_device_id rockchip_combphy_of_match[] = {
+	{
+		.compatible = "rockchip,rk3568-naneng-combphy",
+		.data = &rk3568_combphy_cfgs,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match);
+
+static struct platform_driver rockchip_combphy_driver = {
+	.probe	= rockchip_combphy_probe,
+	.driver = {
+		.name = "rockchip-naneng-combphy",
+		.of_match_table = rockchip_combphy_of_match,
+	},
+};
+module_platform_driver(rockchip_combphy_driver);
+
+MODULE_DESCRIPTION("Rockchip NANENG COMBPHY driver");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1




_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v7 4/4] arm64: dts: rockchip: add naneng combo phy nodes for rk3568
  2021-12-30  8:48 [PATCH v7 0/4] Add Naneng combo PHY support for RK3568 Yifeng Zhao
                   ` (2 preceding siblings ...)
  2021-12-30  8:48 ` [PATCH v7 3/4] phy: rockchip: add naneng combo phy for RK3568 Yifeng Zhao
@ 2021-12-30  8:48 ` Yifeng Zhao
  3 siblings, 0 replies; 12+ messages in thread
From: Yifeng Zhao @ 2021-12-30  8:48 UTC (permalink / raw)
  To: heiko
  Cc: robh+dt, jbx6244, devicetree, vkoul, michael.riesch,
	linux-rockchip, linux-arm-kernel, linux-kernel, linux-phy,
	kishon, p.zabel, cl, kever.yang, lee.jones, wulf, Yifeng Zhao

Add the core dt-node for the rk3568's naneng combo phys.

Signed-off-by: Yifeng Zhao <yifeng.zhao@rock-chips.com>
Signed-off-by: Johan Jonker <jbx6244@gmail.com>
---

Changes in v7: None
Changes in v5:
- remove apb reset

Changes in v4:
- rename node name
- remove reset-names
- move #phy-cells
- add rockchip,rk3568-pipe-grf
- add rockchip,rk3568-pipe-phy-grf

Changes in v3:
- Move pipe_phy_grf0 to rk3568.dtsi

Changes in v2:
- Move phy0 to rk3568.dtsi

 arch/arm64/boot/dts/rockchip/rk3568.dtsi | 21 +++++++++++
 arch/arm64/boot/dts/rockchip/rk356x.dtsi | 47 ++++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
index 2fd313a295f8..91a0b798b857 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
@@ -8,6 +8,11 @@
 / {
 	compatible = "rockchip,rk3568";
 
+	pipe_phy_grf0: syscon@fdc70000 {
+		compatible = "rockchip,rk3568-pipe-phy-grf", "syscon";
+		reg = <0x0 0xfdc70000 0x0 0x1000>;
+	};
+
 	qos_pcie3x1: qos@fe190080 {
 		compatible = "rockchip,rk3568-qos", "syscon";
 		reg = <0x0 0xfe190080 0x0 0x20>;
@@ -71,6 +76,22 @@
 			queue0 {};
 		};
 	};
+
+	combphy0: phy@fe820000 {
+		compatible = "rockchip,rk3568-naneng-combphy";
+		reg = <0x0 0xfe820000 0x0 0x100>;
+		clocks = <&pmucru CLK_PCIEPHY0_REF>,
+			 <&cru PCLK_PIPEPHY0>,
+			 <&cru PCLK_PIPE>;
+		clock-names = "ref", "apb", "pipe";
+		assigned-clocks = <&pmucru CLK_PCIEPHY0_REF>;
+		assigned-clock-rates = <100000000>;
+		resets = <&cru SRST_PIPEPHY0>;
+		rockchip,pipe-grf = <&pipegrf>;
+		rockchip,pipe-phy-grf = <&pipe_phy_grf0>;
+		#phy-cells = <1>;
+		status = "disabled";
+	};
 };
 
 &cpu0_opp_table {
diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index a68033a23975..93f230f799f1 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -218,11 +218,26 @@
 		};
 	};
 
+	pipegrf: syscon@fdc50000 {
+		compatible = "rockchip,rk3568-pipe-grf", "syscon";
+		reg = <0x0 0xfdc50000 0x0 0x1000>;
+	};
+
 	grf: syscon@fdc60000 {
 		compatible = "rockchip,rk3568-grf", "syscon", "simple-mfd";
 		reg = <0x0 0xfdc60000 0x0 0x10000>;
 	};
 
+	pipe_phy_grf1: syscon@fdc80000 {
+		compatible = "rockchip,rk3568-pipe-phy-grf", "syscon";
+		reg = <0x0 0xfdc80000 0x0 0x1000>;
+	};
+
+	pipe_phy_grf2: syscon@fdc90000 {
+		compatible = "rockchip,rk3568-pipe-phy-grf", "syscon";
+		reg = <0x0 0xfdc90000 0x0 0x1000>;
+	};
+
 	pmucru: clock-controller@fdd00000 {
 		compatible = "rockchip,rk3568-pmucru";
 		reg = <0x0 0xfdd00000 0x0 0x1000>;
@@ -1141,6 +1156,38 @@
 		status = "disabled";
 	};
 
+	combphy1: phy@fe830000 {
+		compatible = "rockchip,rk3568-naneng-combphy";
+		reg = <0x0 0xfe830000 0x0 0x100>;
+		clocks = <&pmucru CLK_PCIEPHY1_REF>,
+			 <&cru PCLK_PIPEPHY1>,
+			 <&cru PCLK_PIPE>;
+		clock-names = "ref", "apb", "pipe";
+		assigned-clocks = <&pmucru CLK_PCIEPHY1_REF>;
+		assigned-clock-rates = <100000000>;
+		resets = <&cru SRST_PIPEPHY1>;
+		rockchip,pipe-grf = <&pipegrf>;
+		rockchip,pipe-phy-grf = <&pipe_phy_grf1>;
+		#phy-cells = <1>;
+		status = "disabled";
+	};
+
+	combphy2: phy@fe840000 {
+		compatible = "rockchip,rk3568-naneng-combphy";
+		reg = <0x0 0xfe840000 0x0 0x100>;
+		clocks = <&pmucru CLK_PCIEPHY2_REF>,
+			 <&cru PCLK_PIPEPHY2>,
+			 <&cru PCLK_PIPE>;
+		clock-names = "ref", "apb", "pipe";
+		assigned-clocks = <&pmucru CLK_PCIEPHY2_REF>;
+		assigned-clock-rates = <100000000>;
+		resets = <&cru SRST_PIPEPHY2>;
+		rockchip,pipe-grf = <&pipegrf>;
+		rockchip,pipe-phy-grf = <&pipe_phy_grf2>;
+		#phy-cells = <1>;
+		status = "disabled";
+	};
+
 	pinctrl: pinctrl {
 		compatible = "rockchip,rk3568-pinctrl";
 		rockchip,grf = <&grf>;
-- 
2.17.1




_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v7 1/4] dt-bindings: mfd: syscon: add naneng combo phy register compatible
  2021-12-30  8:48 ` [PATCH v7 1/4] dt-bindings: mfd: syscon: add naneng combo phy register compatible Yifeng Zhao
@ 2021-12-31  0:12   ` Heiko Stübner
  2021-12-31  8:22   ` [PATCH v7] dt-bindings: soc: grf: " Johan Jonker
  1 sibling, 0 replies; 12+ messages in thread
From: Heiko Stübner @ 2021-12-31  0:12 UTC (permalink / raw)
  To: Yifeng Zhao
  Cc: robh+dt, jbx6244, devicetree, vkoul, michael.riesch,
	linux-rockchip, linux-arm-kernel, linux-kernel, linux-phy,
	kishon, p.zabel, cl, kever.yang, lee.jones, wulf, Yifeng Zhao

Hi Yifeng,

Am Donnerstag, 30. Dezember 2021, 09:48:12 CET schrieb Yifeng Zhao:
> From: Johan Jonker <jbx6244@gmail.com>
> 
> Add naneng combo phy register compatible.
> 
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Johan Jonker <jbx6244@gmail.com>
> Signed-off-by: Yifeng Zhao <yifeng.zhao@rock-chips.com>
> ---
> 
> Changes in v7: None
> Changes in v5: None
> Changes in v4: None
> Changes in v3: None
> Changes in v2: None
> 
>  Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
> index fdd96e378df0..e9bb96ab9446 100644
> --- a/Documentation/devicetree/bindings/mfd/syscon.yaml
> +++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
> @@ -52,6 +52,8 @@ properties:
>                - rockchip,rk3288-qos
>                - rockchip,rk3368-qos
>                - rockchip,rk3399-qos
> +              - rockchip,rk3568-pipe-grf
> +              - rockchip,rk3568-pipe-phy-grf

can you please move these to the grf.yaml as discussed in the previous
version.

Background is of course to keep all *-grf compatibles in the same file.

Thanks
Heiko


>                - rockchip,rk3568-qos
>                - samsung,exynos3-sysreg
>                - samsung,exynos4-sysreg
> 





_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v7] dt-bindings: soc: grf: add naneng combo phy register compatible
  2021-12-30  8:48 ` [PATCH v7 1/4] dt-bindings: mfd: syscon: add naneng combo phy register compatible Yifeng Zhao
  2021-12-31  0:12   ` Heiko Stübner
@ 2021-12-31  8:22   ` Johan Jonker
  2022-01-10 20:40     ` Rob Herring
  1 sibling, 1 reply; 12+ messages in thread
From: Johan Jonker @ 2021-12-31  8:22 UTC (permalink / raw)
  To: heiko, yifeng.zhao
  Cc: robh+dt, vkoul, kishon, p.zabel, michael.riesch, kever.yang, cl,
	wulf, linux-phy, devicetree, linux-rockchip, linux-arm-kernel,
	linux-kernel

Add Naneng combo phy register compatible.

Signed-off-by: Johan Jonker <jbx6244@gmail.com>
---
 Documentation/devicetree/bindings/soc/rockchip/grf.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
index b2ba7bed8..5079e9d24 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
+++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
@@ -15,6 +15,8 @@ properties:
       - items:
           - enum:
               - rockchip,rk3288-sgrf
+              - rockchip,rk3568-pipe-grf
+              - rockchip,rk3568-pipe-phy-grf
               - rockchip,rk3568-usb2phy-grf
               - rockchip,rv1108-usbgrf
           - const: syscon
-- 
2.20.1


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v7 3/4] phy: rockchip: add naneng combo phy for RK3568
  2021-12-30  8:48 ` [PATCH v7 3/4] phy: rockchip: add naneng combo phy for RK3568 Yifeng Zhao
@ 2022-01-03 18:26   ` Johan Jonker
  2022-02-04 12:17     ` Johan Jonker
  2022-02-08 10:22     ` zyf
  2022-01-05 10:43   ` Philipp Zabel
  1 sibling, 2 replies; 12+ messages in thread
From: Johan Jonker @ 2022-01-03 18:26 UTC (permalink / raw)
  To: Yifeng Zhao, heiko
  Cc: robh+dt, devicetree, vkoul, michael.riesch, linux-rockchip,
	linux-arm-kernel, linux-kernel, linux-phy, kishon, p.zabel, cl,
	kever.yang, lee.jones, wulf, Frank Wunderlich

Hi Yifeng, Kishon, rob+dt,

Some comments, have a look if it's useful.

====

Could the DT and phy maintainer advise the correct/right driver
structure to Yifeng, so that we can move forward!

====

This driver still follows the wrong approach.
Things used in the manufacturer tree are not necessary future proof in a
mainline kernel.
In order to switch SGMII input between lane1 and lanes2 phy structures
it is needed that there is a parent node.

Could you look at combo phy example:

https://elixir.bootlin.com/linux/latest/source/drivers/phy/marvell/phy-mvebu-a3700-comphy.c

To prevent accidents with a DT from the manefucturer tree and mainline
use a differnet compatible string for each SoC.

See version 6:
Use for_each_available_child_of_node to find all available subnodes.

Make for each SoC a structure with supported features.

Make better use of the phy frame work ops  (setmode, poweron).

====
Use enum phy_mode instead of PHY_TYPE.

PHY_TYPE are used in DT.
phy_mode are used in struct phy *phy
====

Example to generate the capabilities structure:
static const struct rk3568_multiphy_conf rk3568_multiphy_modes[] = {
	/* lane 0 */
	RK3568_MULTI_CONF_GEN(0, PHY_MODE_SATA, 0,
				    MULTI_FW_MODE_SATA),
	RK3568_MULTI_CONF_GEN(0, PHY_MODE_USB_HOST_SS, 0,
				    MULTI_FW_MODE_USB3H),
	/* lane 1 */
	RK3568_MULTI_CONF_GEN(1, PHY_MODE_SATA, 0,
				    MULTI_FW_MODE_SATA),
	RK3568_MULTI_CONF_GEN(1, PHY_MODE_USB_HOST_SS, 0,
				    MULTI_FW_MODE_USB3H),
	RK3568_MULTI_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, 0,
				    MULTI_FW_MODE_SGMII),
	/* lane 2 */
	RK3568_MULTI_CONF_GEN(2, PHY_MODE_SATA, 0,
				    MULTI_FW_MODE_SATA),
	RK3568_MULTI_CONF_ETH(2, PHY_INTERFACE_MODE_SGMII, 1,
				    MULTI_FW_MODE_SGMII),
	RK3568_MULTI_CONF_GEN(2, PHY_MODE_PCIE, 0,
				    MULTI_FW_MODE_PCIE),
};

On 12/30/21 9:48 AM, Yifeng Zhao wrote:
> This patch implements a combo phy driver for Rockchip SoCs
> with NaNeng IP block. This phy can be used as pcie-phy, usb3-phy,
> sata-phy or sgmii-phy.
> 
> Signed-off-by: Yifeng Zhao <yifeng.zhao@rock-chips.com>
> Signed-off-by: Johan Jonker <jbx6244@gmail.com>
> ---
> 
> Changes in v7:
> - rename regs
> - remove pipe_sgmii_mac_sel, u3otg0_port_en and u3otg1_port_en
> 
> Changes in v5:
> - add rockchip_combphy_updatel()
> - restyle
> 
> Changes in v4:
> - restyle
> - add devm_reset_control_array_get()
> - remove clk structure
> - change refclk DT parse
> - change dev_err message
> - add dot to phrase
> - add ext_refclk variable
> - add enable_ssc variable
> - rename rockchip_combphy_param_write
> - remove param_read
> - replace rockchip-naneng-combphy driver name
> 
> Changes in v3:
> - Using api devm_reset_control_get_optional_exclusive and dev_err_probe.
> - Remove apb_rst.
> - Redefine registers address.
> 
> Changes in v2:
> - Using api devm_platform_get_and_ioremap_resource.
> - Modify rockchip_combphy_set_Mode.
> - Add some PHY registers definition.
> 
>  drivers/phy/rockchip/Kconfig                  |   8 +
>  drivers/phy/rockchip/Makefile                 |   1 +
>  .../rockchip/phy-rockchip-naneng-combphy.c    | 589 ++++++++++++++++++
>  3 files changed, 598 insertions(+)
>  create mode 100644 drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
> 
> diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
> index e812adad7242..9022e395c056 100644
> --- a/drivers/phy/rockchip/Kconfig
> +++ b/drivers/phy/rockchip/Kconfig
> @@ -66,6 +66,14 @@ config PHY_ROCKCHIP_INNO_DSIDPHY
>  	  Enable this to support the Rockchip MIPI/LVDS/TTL PHY with
>  	  Innosilicon IP block.
>  
> +config PHY_ROCKCHIP_NANENG_COMBO_PHY
> +	tristate "Rockchip NANENG COMBO PHY Driver"
> +	depends on ARCH_ROCKCHIP && OF
> +	select GENERIC_PHY
> +	help
> +	  Enable this to support the Rockchip PCIe/USB3.0/SATA/QSGMII
> +	  combo PHY with NaNeng IP block.
> +
>  config PHY_ROCKCHIP_PCIE
>  	tristate "Rockchip PCIe PHY Driver"
>  	depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
> diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
> index f0eec212b2aa..a5041efb5b8f 100644
> --- a/drivers/phy/rockchip/Makefile
> +++ b/drivers/phy/rockchip/Makefile
> @@ -6,6 +6,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY)	+= phy-rockchip-inno-csidphy.o
>  obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY)	+= phy-rockchip-inno-dsidphy.o
>  obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI)	+= phy-rockchip-inno-hdmi.o
>  obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2)	+= phy-rockchip-inno-usb2.o
> +obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY)	+= phy-rockchip-naneng-combphy.o
>  obj-$(CONFIG_PHY_ROCKCHIP_PCIE)		+= phy-rockchip-pcie.o
>  obj-$(CONFIG_PHY_ROCKCHIP_TYPEC)	+= phy-rockchip-typec.o
>  obj-$(CONFIG_PHY_ROCKCHIP_USB)		+= phy-rockchip-usb.o
> diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
> new file mode 100644
> index 000000000000..47137a5c448a
> --- /dev/null
> +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
> @@ -0,0 +1,589 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Rockchip PIPE USB3.0 PCIE SATA Combo Phy driver
> + *
> + * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
> + */
> +
> +#include <dt-bindings/phy/phy.h>
> +#include <linux/clk.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of_device.h>
> +#include <linux/phy/phy.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +#include <linux/units.h>
> +
> +#define BIT_WRITEABLE_SHIFT		16
> +#define REF_CLOCK_24MHz			(24 * HZ_PER_MHZ)
> +#define REF_CLOCK_25MHz			(25 * HZ_PER_MHZ)
> +#define REF_CLOCK_100MHz		(100 * HZ_PER_MHZ)
> +
> +/* COMBO PHY REG */
> +#define PHYREG6				0x14
> +#define PHYREG6_PLL_DIV_MASK		GENMASK(7, 6)
> +#define PHYREG6_PLL_DIV_SHIFT		6
> +#define PHYREG6_PLL_DIV_2		1
> +
> +#define PHYREG7				0x18
> +#define PHYREG7_TX_RTERM_MASK		GENMASK(7, 4)
> +#define PHYREG7_TX_RTERM_SHIFT		4
> +#define PHYREG7_TX_RTERM_50OHM		8
> +#define PHYREG7_RX_RTERM_MASK		GENMASK(3, 0)
> +#define PHYREG7_RX_RTERM_SHIFT		0
> +#define PHYREG7_RX_RTERM_44OHM		15
> +
> +#define PHYREG8				0x1C
> +#define PHYREG8_SSC_EN			BIT(4)
> +
> +#define PHYREG11			0x28
> +#define PHYREG11_SU_TRIM_0_7		0xF0
> +
> +#define PHYREG12			0x2C
> +#define PHYREG12_PLL_LPF_ADJ_VALUE	4
> +
> +#define PHYREG13			0x30
> +#define PHYREG13_RESISTER_MASK		GENMASK(5, 4)
> +#define PHYREG13_RESISTER_SHIFT		0x4
> +#define PHYREG13_RESISTER_HIGH_Z	3
> +#define PHYREG13_CKRCV_AMP0		BIT(7)
> +
> +#define PHYREG14			0x34
> +#define PHYREG14_CKRCV_AMP1		BIT(0)
> +
> +#define PHYREG15			0x38
> +#define PHYREG15_CTLE_EN		BIT(0)
> +#define PHYREG15_SSC_CNT_MASK		GENMASK(7, 6)
> +#define PHYREG15_SSC_CNT_SHIFT		6
> +#define PHYREG15_SSC_CNT_VALUE		1
> +
> +#define PHYREG16			0x3C
> +#define PHYREG16_SSC_CNT_VALUE		0x5f
> +
> +#define PHYREG18			0x44
> +#define PHYREG18_PLL_LOOP		0x32
> +
> +#define PHYREG32			0x7C
> +#define PHYREG32_SSC_MASK		GENMASK(7, 4)
> +#define PHYREG32_SSC_DIR_SHIFT		4
> +#define PHYREG32_SSC_UPWARD		0
> +#define PHYREG32_SSC_DOWNWARD		1
> +#define PHYREG32_SSC_OFFSET_SHIFT	6
> +#define PHYREG32_SSC_OFFSET_500PPM	1
> +
> +#define PHYREG33			0x80
> +#define PHYREG33_PLL_KVCO_MASK		GENMASK(4, 2)
> +#define PHYREG33_PLL_KVCO_SHIFT		2
> +#define PHYREG33_PLL_KVCO_VALUE		2
> +
> +struct rockchip_combphy_priv;
> +
> +struct combphy_reg {
> +	u16 offset;
> +	u16 bitend;
> +	u16 bitstart;
> +	u16 disable;
> +	u16 enable;
> +};
> +
> +struct rockchip_combphy_grfcfg {
> +	struct combphy_reg pcie_mode_set;
> +	struct combphy_reg usb_mode_set;
> +	struct combphy_reg sgmii_mode_set;
> +	struct combphy_reg qsgmii_mode_set;
> +	struct combphy_reg pipe_rxterm_set;
> +	struct combphy_reg pipe_txelec_set;
> +	struct combphy_reg pipe_txcomp_set;
> +	struct combphy_reg pipe_clk_25m;
> +	struct combphy_reg pipe_clk_100m;
> +	struct combphy_reg pipe_phymode_sel;
> +	struct combphy_reg pipe_rate_sel;
> +	struct combphy_reg pipe_rxterm_sel;
> +	struct combphy_reg pipe_txelec_sel;
> +	struct combphy_reg pipe_txcomp_sel;
> +	struct combphy_reg pipe_clk_ext;
> +	struct combphy_reg pipe_sel_usb;
> +	struct combphy_reg pipe_sel_qsgmii;
> +	struct combphy_reg pipe_phy_status;
> +	struct combphy_reg con0_for_pcie;
> +	struct combphy_reg con1_for_pcie;
> +	struct combphy_reg con2_for_pcie;
> +	struct combphy_reg con3_for_pcie;
> +	struct combphy_reg con0_for_sata;
> +	struct combphy_reg con1_for_sata;
> +	struct combphy_reg con2_for_sata;
> +	struct combphy_reg con3_for_sata;
> +	struct combphy_reg pipe_con0_for_sata;
> +	struct combphy_reg pipe_xpcs_phy_ready;
> +};
> +
> +struct rockchip_combphy_cfg {
> +	const struct rockchip_combphy_grfcfg *grfcfg;
> +	int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
> +};
> +
> +struct rockchip_combphy_priv {
> +	u8 mode;
> +	void __iomem *mmio;
> +	int num_clks;
> +	struct clk_bulk_data *clks;
> +	struct device *dev;
> +	struct regmap *pipe_grf;
> +	struct regmap *phy_grf;
> +	struct phy *phy;
> +	struct reset_control *phy_rst;
> +	const struct rockchip_combphy_cfg *cfg;
> +	bool enable_ssc;
> +	bool ext_refclk;
> +	struct clk *refclk;
> +};
> +
> +static void rockchip_combphy_updatel(struct rockchip_combphy_priv *priv,
> +				     int mask, int val, int reg)
> +{
> +	unsigned int temp;
> +
> +	temp = readl(priv->mmio + reg);
> +	temp = (temp & ~(mask)) | val;
> +	writel(temp, priv->mmio + reg);
> +}
> +
> +static int rockchip_combphy_param_write(struct regmap *base,
> +					const struct combphy_reg *reg, bool en)
> +{
> +	u32 val, mask, tmp;
> +
> +	tmp = en ? reg->enable : reg->disable;
> +	mask = GENMASK(reg->bitend, reg->bitstart);
> +	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
> +
> +	return regmap_write(base, reg->offset, val);
> +}
> +
> +static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv)
> +{
> +	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
> +	u32 mask, val;
> +
> +	mask = GENMASK(cfg->pipe_phy_status.bitend,
> +		       cfg->pipe_phy_status.bitstart);
> +
> +	regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val);
> +	val = (val & mask) >> cfg->pipe_phy_status.bitstart;
> +
> +	return val;
> +}
> +

> +static int rockchip_combphy_set_mode(struct rockchip_combphy_priv *priv)

static int rockchip_combphy_set_mode(struct phy *phy, enum phy_mode
mode, int submode)

	/* Use this function to remember the mode, ->power_on() will do the
real setup */

> +{
> +	int ret = 0;
> +
> +	switch (priv->mode) {
> +	case PHY_TYPE_PCIE:
> +	case PHY_TYPE_USB3:
> +	case PHY_TYPE_SATA:
> +	case PHY_TYPE_SGMII:
> +	case PHY_TYPE_QSGMII:
> +		if (priv->cfg->combphy_cfg)
> +			ret = priv->cfg->combphy_cfg(priv);
> +		break;
> +	default:
> +		dev_err(priv->dev, "incompatible PHY type\n");
> +		return -EINVAL;
> +	}
> +
> +	if (ret)
> +		dev_err(priv->dev, "failed to init phy for phy mode %x\n", priv->mode);
> +



> +	return ret;
> +}
> +

> +static int rockchip_combphy_init(struct phy *phy)

poweron

> +{
> +	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
> +	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
> +	u32 val;
> +	int ret;
> +
> +	ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
> +	if (ret) {
> +		dev_err(priv->dev, "failed to enable clks\n");
> +		return ret;
> +	}
> +

> +	ret = rockchip_combphy_set_mode(priv);
> +	if (ret)
> +		goto err_clk;
> +

Make use of phy frame work for setmode.

> +	ret = reset_control_deassert(priv->phy_rst);
> +	if (ret)
> +		goto err_clk;
> +
> +	if (priv->mode == PHY_TYPE_USB3) {
> +		ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready,
> +						priv, val,
> +						val == cfg->pipe_phy_status.enable,
> +						10, 1000);
> +		if (ret)
> +			dev_warn(priv->dev, "wait phy status ready timeout\n");
> +	}
> +
> +	return 0;
> +
> +err_clk:
> +	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
> +
> +	return ret;
> +}
> +

> +static int rockchip_combphy_exit(struct phy *phy)

poweroff

> +{
> +	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
> +
> +	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
> +	reset_control_assert(priv->phy_rst);
> +
> +	return 0;
> +}
> +
> +static const struct phy_ops rochchip_combphy_ops = {
> +	.init = rockchip_combphy_init,
> +	.exit = rockchip_combphy_exit,

Maybe use poweron poweroff

.set_mode = rockchip_combphy_set_mode,

> +	.owner = THIS_MODULE,
> +};
> +
> +static struct phy *rockchip_combphy_xlate(struct device *dev, struct of_phandle_args *args)

use xlate to translate phy structure to lanes.

> +{
> +	struct rockchip_combphy_priv *priv = dev_get_drvdata(dev);
> +
> +	if (args->args_count != 1) {
> +		dev_err(dev, "invalid number of arguments\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (priv->mode != PHY_NONE && priv->mode != args->args[0])
> +		dev_warn(dev, "phy type select %d overwriting type %d\n",
> +			 args->args[0], priv->mode);
> +
> +	priv->mode = args->args[0];




> +
> +	return priv->phy;
> +}
> +
> +static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv)
> +{
> +	int i;
> +
> +	priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
> +	if (priv->num_clks < 1)
> +		return -EINVAL;
> +
> +	priv->refclk = NULL;
> +	for (i = 0; i < priv->num_clks; i++) {
> +		if (!strncmp(priv->clks[i].id, "ref", 3)) {
> +			priv->refclk = priv->clks[i].clk;
> +			break;
> +		}
> +	}
> +
> +	if (!priv->refclk) {
> +		dev_err(dev, "no refclk found\n");
> +		return -EINVAL;
> +	}
> +
> +	priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-grf");
> +	if (IS_ERR(priv->pipe_grf)) {
> +		dev_err(dev, "failed to find peri_ctrl pipe-grf regmap\n");
> +		return PTR_ERR(priv->pipe_grf);
> +	}
> +
> +	priv->phy_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-phy-grf");
> +	if (IS_ERR(priv->phy_grf)) {
> +		dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n");
> +		return PTR_ERR(priv->phy_grf);
> +	}
> +
> +	priv->enable_ssc = device_property_present(dev, "rockchip,enable-ssc");
> +
> +	priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk");
> +
> +	priv->phy_rst = devm_reset_control_array_get(dev, false, false);
> +	if (IS_ERR(priv->phy_rst))
> +		return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n");
> +
> +	return 0;
> +}
> +
> +static int rockchip_combphy_probe(struct platform_device *pdev)
> +{
> +	struct phy_provider *phy_provider;
> +	struct device *dev = &pdev->dev;
> +	struct rockchip_combphy_priv *priv;
> +	const struct rockchip_combphy_cfg *phy_cfg;
> +	struct resource *res;
> +	int ret;
> +
> +	phy_cfg = of_device_get_match_data(dev);
> +	if (!phy_cfg) {
> +		dev_err(dev, "no OF match data provided\n");
> +		return -EINVAL;
> +	}
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
> +	if (IS_ERR(priv->mmio)) {
> +		ret = PTR_ERR(priv->mmio);
> +		return ret;
> +	}
> +
> +	priv->dev = dev;
> +	priv->mode = PHY_NONE;
> +	priv->cfg = phy_cfg;
> +
> +	ret = rockchip_combphy_parse_dt(dev, priv);
> +	if (ret)
> +		return ret;
> +
> +	ret = reset_control_assert(priv->phy_rst);
> +	if (ret) {
> +		dev_err(dev, "failed to reset phy\n");
> +		return ret;
> +	}
> +
> +	priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops);
> +	if (IS_ERR(priv->phy)) {
> +		dev_err(dev, "failed to create combphy\n");
> +		return PTR_ERR(priv->phy);
> +	}
> +
> +	dev_set_drvdata(dev, priv);
> +	phy_set_drvdata(priv->phy, priv);
> +
> +	phy_provider = devm_of_phy_provider_register(dev, rockchip_combphy_xlate);
> +
> +	return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv)
struct phy *phy

Use phy structure to pass data.
See version 6.

> +{
> +	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
> +	unsigned long rate;
> +	u32 val;
> +


> +	switch (priv->mode) {

switch phy/lane modes

> +	case PHY_TYPE_PCIE:
PHY_MODE_PCIE

> +		/* Set SSC downward spread spectrum. */
> +		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
> +					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
> +					 PHYREG32);
> +
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
> +		break;
> +

> +	case PHY_TYPE_USB3:

PHY_MODE_USB_DEVICE_SS

> +		/* Set SSC downward spread spectrum. */
> +		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
> +					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
> +					 PHYREG32);
> +
> +		/* Enable adaptive CTLE for USB3.0 Rx. */
> +		val = readl(priv->mmio + PHYREG15);
> +		val |= PHYREG15_CTLE_EN;
> +		writel(val, priv->mmio + PHYREG15);
> +
> +		/* Set PLL KVCO fine tuning signals. */
> +		rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
> +					 PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT,
> +					 PHYREG33);
> +
> +		/* Enable controlling random jitter. */
> +		writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
> +
> +		/* Set PLL input clock divider 1/2. */
> +		rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
> +					 PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT,
> +					 PHYREG6);
> +
> +		writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
> +		writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
> +
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);
> +		break;
> +

> +	case PHY_TYPE_SATA:

PHY_MODE_SATA

> +		/* Enable adaptive CTLE for SATA Rx. */
> +		val = readl(priv->mmio + PHYREG15);
> +		val |= PHYREG15_CTLE_EN;
> +		writel(val, priv->mmio + PHYREG15);
> +		/*
> +		 * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA.
> +		 * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm)
> +		 */
> +		val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;
> +		val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;
> +		writel(val, priv->mmio + PHYREG7);
> +
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);

> +		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);

3xSATA -> 3xprobe -> 3x: call rk3568_combphy_cfg -> 3xaccess pipe_grf

Pipe_grf is not reset, so previous (modules,probe,u-boot) state is
unknown. This driver is just assuming all bit are right.
Fix writing to common grf. Make it idiot proof!


> +		break;
> +


Use sub nodes.
Use phy structure to pass INTERFACE_MODE with arg[]

	case PHY_MODE_ETHERNET:
		switch (lane->submode) {
		case PHY_INTERFACE_MODE_SGMII

> +	case PHY_TYPE_SGMII:

> +		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->sgmii_mode_set, true);
> +		break;
> +

		case PHY_INTERFACE_MODE_QSGMII:
> +	case PHY_TYPE_QSGMII:


> +		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_rate_sel, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true);
> +		break;
> +
> +	default:
> +		dev_err(priv->dev, "incompatible PHY type\n");
> +		return -EINVAL;
> +	}
> +
> +	rate = clk_get_rate(priv->refclk);
> +
> +	switch (rate) {
> +	case REF_CLOCK_24MHz:
> +		if (priv->mode == PHY_TYPE_USB3 || priv->mode == PHY_TYPE_SATA) {
> +			/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */
> +			val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT;
> +			rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,
> +						 val, PHYREG15);
> +
> +			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
> +		}
> +		break;
> +
> +	case REF_CLOCK_25MHz:
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
> +		break;
> +
> +	case REF_CLOCK_100MHz:
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
> +		if (priv->mode == PHY_TYPE_PCIE) {
> +			/* PLL KVCO  fine tuning. */
> +			val = PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT;
> +			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
> +						 val, PHYREG33);
> +
> +			/* Enable controlling random jitter. */
> +			writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
> +
> +			val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT;
> +			rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
> +						 val, PHYREG6);
> +
> +			writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
> +			writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
> +		} else if (priv->mode == PHY_TYPE_SATA) {
> +			/* downward spread spectrum +500ppm */
> +			val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT;
> +			val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT;
> +			rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
> +		}
> +		break;
> +
> +	default:
> +		dev_err(priv->dev, "unsupported rate: %lu\n", rate);
> +		return -EINVAL;
> +	}
> +
> +	if (priv->ext_refclk) {
> +		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
> +		if (priv->mode == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {
> +			val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT;
> +			val |= PHYREG13_CKRCV_AMP0;
> +			rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13);
> +
> +			val = readl(priv->mmio + PHYREG14);
> +			val |= PHYREG14_CKRCV_AMP1;
> +			writel(val, priv->mmio + PHYREG14);
> +		}
> +	}
> +
> +	if (priv->enable_ssc) {
> +		val = readl(priv->mmio + PHYREG8);
> +		val |= PHYREG8_SSC_EN;
> +		writel(val, priv->mmio + PHYREG8);
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
> +	/* pipe-phy-grf */
> +	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
> +	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
> +	.sgmii_mode_set		= { 0x0000, 5, 0, 0x00, 0x01 },
> +	.qsgmii_mode_set	= { 0x0000, 5, 0, 0x00, 0x21 },
> +	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
> +	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
> +	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
> +	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
> +	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
> +	.pipe_phymode_sel	= { 0x0008, 1, 1, 0x00, 0x01 },
> +	.pipe_rate_sel		= { 0x0008, 2, 2, 0x00, 0x01 },
> +	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
> +	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
> +	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
> +	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
> +	.pipe_sel_usb		= { 0x000c, 14, 13, 0x00, 0x01 },
> +	.pipe_sel_qsgmii	= { 0x000c, 15, 13, 0x00, 0x07 },
> +	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
> +	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
> +	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
> +	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
> +	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
> +	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0119 },
> +	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0040 },
> +	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c3 },
> +	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x4407 },
> +	/* pipe-grf */
> +	.pipe_con0_for_sata	= { 0x0000, 15, 0, 0x00, 0x2220 },
> +	.pipe_xpcs_phy_ready	= { 0x0040, 2, 2, 0x00, 0x01 },
> +};
> +

rk3568_multiphy_modes structure

> +static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
> +	.grfcfg		= &rk3568_combphy_grfcfgs,
> +	.combphy_cfg	= rk3568_combphy_cfg,
> +};
> +
> +static const struct of_device_id rockchip_combphy_of_match[] = {

rk3566
rk3568
rk3588

> +	{
> +		.compatible = "rockchip,rk3568-naneng-combphy",
> +		.data = &rk3568_combphy_cfgs,
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match);
> +
> +static struct platform_driver rockchip_combphy_driver = {
> +	.probe	= rockchip_combphy_probe,
> +	.driver = {
> +		.name = "rockchip-naneng-combphy",
> +		.of_match_table = rockchip_combphy_of_match,
> +	},
> +};
> +module_platform_driver(rockchip_combphy_driver);
> +
> +MODULE_DESCRIPTION("Rockchip NANENG COMBPHY driver");
> +MODULE_LICENSE("GPL v2");
> 

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v7 3/4] phy: rockchip: add naneng combo phy for RK3568
  2021-12-30  8:48 ` [PATCH v7 3/4] phy: rockchip: add naneng combo phy for RK3568 Yifeng Zhao
  2022-01-03 18:26   ` Johan Jonker
@ 2022-01-05 10:43   ` Philipp Zabel
  1 sibling, 0 replies; 12+ messages in thread
From: Philipp Zabel @ 2022-01-05 10:43 UTC (permalink / raw)
  To: Yifeng Zhao, heiko
  Cc: robh+dt, jbx6244, devicetree, vkoul, michael.riesch,
	linux-rockchip, linux-arm-kernel, linux-kernel, linux-phy,
	kishon, cl, kever.yang, lee.jones, wulf

On Thu, 2021-12-30 at 16:48 +0800, Yifeng Zhao wrote:
[...]
> +static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv)
> +{
[...]
> +	priv->phy_rst = devm_reset_control_array_get(dev, false, false);

Please use devm_reset_control_array_get_exclusive() instead.

regards
Philipp

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v7] dt-bindings: soc: grf: add naneng combo phy register compatible
  2021-12-31  8:22   ` [PATCH v7] dt-bindings: soc: grf: " Johan Jonker
@ 2022-01-10 20:40     ` Rob Herring
  0 siblings, 0 replies; 12+ messages in thread
From: Rob Herring @ 2022-01-10 20:40 UTC (permalink / raw)
  To: Johan Jonker
  Cc: cl, vkoul, robh+dt, p.zabel, devicetree, linux-phy, yifeng.zhao,
	linux-kernel, linux-rockchip, linux-arm-kernel, kever.yang,
	heiko, wulf, kishon, michael.riesch

On Fri, 31 Dec 2021 09:22:49 +0100, Johan Jonker wrote:
> Add Naneng combo phy register compatible.
> 
> Signed-off-by: Johan Jonker <jbx6244@gmail.com>
> ---
>  Documentation/devicetree/bindings/soc/rockchip/grf.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v7 3/4] phy: rockchip: add naneng combo phy for RK3568
  2022-01-03 18:26   ` Johan Jonker
@ 2022-02-04 12:17     ` Johan Jonker
  2022-02-08 10:22     ` zyf
  1 sibling, 0 replies; 12+ messages in thread
From: Johan Jonker @ 2022-02-04 12:17 UTC (permalink / raw)
  To: Yifeng Zhao, heiko
  Cc: robh+dt, devicetree, vkoul, michael.riesch, linux-rockchip,
	linux-arm-kernel, linux-kernel, linux-phy, kishon, p.zabel, cl,
	kever.yang, lee.jones, wulf, Frank Wunderlich

Hi Heiko, Frank and others,

China is on new year vacation.

Question for Heiko:
With xpcs in a separate node, how do we pass phy modes from gmac to
xpcs, multiphy in a correct DT way?
Can we brand xpcs as phy?
Please advise.

Johan
===

Found example for the way Rockchip connects sgmii in the manufacturer DT.
https://github.com/Poco-Ye/rk-ethernet/blob/master/SGMII.rar

From gmac1.txt:

> &mdio1 {
>         sgmii_phy: phy@1 {
         sgmii_phy: phy@0 { // ???

What is correct?

>                 compatible = "ethernet-phy-ieee802.3-c22";
>                 reg = <0x0>;

C45E
Clause 45 PHY Enable
When this bit is set, Clause 45 capable PHY is connected to MDIO.
When this bit is reset, Clause 22 capable PHY is connected to
MDIO.
Values:
1'b0: Clause 45 PHY is disabled
1'b1: Clause 45 PHY is enabled

>         };
> };
>
>
> &combphy2_psq {
> +       rockchip,sgmii-mac-sel = <1>;
>         status = "okay";
> };
>
>
> &gmac0 {
> 	phy-mode = "sgmii";
> 	
> 	rockchip,pipegrf = <&pipegrf>;
> 	rockchip,xpcs = <&xpcs>;
>
> 	snps,reset-gpio = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
> 	snps,reset-active-low;
> 	/* Reset time is 20ms, 100ms for rtl8211f */
> 	snps,reset-delays-us = <0 20000 100000>;
>
> 	assigned-clocks = <&cru SCLK_GMAC1_RX_TX>;
> 	assigned-clock-parents = <&gmac1_xpcsclk>;
>
> +	pinctrl-0 = <&gmac1m0_miim>;
> 	power-domains = <&power RK3568_PD_PIPE>;
> 	phys = <&combphy2_psq PHY_TYPE_SGMII>;
> +	phy-handle = <&sgmii_phy>;
>
> 	status = "okay";
> };

===

Proposal:
xpcs driver passes mode info to multiphy driver.
Phy arg is used for gmac source selection for PHY_INTERFACE_MODE_SGMII
and PHY_INTERFACE_MODE_QSGMII.

> 	phys = <&xpcs 0>;

===

{
	gmac0_xpcsclk: xpcs-gmac0-clock {
		compatible = "fixed-clock";
		clock-frequency = <125000000>;
		clock-output-names = "clk_gmac0_xpcs_mii";
		#clock-cells = <0>;
	};

	gmac1_xpcsclk: xpcs-gmac1-clock {
		compatible = "fixed-clock";
		clock-frequency = <125000000>;
		clock-output-names = "clk_gmac1_xpcs_mii";
		#clock-cells = <0>;
	};

	xpcs: syscon@fda00000 {
		compatible = "rockchip,rk3568-xpcs", "syscon";
		reg = <0x0 0xfda00000 0x0 0x200000>;
		clocks = <&cru PCLK_XPCS>;
		clock-names = "pclk_xpcs";

>		phys = <&multiphy2>;

		power-domains = <&power RK3568_PD_PIPE>;
 		rockchip,pipegrf = <&pipegrf>; // Switch between gmac0 and gmac1
		status = "disabled";
	};
}

&mdio1 {
         sgmii_phy: phy@0 {
                 compatible = "ethernet-phy-ieee802.3-c22";
                 reg = <0x0>;
         };
 };


&multiphy2 {
         status = "okay";
};


&gmac0 {
	assigned-clocks = <&cru SCLK_GMAC1_RX_TX>;
 	assigned-clock-parents = <&gmac1_xpcsclk>;

 	phys = <&combphy2_psq PHY_TYPE_SGMII>;
	phy-handle = <&sgmii_phy>;
 	phy-mode = "sgmii";

> 	phys = <&xpcs 0>;

	pinctrl-0 = <&gmac1m0_miim>;

 	snps,reset-gpio = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
	snps,reset-active-low;
 	/* Reset time is 20ms, 100ms for rtl8211f */
 	snps,reset-delays-us = <0 20000 100000>;

	status = "okay";
};

On 1/3/22 19:26, Johan Jonker wrote:
> Hi Yifeng, Kishon, rob+dt,
> 
> Some comments, have a look if it's useful.
> 
> ====
> 
> Could the DT and phy maintainer advise the correct/right driver
> structure to Yifeng, so that we can move forward!
> 
> ====
> 

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Re: [PATCH v7 3/4] phy: rockchip: add naneng combo phy for RK3568
  2022-01-03 18:26   ` Johan Jonker
  2022-02-04 12:17     ` Johan Jonker
@ 2022-02-08 10:22     ` zyf
  1 sibling, 0 replies; 12+ messages in thread
From: zyf @ 2022-02-08 10:22 UTC (permalink / raw)
  To: Johan Jonker, 赵仪峰, HeikoStübner
  Cc: robh+dt, devicetree, Vinod Koul, michael.riesch, linux-rockchip,
	linux-arm-kernel, linux-kernel, linux-phy, kishon, Philipp Zabel,
	陈亮, Kever.Yang, Lee Jones, 吴良峰,
	Frank Wunderlich

Hi Johan,

We refer to the following driver:
https://elixir.bootlin.com/linux/latest/source/drivers/phy/hisilicon/phy-histb-combphy.c

Passing phy type through dts phy arg, like this:
phys = <&combphy2u PHY_TYPE_SATA>;
So don't need phy_set_mode.

>> +	rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
> 
>3xSATA -> 3xprobe -> 3x: call rk3568_combphy_cfg -> 3xaccess pipe_grf
> 
The pipe_con0_for_sata is used to configure the rate: 6G, 3G or 1.5G for the SATA mode.
Three phys are configured at the same time, and repeated configuration has no problem.

The current driver supports the configuration of SGMII and QSGMII:
QSGMII:
gmac0 --> 
                   \
                     =----> combphy1 or combphy2
                   /
gmac1 --> 

SGMII(fixed link):
gmac0 -----> combphy1(SGMII)
gmac1 -----> combphy2(SGMII)

The SOC hardware can also support the following link, but the driver not support yet.
In order to avoid exceptions, we won't consider supporting it in the future.
gmac0 -----> combphy2(SGMII)
gmac1 -----> combphy1(SGMII)

-------
Yifeng

>Hi Yifeng, Kishon, rob+dt,
> 
>Some comments, have a look if it's useful.
> 
>====
> 
>Could the DT and phy maintainer advise the correct/right driver
>structure to Yifeng, so that we can move forward!
> 
>====
> 
>This driver still follows the wrong approach.
>Things used in the manufacturer tree are not necessary future proof in a
>mainline kernel.
>In order to switch SGMII input between lane1 and lanes2 phy structures
>it is needed that there is a parent node.
> 
>Could you look at combo phy example:
> 
>https://elixir.bootlin.com/linux/latest/source/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
> 
>To prevent accidents with a DT from the manefucturer tree and mainline
>use a differnet compatible string for each SoC.
> 
>See version 6:
>Use for_each_available_child_of_node to find all available subnodes.
> 
>Make for each SoC a structure with supported features.
> 
>Make better use of the phy frame work ops  (setmode, poweron).
> 
>====
>Use enum phy_mode instead of PHY_TYPE.
> 
>PHY_TYPE are used in DT.
>phy_mode are used in struct phy *phy
>====
> 
>Example to generate the capabilities structure:
>static const struct rk3568_multiphy_conf rk3568_multiphy_modes[] = {
>/* lane 0 */
>RK3568_MULTI_CONF_GEN(0, PHY_MODE_SATA, 0,
>    MULTI_FW_MODE_SATA),
>RK3568_MULTI_CONF_GEN(0, PHY_MODE_USB_HOST_SS, 0,
>    MULTI_FW_MODE_USB3H),
>/* lane 1 */
>RK3568_MULTI_CONF_GEN(1, PHY_MODE_SATA, 0,
>    MULTI_FW_MODE_SATA),
>RK3568_MULTI_CONF_GEN(1, PHY_MODE_USB_HOST_SS, 0,
>    MULTI_FW_MODE_USB3H),
>RK3568_MULTI_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, 0,
>    MULTI_FW_MODE_SGMII),
>/* lane 2 */
>RK3568_MULTI_CONF_GEN(2, PHY_MODE_SATA, 0,
>    MULTI_FW_MODE_SATA),
>RK3568_MULTI_CONF_ETH(2, PHY_INTERFACE_MODE_SGMII, 1,
>    MULTI_FW_MODE_SGMII),
>RK3568_MULTI_CONF_GEN(2, PHY_MODE_PCIE, 0,
>    MULTI_FW_MODE_PCIE),
>};
> 
>On 12/30/21 9:48 AM, Yifeng Zhao wrote:
>> This patch implements a combo phy driver for Rockchip SoCs
>> with NaNeng IP block. This phy can be used as pcie-phy, usb3-phy,
>> sata-phy or sgmii-phy.
>>
>> Signed-off-by: Yifeng Zhao <yifeng.zhao@rock-chips.com>
>> Signed-off-by: Johan Jonker <jbx6244@gmail.com>
>> ---
>>
>> Changes in v7:
>> - rename regs
>> - remove pipe_sgmii_mac_sel, u3otg0_port_en and u3otg1_port_en
>>
>> Changes in v5:
>> - add rockchip_combphy_updatel()
>> - restyle
>>
>> Changes in v4:
>> - restyle
>> - add devm_reset_control_array_get()
>> - remove clk structure
>> - change refclk DT parse
>> - change dev_err message
>> - add dot to phrase
>> - add ext_refclk variable
>> - add enable_ssc variable
>> - rename rockchip_combphy_param_write
>> - remove param_read
>> - replace rockchip-naneng-combphy driver name
>>
>> Changes in v3:
>> - Using api devm_reset_control_get_optional_exclusive and dev_err_probe.
>> - Remove apb_rst.
>> - Redefine registers address.
>>
>> Changes in v2:
>> - Using api devm_platform_get_and_ioremap_resource.
>> - Modify rockchip_combphy_set_Mode.
>> - Add some PHY registers definition.
>>
>>  drivers/phy/rockchip/Kconfig                  |   8 +
>>  drivers/phy/rockchip/Makefile                 |   1 +
>>  .../rockchip/phy-rockchip-naneng-combphy.c    | 589 ++++++++++++++++++
>>  3 files changed, 598 insertions(+)
>>  create mode 100644 drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
>>
>> diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
>> index e812adad7242..9022e395c056 100644
>> --- a/drivers/phy/rockchip/Kconfig
>> +++ b/drivers/phy/rockchip/Kconfig
>> @@ -66,6 +66,14 @@ config PHY_ROCKCHIP_INNO_DSIDPHY
>>    Enable this to support the Rockchip MIPI/LVDS/TTL PHY with
>>    Innosilicon IP block.
>> 
>> +config PHY_ROCKCHIP_NANENG_COMBO_PHY
>> +	tristate "Rockchip NANENG COMBO PHY Driver"
>> +	depends on ARCH_ROCKCHIP && OF
>> +	select GENERIC_PHY
>> +	help
>> +	  Enable this to support the Rockchip PCIe/USB3.0/SATA/QSGMII
>> +	  combo PHY with NaNeng IP block.
>> +
>>  config PHY_ROCKCHIP_PCIE
>>  tristate "Rockchip PCIe PHY Driver"
>>  depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
>> diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
>> index f0eec212b2aa..a5041efb5b8f 100644
>> --- a/drivers/phy/rockchip/Makefile
>> +++ b/drivers/phy/rockchip/Makefile
>> @@ -6,6 +6,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY)	+= phy-rockchip-inno-csidphy.o
>>  obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY)	+= phy-rockchip-inno-dsidphy.o
>>  obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI)	+= phy-rockchip-inno-hdmi.o
>>  obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2)	+= phy-rockchip-inno-usb2.o
>> +obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY)	+= phy-rockchip-naneng-combphy.o
>>  obj-$(CONFIG_PHY_ROCKCHIP_PCIE)	+= phy-rockchip-pcie.o
>>  obj-$(CONFIG_PHY_ROCKCHIP_TYPEC)	+= phy-rockchip-typec.o
>>  obj-$(CONFIG_PHY_ROCKCHIP_USB)	+= phy-rockchip-usb.o
>> diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
>> new file mode 100644
>> index 000000000000..47137a5c448a
>> --- /dev/null
>> +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
>> @@ -0,0 +1,589 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Rockchip PIPE USB3.0 PCIE SATA Combo Phy driver
>> + *
>> + * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
>> + */
>> +
>> +#include <dt-bindings/phy/phy.h>
>> +#include <linux/clk.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/of_device.h>
>> +#include <linux/phy/phy.h>
>> +#include <linux/regmap.h>
>> +#include <linux/reset.h>
>> +#include <linux/units.h>
>> +
>> +#define BIT_WRITEABLE_SHIFT	16
>> +#define REF_CLOCK_24MHz	(24 * HZ_PER_MHZ)
>> +#define REF_CLOCK_25MHz	(25 * HZ_PER_MHZ)
>> +#define REF_CLOCK_100MHz	(100 * HZ_PER_MHZ)
>> +
>> +/* COMBO PHY REG */
>> +#define PHYREG6	0x14
>> +#define PHYREG6_PLL_DIV_MASK	GENMASK(7, 6)
>> +#define PHYREG6_PLL_DIV_SHIFT	6
>> +#define PHYREG6_PLL_DIV_2	1
>> +
>> +#define PHYREG7	0x18
>> +#define PHYREG7_TX_RTERM_MASK	GENMASK(7, 4)
>> +#define PHYREG7_TX_RTERM_SHIFT	4
>> +#define PHYREG7_TX_RTERM_50OHM	8
>> +#define PHYREG7_RX_RTERM_MASK	GENMASK(3, 0)
>> +#define PHYREG7_RX_RTERM_SHIFT	0
>> +#define PHYREG7_RX_RTERM_44OHM	15
>> +
>> +#define PHYREG8	0x1C
>> +#define PHYREG8_SSC_EN	BIT(4)
>> +
>> +#define PHYREG11	0x28
>> +#define PHYREG11_SU_TRIM_0_7	0xF0
>> +
>> +#define PHYREG12	0x2C
>> +#define PHYREG12_PLL_LPF_ADJ_VALUE	4
>> +
>> +#define PHYREG13	0x30
>> +#define PHYREG13_RESISTER_MASK	GENMASK(5, 4)
>> +#define PHYREG13_RESISTER_SHIFT	0x4
>> +#define PHYREG13_RESISTER_HIGH_Z	3
>> +#define PHYREG13_CKRCV_AMP0	BIT(7)
>> +
>> +#define PHYREG14	0x34
>> +#define PHYREG14_CKRCV_AMP1	BIT(0)
>> +
>> +#define PHYREG15	0x38
>> +#define PHYREG15_CTLE_EN	BIT(0)
>> +#define PHYREG15_SSC_CNT_MASK	GENMASK(7, 6)
>> +#define PHYREG15_SSC_CNT_SHIFT	6
>> +#define PHYREG15_SSC_CNT_VALUE	1
>> +
>> +#define PHYREG16	0x3C
>> +#define PHYREG16_SSC_CNT_VALUE	0x5f
>> +
>> +#define PHYREG18	0x44
>> +#define PHYREG18_PLL_LOOP	0x32
>> +
>> +#define PHYREG32	0x7C
>> +#define PHYREG32_SSC_MASK	GENMASK(7, 4)
>> +#define PHYREG32_SSC_DIR_SHIFT	4
>> +#define PHYREG32_SSC_UPWARD	0
>> +#define PHYREG32_SSC_DOWNWARD	1
>> +#define PHYREG32_SSC_OFFSET_SHIFT	6
>> +#define PHYREG32_SSC_OFFSET_500PPM	1
>> +
>> +#define PHYREG33	0x80
>> +#define PHYREG33_PLL_KVCO_MASK	GENMASK(4, 2)
>> +#define PHYREG33_PLL_KVCO_SHIFT	2
>> +#define PHYREG33_PLL_KVCO_VALUE	2
>> +
>> +struct rockchip_combphy_priv;
>> +
>> +struct combphy_reg {
>> +	u16 offset;
>> +	u16 bitend;
>> +	u16 bitstart;
>> +	u16 disable;
>> +	u16 enable;
>> +};
>> +
>> +struct rockchip_combphy_grfcfg {
>> +	struct combphy_reg pcie_mode_set;
>> +	struct combphy_reg usb_mode_set;
>> +	struct combphy_reg sgmii_mode_set;
>> +	struct combphy_reg qsgmii_mode_set;
>> +	struct combphy_reg pipe_rxterm_set;
>> +	struct combphy_reg pipe_txelec_set;
>> +	struct combphy_reg pipe_txcomp_set;
>> +	struct combphy_reg pipe_clk_25m;
>> +	struct combphy_reg pipe_clk_100m;
>> +	struct combphy_reg pipe_phymode_sel;
>> +	struct combphy_reg pipe_rate_sel;
>> +	struct combphy_reg pipe_rxterm_sel;
>> +	struct combphy_reg pipe_txelec_sel;
>> +	struct combphy_reg pipe_txcomp_sel;
>> +	struct combphy_reg pipe_clk_ext;
>> +	struct combphy_reg pipe_sel_usb;
>> +	struct combphy_reg pipe_sel_qsgmii;
>> +	struct combphy_reg pipe_phy_status;
>> +	struct combphy_reg con0_for_pcie;
>> +	struct combphy_reg con1_for_pcie;
>> +	struct combphy_reg con2_for_pcie;
>> +	struct combphy_reg con3_for_pcie;
>> +	struct combphy_reg con0_for_sata;
>> +	struct combphy_reg con1_for_sata;
>> +	struct combphy_reg con2_for_sata;
>> +	struct combphy_reg con3_for_sata;
>> +	struct combphy_reg pipe_con0_for_sata;
>> +	struct combphy_reg pipe_xpcs_phy_ready;
>> +};
>> +
>> +struct rockchip_combphy_cfg {
>> +	const struct rockchip_combphy_grfcfg *grfcfg;
>> +	int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
>> +};
>> +
>> +struct rockchip_combphy_priv {
>> +	u8 mode;
>> +	void __iomem *mmio;
>> +	int num_clks;
>> +	struct clk_bulk_data *clks;
>> +	struct device *dev;
>> +	struct regmap *pipe_grf;
>> +	struct regmap *phy_grf;
>> +	struct phy *phy;
>> +	struct reset_control *phy_rst;
>> +	const struct rockchip_combphy_cfg *cfg;
>> +	bool enable_ssc;
>> +	bool ext_refclk;
>> +	struct clk *refclk;
>> +};
>> +
>> +static void rockchip_combphy_updatel(struct rockchip_combphy_priv *priv,
>> +	     int mask, int val, int reg)
>> +{
>> +	unsigned int temp;
>> +
>> +	temp = readl(priv->mmio + reg);
>> +	temp = (temp & ~(mask)) | val;
>> +	writel(temp, priv->mmio + reg);
>> +}
>> +
>> +static int rockchip_combphy_param_write(struct regmap *base,
>> +	const struct combphy_reg *reg, bool en)
>> +{
>> +	u32 val, mask, tmp;
>> +
>> +	tmp = en ? reg->enable : reg->disable;
>> +	mask = GENMASK(reg->bitend, reg->bitstart);
>> +	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
>> +
>> +	return regmap_write(base, reg->offset, val);
>> +}
>> +
>> +static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv)
>> +{
>> +	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
>> +	u32 mask, val;
>> +
>> +	mask = GENMASK(cfg->pipe_phy_status.bitend,
>> +	       cfg->pipe_phy_status.bitstart);
>> +
>> +	regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val);
>> +	val = (val & mask) >> cfg->pipe_phy_status.bitstart;
>> +
>> +	return val;
>> +}
>> +
> 
>> +static int rockchip_combphy_set_mode(struct rockchip_combphy_priv *priv)
> 
>static int rockchip_combphy_set_mode(struct phy *phy, enum phy_mode
>mode, int submode)
> 
>/* Use this function to remember the mode, ->power_on() will do the
>real setup */
> 
>> +{
>> +	int ret = 0;
>> +
>> +	switch (priv->mode) {
>> +	case PHY_TYPE_PCIE:
>> +	case PHY_TYPE_USB3:
>> +	case PHY_TYPE_SATA:
>> +	case PHY_TYPE_SGMII:
>> +	case PHY_TYPE_QSGMII:
>> +	if (priv->cfg->combphy_cfg)
>> +	ret = priv->cfg->combphy_cfg(priv);
>> +	break;
>> +	default:
>> +	dev_err(priv->dev, "incompatible PHY type\n");
>> +	return -EINVAL;
>> +	}
>> +
>> +	if (ret)
>> +	dev_err(priv->dev, "failed to init phy for phy mode %x\n", priv->mode);
>> +
> 
> 
> 
>> +	return ret;
>> +}
>> +
> 
>> +static int rockchip_combphy_init(struct phy *phy)
> 
>poweron
> 
>> +{
>> +	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
>> +	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
>> +	u32 val;
>> +	int ret;
>> +
>> +	ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
>> +	if (ret) {
>> +	dev_err(priv->dev, "failed to enable clks\n");
>> +	return ret;
>> +	}
>> +
> 
>> +	ret = rockchip_combphy_set_mode(priv);
>> +	if (ret)
>> +	goto err_clk;
>> +
> 
>Make use of phy frame work for setmode.
> 
>> +	ret = reset_control_deassert(priv->phy_rst);
>> +	if (ret)
>> +	goto err_clk;
>> +
>> +	if (priv->mode == PHY_TYPE_USB3) {
>> +	ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready,
>> +	priv, val,
>> +	val == cfg->pipe_phy_status.enable,
>> +	10, 1000);
>> +	if (ret)
>> +	dev_warn(priv->dev, "wait phy status ready timeout\n");
>> +	}
>> +
>> +	return 0;
>> +
>> +err_clk:
>> +	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
>> +
>> +	return ret;
>> +}
>> +
> 
>> +static int rockchip_combphy_exit(struct phy *phy)
> 
>poweroff
> 
>> +{
>> +	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
>> +
>> +	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
>> +	reset_control_assert(priv->phy_rst);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct phy_ops rochchip_combphy_ops = {
>> +	.init = rockchip_combphy_init,
>> +	.exit = rockchip_combphy_exit,
> 
>Maybe use poweron poweroff
> 
>.set_mode = rockchip_combphy_set_mode,
> 
>> +	.owner = THIS_MODULE,
>> +};
>> +
>> +static struct phy *rockchip_combphy_xlate(struct device *dev, struct of_phandle_args *args)
> 
>use xlate to translate phy structure to lanes.
> 
>> +{
>> +	struct rockchip_combphy_priv *priv = dev_get_drvdata(dev);
>> +
>> +	if (args->args_count != 1) {
>> +	dev_err(dev, "invalid number of arguments\n");
>> +	return ERR_PTR(-EINVAL);
>> +	}
>> +
>> +	if (priv->mode != PHY_NONE && priv->mode != args->args[0])
>> +	dev_warn(dev, "phy type select %d overwriting type %d\n",
>> +	args->args[0], priv->mode);
>> +
>> +	priv->mode = args->args[0];
> 
> 
> 
> 
>> +
>> +	return priv->phy;
>> +}
>> +
>> +static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv)
>> +{
>> +	int i;
>> +
>> +	priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
>> +	if (priv->num_clks < 1)
>> +	return -EINVAL;
>> +
>> +	priv->refclk = NULL;
>> +	for (i = 0; i < priv->num_clks; i++) {
>> +	if (!strncmp(priv->clks[i].id, "ref", 3)) {
>> +	priv->refclk = priv->clks[i].clk;
>> +	break;
>> +	}
>> +	}
>> +
>> +	if (!priv->refclk) {
>> +	dev_err(dev, "no refclk found\n");
>> +	return -EINVAL;
>> +	}
>> +
>> +	priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-grf");
>> +	if (IS_ERR(priv->pipe_grf)) {
>> +	dev_err(dev, "failed to find peri_ctrl pipe-grf regmap\n");
>> +	return PTR_ERR(priv->pipe_grf);
>> +	}
>> +
>> +	priv->phy_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-phy-grf");
>> +	if (IS_ERR(priv->phy_grf)) {
>> +	dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n");
>> +	return PTR_ERR(priv->phy_grf);
>> +	}
>> +
>> +	priv->enable_ssc = device_property_present(dev, "rockchip,enable-ssc");
>> +
>> +	priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk");
>> +
>> +	priv->phy_rst = devm_reset_control_array_get(dev, false, false);
>> +	if (IS_ERR(priv->phy_rst))
>> +	return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n");
>> +
>> +	return 0;
>> +}
>> +
>> +static int rockchip_combphy_probe(struct platform_device *pdev)
>> +{
>> +	struct phy_provider *phy_provider;
>> +	struct device *dev = &pdev->dev;
>> +	struct rockchip_combphy_priv *priv;
>> +	const struct rockchip_combphy_cfg *phy_cfg;
>> +	struct resource *res;
>> +	int ret;
>> +
>> +	phy_cfg = of_device_get_match_data(dev);
>> +	if (!phy_cfg) {
>> +	dev_err(dev, "no OF match data provided\n");
>> +	return -EINVAL;
>> +	}
>> +
>> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>> +	if (!priv)
>> +	return -ENOMEM;
>> +
>> +	priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
>> +	if (IS_ERR(priv->mmio)) {
>> +	ret = PTR_ERR(priv->mmio);
>> +	return ret;
>> +	}
>> +
>> +	priv->dev = dev;
>> +	priv->mode = PHY_NONE;
>> +	priv->cfg = phy_cfg;
>> +
>> +	ret = rockchip_combphy_parse_dt(dev, priv);
>> +	if (ret)
>> +	return ret;
>> +
>> +	ret = reset_control_assert(priv->phy_rst);
>> +	if (ret) {
>> +	dev_err(dev, "failed to reset phy\n");
>> +	return ret;
>> +	}
>> +
>> +	priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops);
>> +	if (IS_ERR(priv->phy)) {
>> +	dev_err(dev, "failed to create combphy\n");
>> +	return PTR_ERR(priv->phy);
>> +	}
>> +
>> +	dev_set_drvdata(dev, priv);
>> +	phy_set_drvdata(priv->phy, priv);
>> +
>> +	phy_provider = devm_of_phy_provider_register(dev, rockchip_combphy_xlate);
>> +
>> +	return PTR_ERR_OR_ZERO(phy_provider);
>> +}
>> +
>> +static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv)
>struct phy *phy
> 
>Use phy structure to pass data.
>See version 6.
> 
>> +{
>> +	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
>> +	unsigned long rate;
>> +	u32 val;
>> +
> 
> 
>> +	switch (priv->mode) {
> 
>switch phy/lane modes
> 
>> +	case PHY_TYPE_PCIE:
>PHY_MODE_PCIE
> 
>> +	/* Set SSC downward spread spectrum. */
>> +	rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
>> +	PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
>> +	PHYREG32);
>> +
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
>> +	break;
>> +
> 
>> +	case PHY_TYPE_USB3:
> 
>PHY_MODE_USB_DEVICE_SS
> 
>> +	/* Set SSC downward spread spectrum. */
>> +	rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
>> +	PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
>> +	PHYREG32);
>> +
>> +	/* Enable adaptive CTLE for USB3.0 Rx. */
>> +	val = readl(priv->mmio + PHYREG15);
>> +	val |= PHYREG15_CTLE_EN;
>> +	writel(val, priv->mmio + PHYREG15);
>> +
>> +	/* Set PLL KVCO fine tuning signals. */
>> +	rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
>> +	PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT,
>> +	PHYREG33);
>> +
>> +	/* Enable controlling random jitter. */
>> +	writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
>> +
>> +	/* Set PLL input clock divider 1/2. */
>> +	rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
>> +	PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT,
>> +	PHYREG6);
>> +
>> +	writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
>> +	writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
>> +
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);
>> +	break;
>> +
> 
>> +	case PHY_TYPE_SATA:
> 
>PHY_MODE_SATA
> 
>> +	/* Enable adaptive CTLE for SATA Rx. */
>> +	val = readl(priv->mmio + PHYREG15);
>> +	val |= PHYREG15_CTLE_EN;
>> +	writel(val, priv->mmio + PHYREG15);
>> +	/*
>> +	* Set tx_rterm=50ohm and rx_rterm=44ohm for SATA.
>> +	* 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm)
>> +	*/
>> +	val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;
>> +	val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;
>> +	writel(val, priv->mmio + PHYREG7);
>> +
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);
> 
>> +	rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
> 
>3xSATA -> 3xprobe -> 3x: call rk3568_combphy_cfg -> 3xaccess pipe_grf
> 
>Pipe_grf is not reset, so previous (modules,probe,u-boot) state is
>unknown. This driver is just assuming all bit are right.
>Fix writing to common grf. Make it idiot proof!
> 
> 
>> +	break;
>> +
> 
> 
>Use sub nodes.
>Use phy structure to pass INTERFACE_MODE with arg[]
> 
>case PHY_MODE_ETHERNET:
>switch (lane->submode) {
>case PHY_INTERFACE_MODE_SGMII
> 
>> +	case PHY_TYPE_SGMII:
> 
>> +	rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->sgmii_mode_set, true);
>> +	break;
>> +
> 
>case PHY_INTERFACE_MODE_QSGMII:
>> +	case PHY_TYPE_QSGMII:
> 
> 
>> +	rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_rate_sel, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true);
>> +	break;
>> +
>> +	default:
>> +	dev_err(priv->dev, "incompatible PHY type\n");
>> +	return -EINVAL;
>> +	}
>> +
>> +	rate = clk_get_rate(priv->refclk);
>> +
>> +	switch (rate) {
>> +	case REF_CLOCK_24MHz:
>> +	if (priv->mode == PHY_TYPE_USB3 || priv->mode == PHY_TYPE_SATA) {
>> +	/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */
>> +	val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT;
>> +	rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,
>> +	val, PHYREG15);
>> +
>> +	writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
>> +	}
>> +	break;
>> +
>> +	case REF_CLOCK_25MHz:
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
>> +	break;
>> +
>> +	case REF_CLOCK_100MHz:
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
>> +	if (priv->mode == PHY_TYPE_PCIE) {
>> +	/* PLL KVCO  fine tuning. */
>> +	val = PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT;
>> +	rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
>> +	val, PHYREG33);
>> +
>> +	/* Enable controlling random jitter. */
>> +	writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
>> +
>> +	val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT;
>> +	rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
>> +	val, PHYREG6);
>> +
>> +	writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
>> +	writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
>> +	} else if (priv->mode == PHY_TYPE_SATA) {
>> +	/* downward spread spectrum +500ppm */
>> +	val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT;
>> +	val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT;
>> +	rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
>> +	}
>> +	break;
>> +
>> +	default:
>> +	dev_err(priv->dev, "unsupported rate: %lu\n", rate);
>> +	return -EINVAL;
>> +	}
>> +
>> +	if (priv->ext_refclk) {
>> +	rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
>> +	if (priv->mode == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {
>> +	val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT;
>> +	val |= PHYREG13_CKRCV_AMP0;
>> +	rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13);
>> +
>> +	val = readl(priv->mmio + PHYREG14);
>> +	val |= PHYREG14_CKRCV_AMP1;
>> +	writel(val, priv->mmio + PHYREG14);
>> +	}
>> +	}
>> +
>> +	if (priv->enable_ssc) {
>> +	val = readl(priv->mmio + PHYREG8);
>> +	val |= PHYREG8_SSC_EN;
>> +	writel(val, priv->mmio + PHYREG8);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
>> +	/* pipe-phy-grf */
>> +	.pcie_mode_set	= { 0x0000, 5, 0, 0x00, 0x11 },
>> +	.usb_mode_set	= { 0x0000, 5, 0, 0x00, 0x04 },
>> +	.sgmii_mode_set	= { 0x0000, 5, 0, 0x00, 0x01 },
>> +	.qsgmii_mode_set	= { 0x0000, 5, 0, 0x00, 0x21 },
>> +	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
>> +	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
>> +	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
>> +	.pipe_clk_25m	= { 0x0004, 14, 13, 0x00, 0x01 },
>> +	.pipe_clk_100m	= { 0x0004, 14, 13, 0x00, 0x02 },
>> +	.pipe_phymode_sel	= { 0x0008, 1, 1, 0x00, 0x01 },
>> +	.pipe_rate_sel	= { 0x0008, 2, 2, 0x00, 0x01 },
>> +	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
>> +	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
>> +	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
>> +	.pipe_clk_ext	= { 0x000c, 9, 8, 0x02, 0x01 },
>> +	.pipe_sel_usb	= { 0x000c, 14, 13, 0x00, 0x01 },
>> +	.pipe_sel_qsgmii	= { 0x000c, 15, 13, 0x00, 0x07 },
>> +	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
>> +	.con0_for_pcie	= { 0x0000, 15, 0, 0x00, 0x1000 },
>> +	.con1_for_pcie	= { 0x0004, 15, 0, 0x00, 0x0000 },
>> +	.con2_for_pcie	= { 0x0008, 15, 0, 0x00, 0x0101 },
>> +	.con3_for_pcie	= { 0x000c, 15, 0, 0x00, 0x0200 },
>> +	.con0_for_sata	= { 0x0000, 15, 0, 0x00, 0x0119 },
>> +	.con1_for_sata	= { 0x0004, 15, 0, 0x00, 0x0040 },
>> +	.con2_for_sata	= { 0x0008, 15, 0, 0x00, 0x80c3 },
>> +	.con3_for_sata	= { 0x000c, 15, 0, 0x00, 0x4407 },
>> +	/* pipe-grf */
>> +	.pipe_con0_for_sata	= { 0x0000, 15, 0, 0x00, 0x2220 },
>> +	.pipe_xpcs_phy_ready	= { 0x0040, 2, 2, 0x00, 0x01 },
>> +};
>> +
> 
>rk3568_multiphy_modes structure
> 
>> +static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
>> +	.grfcfg	= &rk3568_combphy_grfcfgs,
>> +	.combphy_cfg	= rk3568_combphy_cfg,
>> +};
>> +
>> +static const struct of_device_id rockchip_combphy_of_match[] = {
> 
>rk3566
>rk3568
>rk3588
> 
>> +	{
>> +	.compatible = "rockchip,rk3568-naneng-combphy",
>> +	.data = &rk3568_combphy_cfgs,
>> +	},
>> +	{ },
>> +};
>> +MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match);
>> +
>> +static struct platform_driver rockchip_combphy_driver = {
>> +	.probe	= rockchip_combphy_probe,
>> +	.driver = {
>> +	.name = "rockchip-naneng-combphy",
>> +	.of_match_table = rockchip_combphy_of_match,
>> +	},
>> +};
>> +module_platform_driver(rockchip_combphy_driver);
>> +
>> +MODULE_DESCRIPTION("Rockchip NANENG COMBPHY driver");
>> +MODULE_LICENSE("GPL v2");
>>
 
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2022-02-08 10:22 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-30  8:48 [PATCH v7 0/4] Add Naneng combo PHY support for RK3568 Yifeng Zhao
2021-12-30  8:48 ` [PATCH v7 1/4] dt-bindings: mfd: syscon: add naneng combo phy register compatible Yifeng Zhao
2021-12-31  0:12   ` Heiko Stübner
2021-12-31  8:22   ` [PATCH v7] dt-bindings: soc: grf: " Johan Jonker
2022-01-10 20:40     ` Rob Herring
2021-12-30  8:48 ` [PATCH v7 2/4] dt-bindings: phy: rockchip: Add Naneng combo PHY bindings Yifeng Zhao
2021-12-30  8:48 ` [PATCH v7 3/4] phy: rockchip: add naneng combo phy for RK3568 Yifeng Zhao
2022-01-03 18:26   ` Johan Jonker
2022-02-04 12:17     ` Johan Jonker
2022-02-08 10:22     ` zyf
2022-01-05 10:43   ` Philipp Zabel
2021-12-30  8:48 ` [PATCH v7 4/4] arm64: dts: rockchip: add naneng combo phy nodes for rk3568 Yifeng Zhao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).