linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] add the imx8 pcie phy driver support
@ 2021-09-26  7:39 Richard Zhu
  2021-09-26  7:39 ` [PATCH v2 1/4] dt-bindings: phy: phy-imx8-pcie: Add binding for the pad modes of imx8 pcie phy Richard Zhu
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Richard Zhu @ 2021-09-26  7:39 UTC (permalink / raw)
  To: l.stach, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel, linux-imx

Refer to the discussion [1] when try to enable i.MX8MM PCIe support,
one standalone PCIe PHY driver should be seperated from i.MX PCIe
driver when enable i.MX8MM PCIe support.

This patch-set adds the standalone PCIe PHY driver suport, and as a
preparatory to add the i.MX8MM PCIe support later.

The PCIe works on i.MX8MM EVK board based the the blkctrl power driver
[2] and this PHY driver patch-set.

[1] https://patchwork.ozlabs.org/project/linux-pci/patch/20210510141509.929120-3-l.stach@pengutronix.de/
[2] https://patchwork.kernel.org/project/linux-arm-kernel/cover/20210910202640.980366-1-l.stach@pengutronix.de/

Changes v1 --> v2:
- Update the license of the dt-binding header file to make the license
  compatible with dts files.
- Fix the dt_binding_check errors.

[PATCH v2 1/4] dt-bindings: phy: phy-imx8-pcie: Add binding for the
[PATCH v2 2/4] dt-bindings: phy: add imx8 pcie phy driver support
[PATCH v2 3/4] arm64: dts: imx8mm: add the pcie phy support
[PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie

Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml |  67 ++++++++++++++++++++++++++++++++
arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi                |   4 ++
arch/arm64/boot/dts/freescale/imx8mm.dtsi                    |  12 ++++++
drivers/phy/freescale/Kconfig                                |   9 +++++
drivers/phy/freescale/Makefile                               |   1 +
drivers/phy/freescale/phy-fsl-imx8-pcie.c                    | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/dt-bindings/phy/phy-imx8-pcie.h                      |  14 +++++++
7 files changed, 274 insertions(+)


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

* [PATCH v2 1/4] dt-bindings: phy: phy-imx8-pcie: Add binding for the pad modes of imx8 pcie phy
  2021-09-26  7:39 [PATCH v2 0/4] add the imx8 pcie phy driver support Richard Zhu
@ 2021-09-26  7:39 ` Richard Zhu
  2021-09-27  8:27   ` Lucas Stach
  2021-09-26  7:39 ` [PATCH v2 2/4] dt-bindings: phy: add imx8 pcie phy driver support Richard Zhu
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 15+ messages in thread
From: Richard Zhu @ 2021-09-26  7:39 UTC (permalink / raw)
  To: l.stach, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel,
	linux-imx, Richard Zhu

Add binding for reference clock PAD modes of the i.MX8 PCIe PHY.

Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
 include/dt-bindings/phy/phy-imx8-pcie.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 include/dt-bindings/phy/phy-imx8-pcie.h

diff --git a/include/dt-bindings/phy/phy-imx8-pcie.h b/include/dt-bindings/phy/phy-imx8-pcie.h
new file mode 100644
index 000000000000..59ed322f8d6c
--- /dev/null
+++ b/include/dt-bindings/phy/phy-imx8-pcie.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * This header provides constants for i.MX8 PCIe.
+ */
+
+#ifndef _DT_BINDINGS_IMX8_PCIE_H
+#define _DT_BINDINGS_IMX8_PCIE_H
+
+/* Reference clock PAD mode */
+#define IMX8_PCIE_REFCLK_PAD_NO_USED	0
+#define IMX8_PCIE_REFCLK_PAD_INPUT	1
+#define IMX8_PCIE_REFCLK_PAD_OUTPUT	2
+
+#endif /* _DT_BINDINGS_IMX8_PCIE_H */
-- 
2.25.1


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

* [PATCH v2 2/4] dt-bindings: phy: add imx8 pcie phy driver support
  2021-09-26  7:39 [PATCH v2 0/4] add the imx8 pcie phy driver support Richard Zhu
  2021-09-26  7:39 ` [PATCH v2 1/4] dt-bindings: phy: phy-imx8-pcie: Add binding for the pad modes of imx8 pcie phy Richard Zhu
@ 2021-09-26  7:39 ` Richard Zhu
  2021-09-27  8:32   ` Lucas Stach
  2021-09-26  7:39 ` [PATCH v2 3/4] arm64: dts: imx8mm: add the pcie phy support Richard Zhu
  2021-09-26  7:39 ` [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie standalone phy driver Richard Zhu
  3 siblings, 1 reply; 15+ messages in thread
From: Richard Zhu @ 2021-09-26  7:39 UTC (permalink / raw)
  To: l.stach, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel,
	linux-imx, Richard Zhu

Add dt-binding for the standalone i.MX8 PCIe PHY driver.

Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
 .../bindings/phy/fsl,imx8-pcie-phy.yaml       | 67 +++++++++++++++++++
 1 file changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml

diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml
new file mode 100644
index 000000000000..fd08897fef82
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/fsl,imx8-pcie-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX8 SoC series PCIe PHY Device Tree Bindings
+
+maintainers:
+  - Richard Zhu <hongxing.zhu@nxp.com>
+
+properties:
+  "#phy-cells":
+    const: 0
+
+  compatible:
+    enum:
+      - fsl,imx8mm-pcie-phy
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: PHY module clock
+
+  clock-names:
+    items:
+      - const: phy
+
+  fsl,refclk-pad-mode:
+    description: |
+      Specifies the mode of the refclk pad used. It can be NO_USED(PHY
+      refclock is derived from SoC internal source), INPUT(PHY refclock
+      is provided externally via the refclk pad) or OUTPUT(PHY refclock
+      is derived from SoC internal source and provided on the refclk pad).
+      Refer include/dt-bindings/phy/phy-imx8-pcie.h for the constants
+      to be used.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [ 0, 1, 2 ]
+
+required:
+  - "#phy-cells"
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - fsl,refclk-pad-mode
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/imx8mm-clock.h>
+
+    pcie_phy: pcie-phy@32f00000 {
+            compatible = "fsl,imx8mm-pcie-phy";
+            reg = <0x32f00000 0x10000>;
+            clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
+            clock-names = "phy";
+            assigned-clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
+            assigned-clock-rates = <100000000>;
+            assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_100M>;
+            fsl,refclk-pad-mode = <1>;
+            #phy-cells = <0>;
+    };
+...
-- 
2.25.1


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

* [PATCH v2 3/4] arm64: dts: imx8mm: add the pcie phy support
  2021-09-26  7:39 [PATCH v2 0/4] add the imx8 pcie phy driver support Richard Zhu
  2021-09-26  7:39 ` [PATCH v2 1/4] dt-bindings: phy: phy-imx8-pcie: Add binding for the pad modes of imx8 pcie phy Richard Zhu
  2021-09-26  7:39 ` [PATCH v2 2/4] dt-bindings: phy: add imx8 pcie phy driver support Richard Zhu
@ 2021-09-26  7:39 ` Richard Zhu
  2021-09-27  8:35   ` Lucas Stach
  2021-09-26  7:39 ` [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie standalone phy driver Richard Zhu
  3 siblings, 1 reply; 15+ messages in thread
From: Richard Zhu @ 2021-09-26  7:39 UTC (permalink / raw)
  To: l.stach, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel,
	linux-imx, Richard Zhu

Add the PCIe PHY support on iMX8MM platforms.

Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi |  4 ++++
 arch/arm64/boot/dts/freescale/imx8mm.dtsi     | 12 ++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
index e033d0257b5a..e7f398433486 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
@@ -289,6 +289,10 @@ pca6416: gpio@20 {
 	};
 };
 
+&pcie_phy {
+	status = "okay";
+};
+
 &sai3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_sai3>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index e7648c3b8390..de231d531ba4 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -998,6 +998,18 @@ usbmisc2: usbmisc@32e50200 {
 				reg = <0x32e50200 0x200>;
 			};
 
+			pcie_phy: pcie-phy@32f00000 {
+				compatible = "fsl,imx8mm-pcie-phy";
+				reg = <0x32f00000 0x10000>;
+				clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
+				clock-names = "phy";
+				assigned-clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
+				assigned-clock-rates = <100000000>;
+				assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_100M>;
+				#phy-cells = <0>;
+				fsl,refclk-pad-mode = <1>;
+				status = "disabled";
+			};
 		};
 
 		dma_apbh: dma-controller@33000000 {
-- 
2.25.1


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

* [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie standalone phy driver
  2021-09-26  7:39 [PATCH v2 0/4] add the imx8 pcie phy driver support Richard Zhu
                   ` (2 preceding siblings ...)
  2021-09-26  7:39 ` [PATCH v2 3/4] arm64: dts: imx8mm: add the pcie phy support Richard Zhu
@ 2021-09-26  7:39 ` Richard Zhu
  2021-09-27  8:43   ` Lucas Stach
  3 siblings, 1 reply; 15+ messages in thread
From: Richard Zhu @ 2021-09-26  7:39 UTC (permalink / raw)
  To: l.stach, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel,
	linux-imx, Richard Zhu

Add the standalone i.MX8 PCIe PHY driver.
Some reset bits should be manipulated between PHY configurations and
status check(internal PLL is locked or not).
So, do the PHY configuration in the phy_calibrate().
And check the PHY is ready or not in the phy_init().

Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
 drivers/phy/freescale/Kconfig             |   9 ++
 drivers/phy/freescale/Makefile            |   1 +
 drivers/phy/freescale/phy-fsl-imx8-pcie.c | 167 ++++++++++++++++++++++
 3 files changed, 177 insertions(+)
 create mode 100644 drivers/phy/freescale/phy-fsl-imx8-pcie.c

diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
index 320630ffe3cd..da078a676fbc 100644
--- a/drivers/phy/freescale/Kconfig
+++ b/drivers/phy/freescale/Kconfig
@@ -14,3 +14,12 @@ config PHY_MIXEL_MIPI_DPHY
 	help
 	  Enable this to add support for the Mixel DSI PHY as found
 	  on NXP's i.MX8 family of SOCs.
+
+config PHY_FSL_IMX8_PCIE
+	tristate "Freescale i.MX8 PCIE PHY"
+	depends on OF && HAS_IOMEM
+	select GENERIC_PHY
+	default ARCH_MXC
+	help
+	  Enable this to add support for the PCIE PHY as found on i.MX8
+	  family of SOCs.
diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
index 1d02e3869b45..9fd467b58621 100644
--- a/drivers/phy/freescale/Makefile
+++ b/drivers/phy/freescale/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_PHY_FSL_IMX8MQ_USB)	+= phy-fsl-imx8mq-usb.o
 obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY)	+= phy-fsl-imx8-mipi-dphy.o
+obj-$(CONFIG_PHY_FSL_IMX8_PCIE)		+= phy-fsl-imx8-pcie.o
diff --git a/drivers/phy/freescale/phy-fsl-imx8-pcie.c b/drivers/phy/freescale/phy-fsl-imx8-pcie.c
new file mode 100644
index 000000000000..ff47d6b83686
--- /dev/null
+++ b/drivers/phy/freescale/phy-fsl-imx8-pcie.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 NXP
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <dt-binding/phy/phy-fsl-imx8-pcie.h>
+
+#define IMX8MM_PCIE_PHY_CMN_REG061	0x184
+#define  ANA_PLL_CLK_OUT_TO_EXT_IO_EN	BIT(0)
+#define IMX8MM_PCIE_PHY_CMN_REG062	0x188
+#define  ANA_PLL_CLK_OUT_TO_EXT_IO_SEL	BIT(3)
+#define IMX8MM_PCIE_PHY_CMN_REG063	0x18C
+#define  AUX_PLL_REFCLK_SEL_SYS_PLL	GENMASK(7, 6)
+#define IMX8MM_PCIE_PHY_CMN_REG064	0x190
+#define  ANA_AUX_RX_TX_SEL_TX		BIT(7)
+#define  ANA_AUX_RX_TERM_GND_EN		BIT(3)
+#define  ANA_AUX_TX_TERM		BIT(2)
+#define IMX8MM_PCIE_PHY_CMN_REG065	0x194
+#define  ANA_AUX_RX_TERM		(BIT(7) | BIT(4))
+#define  ANA_AUX_TX_LVL			GENMASK(3, 0)
+#define IMX8MM_PCIE_PHY_CMN_REG75	0x1D4
+#define  PCIE_PHY_CMN_REG75_PLL_DONE	0x3
+#define PCIE_PHY_TRSV_REG5		0x414
+#define  PCIE_PHY_TRSV_REG5_GEN1_DEEMP	0x2D
+#define PCIE_PHY_TRSV_REG6		0x418
+#define  PCIE_PHY_TRSV_REG6_GEN2_DEEMP	0xF
+
+struct imx8_pcie_phy {
+	u32		refclk_pad_mode;
+	void __iomem	*base;
+	struct clk	*clk;
+	struct phy	*phy;
+};
+
+static int imx8_pcie_phy_init(struct phy *phy)
+{
+	int ret;
+	u32 val;
+	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
+
+	ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG75,
+				 val, val == PCIE_PHY_CMN_REG75_PLL_DONE,
+				 10, 20000);
+	return ret;
+}
+
+static int imx8_pcie_phy_cal(struct phy *phy)
+{
+	u32 value, pad_mode;
+	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
+
+	pad_mode = imx8_phy->refclk_pad_mode;
+	if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
+		/* Configure the pad as input */
+		value = readl(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
+		writel(value & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
+		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
+	} else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
+		/* Configure the PHY to output the refclock via pad */
+		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
+		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
+		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
+		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
+		writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
+		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
+		value = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
+		writel(value | ANA_AUX_RX_TERM_GND_EN,
+		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
+		writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
+		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
+	}
+
+	/* Tune PHY de-emphasis setting to pass PCIe compliance. */
+	writel(PCIE_PHY_TRSV_REG5_GEN1_DEEMP,
+	       imx8_phy->base + PCIE_PHY_TRSV_REG5);
+	writel(PCIE_PHY_TRSV_REG6_GEN2_DEEMP,
+	       imx8_phy->base + PCIE_PHY_TRSV_REG6);
+
+	return 0;
+}
+
+static int imx8_pcie_phy_power_on(struct phy *phy)
+{
+	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
+
+	return clk_prepare_enable(imx8_phy->clk);
+}
+
+static int imx8_pcie_phy_power_off(struct phy *phy)
+{
+	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
+
+	clk_disable_unprepare(imx8_phy->clk);
+
+	return 0;
+}
+
+static const struct phy_ops imx8_pcie_phy_ops = {
+	.init		= imx8_pcie_phy_init,
+	.calibrate	= imx8_pcie_phy_cal,
+	.power_on	= imx8_pcie_phy_power_on,
+	.power_off	= imx8_pcie_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static int imx8_pcie_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct imx8_pcie_phy *imx8_phy;
+	struct resource *res;
+
+	imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL);
+	if (!imx8_phy)
+		return -ENOMEM;
+
+	/* get PHY refclk pad mode */
+	of_property_read_u32(np, "fsl,refclk-pad-mode",
+			     &imx8_phy->refclk_pad_mode);
+
+	imx8_phy->clk = devm_clk_get(dev, "phy");
+	if (IS_ERR(imx8_phy->clk)) {
+		dev_err(dev, "failed to get imx pcie phy clock\n");
+		return PTR_ERR(imx8_phy->clk);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	imx8_phy->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(imx8_phy->base))
+		return PTR_ERR(imx8_phy->base);
+
+	imx8_phy->phy = devm_phy_create(dev, NULL, &imx8_pcie_phy_ops);
+	if (IS_ERR(imx8_phy->phy))
+		return PTR_ERR(imx8_phy->phy);
+
+	phy_set_drvdata(imx8_phy->phy, imx8_phy);
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id imx8_pcie_phy_of_match[] = {
+	{.compatible = "fsl,imx8mm-pcie-phy",},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
+
+static struct platform_driver imx8_pcie_phy_driver = {
+	.probe	= imx8_pcie_phy_probe,
+	.driver = {
+		.name	= "imx8-pcie-phy",
+		.of_match_table	= imx8_pcie_phy_of_match,
+	}
+};
+module_platform_driver(imx8_pcie_phy_driver);
+
+MODULE_DESCRIPTION("FSL IMX8 PCIE PHY driver");
+MODULE_LICENSE("GPL");
-- 
2.25.1


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

* Re: [PATCH v2 1/4] dt-bindings: phy: phy-imx8-pcie: Add binding for the pad modes of imx8 pcie phy
  2021-09-26  7:39 ` [PATCH v2 1/4] dt-bindings: phy: phy-imx8-pcie: Add binding for the pad modes of imx8 pcie phy Richard Zhu
@ 2021-09-27  8:27   ` Lucas Stach
  2021-09-28  2:28     ` Richard Zhu
  0 siblings, 1 reply; 15+ messages in thread
From: Lucas Stach @ 2021-09-27  8:27 UTC (permalink / raw)
  To: Richard Zhu, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel, linux-imx

Am Sonntag, dem 26.09.2021 um 15:39 +0800 schrieb Richard Zhu:
> Add binding for reference clock PAD modes of the i.MX8 PCIe PHY.
> 
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
>  include/dt-bindings/phy/phy-imx8-pcie.h | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
>  create mode 100644 include/dt-bindings/phy/phy-imx8-pcie.h
> 
> diff --git a/include/dt-bindings/phy/phy-imx8-pcie.h b/include/dt-bindings/phy/phy-imx8-pcie.h
> new file mode 100644
> index 000000000000..59ed322f8d6c
> --- /dev/null
> +++ b/include/dt-bindings/phy/phy-imx8-pcie.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */

This should be (GPL-2.0+ OR MIT) to be compatible with the license of
the DTSI file it is included in.

> +/*
> + * This header provides constants for i.MX8 PCIe.
> + */
> +
> +#ifndef _DT_BINDINGS_IMX8_PCIE_H
> +#define _DT_BINDINGS_IMX8_PCIE_H
> +
> +/* Reference clock PAD mode */
> +#define IMX8_PCIE_REFCLK_PAD_NO_USED	0

I think _UNUSED would be the more idiomatic way to call this.

> +#define IMX8_PCIE_REFCLK_PAD_INPUT	1
> +#define IMX8_PCIE_REFCLK_PAD_OUTPUT	2
> +
> +#endif /* _DT_BINDINGS_IMX8_PCIE_H */



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

* Re: [PATCH v2 2/4] dt-bindings: phy: add imx8 pcie phy driver support
  2021-09-26  7:39 ` [PATCH v2 2/4] dt-bindings: phy: add imx8 pcie phy driver support Richard Zhu
@ 2021-09-27  8:32   ` Lucas Stach
  2021-09-28  2:37     ` Richard Zhu
  0 siblings, 1 reply; 15+ messages in thread
From: Lucas Stach @ 2021-09-27  8:32 UTC (permalink / raw)
  To: Richard Zhu, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel, linux-imx

Am Sonntag, dem 26.09.2021 um 15:39 +0800 schrieb Richard Zhu:
> Add dt-binding for the standalone i.MX8 PCIe PHY driver.
> 
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
>  .../bindings/phy/fsl,imx8-pcie-phy.yaml       | 67 +++++++++++++++++++
>  1 file changed, 67 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml
> 
> diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml
> new file mode 100644
> index 000000000000..fd08897fef82
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml
> @@ -0,0 +1,67 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/fsl,imx8-pcie-phy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Freescale i.MX8 SoC series PCIe PHY Device Tree Bindings
> +
> +maintainers:
> +  - Richard Zhu <hongxing.zhu@nxp.com>
> +
> +properties:
> +  "#phy-cells":
> +    const: 0
> +
> +  compatible:
> +    enum:
> +      - fsl,imx8mm-pcie-phy
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    items:
> +      - description: PHY module clock
> +
> +  clock-names:
> +    items:
> +      - const: phy

The clock name should describe what it is used for in the hardware
block described by the DT node. So I would think this should be called
"ref" or something like this, as I believe this clock is really only
used as the reference clock and can be disabled when the refclock is
supplied via the pad, right?
 
> +
> +  fsl,refclk-pad-mode:
> +    description: |
> +      Specifies the mode of the refclk pad used. It can be NO_USED(PHY
> +      refclock is derived from SoC internal source), INPUT(PHY refclock
> +      is provided externally via the refclk pad) or OUTPUT(PHY refclock
> +      is derived from SoC internal source and provided on the refclk pad).
> +      Refer include/dt-bindings/phy/phy-imx8-pcie.h for the constants
> +      to be used.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    enum: [ 0, 1, 2 ]
> +
> +required:
> +  - "#phy-cells"
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +  - fsl,refclk-pad-mode
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/imx8mm-clock.h>
> +
> +    pcie_phy: pcie-phy@32f00000 {
> +            compatible = "fsl,imx8mm-pcie-phy";
> +            reg = <0x32f00000 0x10000>;
> +            clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
> +            clock-names = "phy";
> +            assigned-clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
> +            assigned-clock-rates = <100000000>;
> +            assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_100M>;
> +            fsl,refclk-pad-mode = <1>;

Include the new header added in patch 1 and use the enum.

> +            #phy-cells = <0>;
> +    };
> +...



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

* Re: [PATCH v2 3/4] arm64: dts: imx8mm: add the pcie phy support
  2021-09-26  7:39 ` [PATCH v2 3/4] arm64: dts: imx8mm: add the pcie phy support Richard Zhu
@ 2021-09-27  8:35   ` Lucas Stach
  2021-09-28  2:38     ` Richard Zhu
  0 siblings, 1 reply; 15+ messages in thread
From: Lucas Stach @ 2021-09-27  8:35 UTC (permalink / raw)
  To: Richard Zhu, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel, linux-imx

Am Sonntag, dem 26.09.2021 um 15:39 +0800 schrieb Richard Zhu:
> Add the PCIe PHY support on iMX8MM platforms.
> 
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
>  arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi |  4 ++++
>  arch/arm64/boot/dts/freescale/imx8mm.dtsi     | 12 ++++++++++++

This should be split into 2 patches: one for the SoC and one for the
EVK board.

>  2 files changed, 16 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
> index e033d0257b5a..e7f398433486 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
> @@ -289,6 +289,10 @@ pca6416: gpio@20 {
>  	};
>  };
>  
> +&pcie_phy {
> +	status = "okay";
> +};
> +
>  &sai3 {
>  	pinctrl-names = "default";
>  	pinctrl-0 = <&pinctrl_sai3>;
> diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
> index e7648c3b8390..de231d531ba4 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
> @@ -998,6 +998,18 @@ usbmisc2: usbmisc@32e50200 {
>  				reg = <0x32e50200 0x200>;
>  			};
>  
> +			pcie_phy: pcie-phy@32f00000 {
> +				compatible = "fsl,imx8mm-pcie-phy";
> +				reg = <0x32f00000 0x10000>;
> +				clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
> +				clock-names = "phy";
> +				assigned-clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
> +				assigned-clock-rates = <100000000>;
> +				assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_100M>;
> +				#phy-cells = <0>;
> +				fsl,refclk-pad-mode = <1>;

Move this to the board DT, as the pad mode is a board level decision.
Also use the enum instead of raw value.

> +				status = "disabled";
> +			};
>  		};
>  
>  		dma_apbh: dma-controller@33000000 {



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

* Re: [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie standalone phy driver
  2021-09-26  7:39 ` [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie standalone phy driver Richard Zhu
@ 2021-09-27  8:43   ` Lucas Stach
  2021-09-28  7:09     ` Richard Zhu
  0 siblings, 1 reply; 15+ messages in thread
From: Lucas Stach @ 2021-09-27  8:43 UTC (permalink / raw)
  To: Richard Zhu, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel, linux-imx

Am Sonntag, dem 26.09.2021 um 15:39 +0800 schrieb Richard Zhu:
> Add the standalone i.MX8 PCIe PHY driver.
> Some reset bits should be manipulated between PHY configurations and
> status check(internal PLL is locked or not).
> So, do the PHY configuration in the phy_calibrate().
> And check the PHY is ready or not in the phy_init().

I would really like to see the PCIe controller driver side of this
also, as it's hard to review standalone. For example I'm not sure if
some of those reset bits should also be driven from the PHY driver,
even if they are currently hooked up to the controller driver.

Also I think the IOMUX GPR register handling belongs in the PHY driver,
as it's configuring the reference clock routing.

> 
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
>  drivers/phy/freescale/Kconfig             |   9 ++
>  drivers/phy/freescale/Makefile            |   1 +
>  drivers/phy/freescale/phy-fsl-imx8-pcie.c | 167 ++++++++++++++++++++++
>  3 files changed, 177 insertions(+)
>  create mode 100644 drivers/phy/freescale/phy-fsl-imx8-pcie.c

From what I know, there are several quite different PCIe PHYs used in
the different i.MX8 variants. I'm not sure if we want to stuff them all
into one file. I guess we should be more specific here and call this
imx8m-phy, or even imx8mm-phy.

> 
> diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
> index 320630ffe3cd..da078a676fbc 100644
> --- a/drivers/phy/freescale/Kconfig
> +++ b/drivers/phy/freescale/Kconfig
> @@ -14,3 +14,12 @@ config PHY_MIXEL_MIPI_DPHY
>  	help
>  	  Enable this to add support for the Mixel DSI PHY as found
>  	  on NXP's i.MX8 family of SOCs.
> +
> +config PHY_FSL_IMX8_PCIE
> +	tristate "Freescale i.MX8 PCIE PHY"
> +	depends on OF && HAS_IOMEM
> +	select GENERIC_PHY
> +	default ARCH_MXC
> +	help
> +	  Enable this to add support for the PCIE PHY as found on i.MX8
> +	  family of SOCs.
> diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
> index 1d02e3869b45..9fd467b58621 100644
> --- a/drivers/phy/freescale/Makefile
> +++ b/drivers/phy/freescale/Makefile
> @@ -1,3 +1,4 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-$(CONFIG_PHY_FSL_IMX8MQ_USB)	+= phy-fsl-imx8mq-usb.o
>  obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY)	+= phy-fsl-imx8-mipi-dphy.o
> +obj-$(CONFIG_PHY_FSL_IMX8_PCIE)		+= phy-fsl-imx8-pcie.o
> diff --git a/drivers/phy/freescale/phy-fsl-imx8-pcie.c b/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> new file mode 100644
> index 000000000000..ff47d6b83686
> --- /dev/null
> +++ b/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> @@ -0,0 +1,167 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2021 NXP
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <dt-binding/phy/phy-fsl-imx8-pcie.h>
> +
> +#define IMX8MM_PCIE_PHY_CMN_REG061	0x184
> +#define  ANA_PLL_CLK_OUT_TO_EXT_IO_EN	BIT(0)
> +#define IMX8MM_PCIE_PHY_CMN_REG062	0x188
> +#define  ANA_PLL_CLK_OUT_TO_EXT_IO_SEL	BIT(3)
> +#define IMX8MM_PCIE_PHY_CMN_REG063	0x18C
> +#define  AUX_PLL_REFCLK_SEL_SYS_PLL	GENMASK(7, 6)
> +#define IMX8MM_PCIE_PHY_CMN_REG064	0x190
> +#define  ANA_AUX_RX_TX_SEL_TX		BIT(7)
> +#define  ANA_AUX_RX_TERM_GND_EN		BIT(3)
> +#define  ANA_AUX_TX_TERM		BIT(2)
> +#define IMX8MM_PCIE_PHY_CMN_REG065	0x194
> +#define  ANA_AUX_RX_TERM		(BIT(7) | BIT(4))
> +#define  ANA_AUX_TX_LVL			GENMASK(3, 0)
> +#define IMX8MM_PCIE_PHY_CMN_REG75	0x1D4
> +#define  PCIE_PHY_CMN_REG75_PLL_DONE	0x3
> +#define PCIE_PHY_TRSV_REG5		0x414
> +#define  PCIE_PHY_TRSV_REG5_GEN1_DEEMP	0x2D
> +#define PCIE_PHY_TRSV_REG6		0x418
> +#define  PCIE_PHY_TRSV_REG6_GEN2_DEEMP	0xF
> +
> +struct imx8_pcie_phy {
> +	u32		refclk_pad_mode;
> +	void __iomem	*base;
> +	struct clk	*clk;
> +	struct phy	*phy;
> +};
> +
> +static int imx8_pcie_phy_init(struct phy *phy)
> +{
> +	int ret;
> +	u32 val;
> +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> +
> +	ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG75,
> +				 val, val == PCIE_PHY_CMN_REG75_PLL_DONE,
> +				 10, 20000);
> +	return ret;
> +}
> +
> +static int imx8_pcie_phy_cal(struct phy *phy)
> +{
> +	u32 value, pad_mode;
> +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> +
> +	pad_mode = imx8_phy->refclk_pad_mode;
> +	if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
> +		/* Configure the pad as input */
> +		value = readl(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
> +		writel(value & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
> +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
> +	} else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
> +		/* Configure the PHY to output the refclock via pad */
> +		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
> +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
> +		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
> +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
> +		writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
> +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
> +		value = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
> +		writel(value | ANA_AUX_RX_TERM_GND_EN,
> +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
> +		writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
> +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
> +	}
> +
> +	/* Tune PHY de-emphasis setting to pass PCIe compliance. */
> +	writel(PCIE_PHY_TRSV_REG5_GEN1_DEEMP,
> +	       imx8_phy->base + PCIE_PHY_TRSV_REG5);
> +	writel(PCIE_PHY_TRSV_REG6_GEN2_DEEMP,
> +	       imx8_phy->base + PCIE_PHY_TRSV_REG6);
> +
> +	return 0;
> +}
> +
> +static int imx8_pcie_phy_power_on(struct phy *phy)
> +{
> +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> +
> +	return clk_prepare_enable(imx8_phy->clk);

Do we need to enable this clock when the refclock is supplied
externally via the pad?

> +}
> +
> +static int imx8_pcie_phy_power_off(struct phy *phy)
> +{
> +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> +
> +	clk_disable_unprepare(imx8_phy->clk);
> +
> +	return 0;
> +}
> +
> +static const struct phy_ops imx8_pcie_phy_ops = {
> +	.init		= imx8_pcie_phy_init,
> +	.calibrate	= imx8_pcie_phy_cal,
> +	.power_on	= imx8_pcie_phy_power_on,
> +	.power_off	= imx8_pcie_phy_power_off,
> +	.owner		= THIS_MODULE,
> +};
> +
> +static int imx8_pcie_phy_probe(struct platform_device *pdev)
> +{
> +	struct phy_provider *phy_provider;
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct imx8_pcie_phy *imx8_phy;
> +	struct resource *res;
> +
> +	imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL);
> +	if (!imx8_phy)
> +		return -ENOMEM;
> +
> +	/* get PHY refclk pad mode */
> +	of_property_read_u32(np, "fsl,refclk-pad-mode",
> +			     &imx8_phy->refclk_pad_mode);
> +
> +	imx8_phy->clk = devm_clk_get(dev, "phy");
> +	if (IS_ERR(imx8_phy->clk)) {
> +		dev_err(dev, "failed to get imx pcie phy clock\n");
> +		return PTR_ERR(imx8_phy->clk);
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	imx8_phy->base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(imx8_phy->base))
> +		return PTR_ERR(imx8_phy->base);
> +
> +	imx8_phy->phy = devm_phy_create(dev, NULL, &imx8_pcie_phy_ops);
> +	if (IS_ERR(imx8_phy->phy))
> +		return PTR_ERR(imx8_phy->phy);
> +
> +	phy_set_drvdata(imx8_phy->phy, imx8_phy);
> +
> +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> +	return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static const struct of_device_id imx8_pcie_phy_of_match[] = {
> +	{.compatible = "fsl,imx8mm-pcie-phy",},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
> +
> +static struct platform_driver imx8_pcie_phy_driver = {
> +	.probe	= imx8_pcie_phy_probe,
> +	.driver = {
> +		.name	= "imx8-pcie-phy",
> +		.of_match_table	= imx8_pcie_phy_of_match,
> +	}
> +};
> +module_platform_driver(imx8_pcie_phy_driver);
> +
> +MODULE_DESCRIPTION("FSL IMX8 PCIE PHY driver");
> +MODULE_LICENSE("GPL");



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

* RE: [PATCH v2 1/4] dt-bindings: phy: phy-imx8-pcie: Add binding for the pad modes of imx8 pcie phy
  2021-09-27  8:27   ` Lucas Stach
@ 2021-09-28  2:28     ` Richard Zhu
  0 siblings, 0 replies; 15+ messages in thread
From: Richard Zhu @ 2021-09-28  2:28 UTC (permalink / raw)
  To: Lucas Stach, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel,
	dl-linux-imx


> -----Original Message-----
> From: Lucas Stach <l.stach@pengutronix.de>
> Sent: Monday, September 27, 2021 4:27 PM
> To: Richard Zhu <hongxing.zhu@nxp.com>; kishon@ti.com; vkoul@kernel.org;
> robh@kernel.org; galak@kernel.crashing.org; shawnguo@kernel.org
> Cc: linux-phy@lists.infradead.org; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> kernel@pengutronix.de; dl-linux-imx <linux-imx@nxp.com>
> Subject: Re: [PATCH v2 1/4] dt-bindings: phy: phy-imx8-pcie: Add binding for
> the pad modes of imx8 pcie phy
> 
> Am Sonntag, dem 26.09.2021 um 15:39 +0800 schrieb Richard Zhu:
> > Add binding for reference clock PAD modes of the i.MX8 PCIe PHY.
> >
> > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > ---
> >  include/dt-bindings/phy/phy-imx8-pcie.h | 14 ++++++++++++++
> >  1 file changed, 14 insertions(+)
> >  create mode 100644 include/dt-bindings/phy/phy-imx8-pcie.h
> >
> > diff --git a/include/dt-bindings/phy/phy-imx8-pcie.h
> > b/include/dt-bindings/phy/phy-imx8-pcie.h
> > new file mode 100644
> > index 000000000000..59ed322f8d6c
> > --- /dev/null
> > +++ b/include/dt-bindings/phy/phy-imx8-pcie.h
> > @@ -0,0 +1,14 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> 
> This should be (GPL-2.0+ OR MIT) to be compatible with the license of the
> DTSI file it is included in.
[Richard Zhu] Thanks for your comments. Okay, would be changed as this one later.

> 
> > +/*
> > + * This header provides constants for i.MX8 PCIe.
> > + */
> > +
> > +#ifndef _DT_BINDINGS_IMX8_PCIE_H
> > +#define _DT_BINDINGS_IMX8_PCIE_H
> > +
> > +/* Reference clock PAD mode */
> > +#define IMX8_PCIE_REFCLK_PAD_NO_USED	0
> 
> I think _UNUSED would be the more idiomatic way to call this.
> 
[Richard Zhu] Okay, got that. Thanks.

Best Regards
Richard Zhu
> > +#define IMX8_PCIE_REFCLK_PAD_INPUT	1
> > +#define IMX8_PCIE_REFCLK_PAD_OUTPUT	2
> > +
> > +#endif /* _DT_BINDINGS_IMX8_PCIE_H */
> 


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

* RE: [PATCH v2 2/4] dt-bindings: phy: add imx8 pcie phy driver support
  2021-09-27  8:32   ` Lucas Stach
@ 2021-09-28  2:37     ` Richard Zhu
  0 siblings, 0 replies; 15+ messages in thread
From: Richard Zhu @ 2021-09-28  2:37 UTC (permalink / raw)
  To: Lucas Stach, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel,
	dl-linux-imx


> -----Original Message-----
> From: Lucas Stach <l.stach@pengutronix.de>
> Sent: Monday, September 27, 2021 4:33 PM
> To: Richard Zhu <hongxing.zhu@nxp.com>; kishon@ti.com; vkoul@kernel.org;
> robh@kernel.org; galak@kernel.crashing.org; shawnguo@kernel.org
> Cc: linux-phy@lists.infradead.org; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> kernel@pengutronix.de; dl-linux-imx <linux-imx@nxp.com>
> Subject: Re: [PATCH v2 2/4] dt-bindings: phy: add imx8 pcie phy driver support
> 
> Am Sonntag, dem 26.09.2021 um 15:39 +0800 schrieb Richard Zhu:
> > Add dt-binding for the standalone i.MX8 PCIe PHY driver.
> >
> > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > ---
> >  .../bindings/phy/fsl,imx8-pcie-phy.yaml       | 67
> +++++++++++++++++++
> >  1 file changed, 67 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml
> >
> > diff --git
> > a/Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml
> > b/Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml
> > new file mode 100644
> > index 000000000000..fd08897fef82
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/phy/fsl,imx8-pcie-phy.yaml
> > @@ -0,0 +1,67 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2
> > +---
> > +$id:
> > +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevi
> >
> +cetree.org%2Fschemas%2Fphy%2Ffsl%2Cimx8-pcie-phy.yaml%23&amp;dat
> a=04%
> >
> +7C01%7Chongxing.zhu%40nxp.com%7C7c5f7203447a4c259d9f08d981915ef
> 3%7C68
> >
> +6ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637683283637916778%
> 7CUnknown
> >
> +%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1ha
> WwiLC
> >
> +JXVCI6Mn0%3D%7C1000&amp;sdata=m1S7Si0nL4zveL76S%2FvpKbFFrWhJa
> mFNgcVld
> > +Rxx82I%3D&amp;reserved=0
> > +$schema:
> > +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevi
> >
> +cetree.org%2Fmeta-schemas%2Fcore.yaml%23&amp;data=04%7C01%7Cho
> ngxing.
> >
> +zhu%40nxp.com%7C7c5f7203447a4c259d9f08d981915ef3%7C686ea1d3bc
> 2b4c6fa9
> >
> +2cd99c5c301635%7C0%7C0%7C637683283637916778%7CUnknown%7CT
> WFpbGZsb3d8e
> >
> +yJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3
> D%7C1
> >
> +000&amp;sdata=S2uWTI603YkF68zqySbkcK32XaPEwU4%2BHuntwR%2Bkx7
> g%3D&amp;
> > +reserved=0
> > +
> > +title: Freescale i.MX8 SoC series PCIe PHY Device Tree Bindings
> > +
> > +maintainers:
> > +  - Richard Zhu <hongxing.zhu@nxp.com>
> > +
> > +properties:
> > +  "#phy-cells":
> > +    const: 0
> > +
> > +  compatible:
> > +    enum:
> > +      - fsl,imx8mm-pcie-phy
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    items:
> > +      - description: PHY module clock
> > +
> > +  clock-names:
> > +    items:
> > +      - const: phy
> 
> The clock name should describe what it is used for in the hardware block
> described by the DT node. So I would think this should be called "ref" or
> something like this, as I believe this clock is really only used as the reference
> clock and can be disabled when the refclock is supplied via the pad, right?
> 
[Richard Zhu] That's right. "ref" is better. Thanks.

> > +
> > +  fsl,refclk-pad-mode:
> > +    description: |
> > +      Specifies the mode of the refclk pad used. It can be NO_USED(PHY
> > +      refclock is derived from SoC internal source), INPUT(PHY refclock
> > +      is provided externally via the refclk pad) or OUTPUT(PHY refclock
> > +      is derived from SoC internal source and provided on the refclk pad).
> > +      Refer include/dt-bindings/phy/phy-imx8-pcie.h for the constants
> > +      to be used.
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    enum: [ 0, 1, 2 ]
> > +
> > +required:
> > +  - "#phy-cells"
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - clock-names
> > +  - fsl,refclk-pad-mode
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/clock/imx8mm-clock.h>
> > +
> > +    pcie_phy: pcie-phy@32f00000 {
> > +            compatible = "fsl,imx8mm-pcie-phy";
> > +            reg = <0x32f00000 0x10000>;
> > +            clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
> > +            clock-names = "phy";
> > +            assigned-clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
> > +            assigned-clock-rates = <100000000>;
> > +            assigned-clock-parents = <&clk
> IMX8MM_SYS_PLL2_100M>;
> > +            fsl,refclk-pad-mode = <1>;
> 
> Include the new header added in patch 1 and use the enum.
[Richard Zhu] Got that, would changed in next version. Thanks.
> 
> > +            #phy-cells = <0>;
> > +    };
> > +...
> 


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

* RE: [PATCH v2 3/4] arm64: dts: imx8mm: add the pcie phy support
  2021-09-27  8:35   ` Lucas Stach
@ 2021-09-28  2:38     ` Richard Zhu
  0 siblings, 0 replies; 15+ messages in thread
From: Richard Zhu @ 2021-09-28  2:38 UTC (permalink / raw)
  To: Lucas Stach, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel,
	dl-linux-imx

> -----Original Message-----
> From: Lucas Stach <l.stach@pengutronix.de>
> Sent: Monday, September 27, 2021 4:35 PM
> To: Richard Zhu <hongxing.zhu@nxp.com>; kishon@ti.com; vkoul@kernel.org;
> robh@kernel.org; galak@kernel.crashing.org; shawnguo@kernel.org
> Cc: linux-phy@lists.infradead.org; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> kernel@pengutronix.de; dl-linux-imx <linux-imx@nxp.com>
> Subject: Re: [PATCH v2 3/4] arm64: dts: imx8mm: add the pcie phy support
> 
> Am Sonntag, dem 26.09.2021 um 15:39 +0800 schrieb Richard Zhu:
> > Add the PCIe PHY support on iMX8MM platforms.
> >
> > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > ---
> >  arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi |  4 ++++
> >  arch/arm64/boot/dts/freescale/imx8mm.dtsi     | 12 ++++++++++++
> 
> This should be split into 2 patches: one for the SoC and one for the EVK board.
> 
[Richard Zhu] Okay, would split this patch into 2 patches later. Thanks.

> >  2 files changed, 16 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
> > b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
> > index e033d0257b5a..e7f398433486 100644
> > --- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
> > +++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
> > @@ -289,6 +289,10 @@ pca6416: gpio@20 {
> >  	};
> >  };
> >
> > +&pcie_phy {
> > +	status = "okay";
> > +};
> > +
> >  &sai3 {
> >  	pinctrl-names = "default";
> >  	pinctrl-0 = <&pinctrl_sai3>;
> > diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
> > b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
> > index e7648c3b8390..de231d531ba4 100644
> > --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
> > +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
> > @@ -998,6 +998,18 @@ usbmisc2: usbmisc@32e50200 {
> >  				reg = <0x32e50200 0x200>;
> >  			};
> >
> > +			pcie_phy: pcie-phy@32f00000 {
> > +				compatible = "fsl,imx8mm-pcie-phy";
> > +				reg = <0x32f00000 0x10000>;
> > +				clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
> > +				clock-names = "phy";
> > +				assigned-clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
> > +				assigned-clock-rates = <100000000>;
> > +				assigned-clock-parents = <&clk
> IMX8MM_SYS_PLL2_100M>;
> > +				#phy-cells = <0>;
> > +				fsl,refclk-pad-mode = <1>;
> 
> Move this to the board DT, as the pad mode is a board level decision.
> Also use the enum instead of raw value.
[Richard Zhu] Got that, thanks.
> 
> > +				status = "disabled";
> > +			};
> >  		};
> >
> >  		dma_apbh: dma-controller@33000000 {
> 


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

* RE: [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie standalone phy driver
  2021-09-27  8:43   ` Lucas Stach
@ 2021-09-28  7:09     ` Richard Zhu
  2021-09-28  8:43       ` Lucas Stach
  0 siblings, 1 reply; 15+ messages in thread
From: Richard Zhu @ 2021-09-28  7:09 UTC (permalink / raw)
  To: Lucas Stach, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel,
	dl-linux-imx

> -----Original Message-----
> From: Lucas Stach <l.stach@pengutronix.de>
> Sent: Monday, September 27, 2021 4:43 PM
> To: Richard Zhu <hongxing.zhu@nxp.com>; kishon@ti.com; vkoul@kernel.org;
> robh@kernel.org; galak@kernel.crashing.org; shawnguo@kernel.org
> Cc: linux-phy@lists.infradead.org; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> kernel@pengutronix.de; dl-linux-imx <linux-imx@nxp.com>
> Subject: Re: [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie
> standalone phy driver
> 
> Am Sonntag, dem 26.09.2021 um 15:39 +0800 schrieb Richard Zhu:
> > Add the standalone i.MX8 PCIe PHY driver.
> > Some reset bits should be manipulated between PHY configurations and
> > status check(internal PLL is locked or not).
> > So, do the PHY configuration in the phy_calibrate().
> > And check the PHY is ready or not in the phy_init().
> 
> I would really like to see the PCIe controller driver side of this also, as it's hard
> to review standalone. For example I'm not sure if some of those reset bits
> should also be driven from the PHY driver, even if they are currently hooked
> up to the controller driver.
> 
> Also I think the IOMUX GPR register handling belongs in the PHY driver, as it's
> configuring the reference clock routing.
> 
[Richard Zhu] Sorry to bring inconvenience to you. I would send out the v3
 patch-set and the i.MX8MM PCIe controller driver patches after I'm back from the
 national holiday tomorrow(about one week). 
Although most of the IOMUX GPR bits are related to PHY, but there are some bits are
 defined only for controller. For example, the device_type of the controller, the clkreq#
 signal control in L1SS, and so on. We can't encapsulate all the GPR bits setting into PHY driver.
So, it's better to let controller driver to handle the general register bits manipulations.
How do you think about that?

> >
> > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > ---
> >  drivers/phy/freescale/Kconfig             |   9 ++
> >  drivers/phy/freescale/Makefile            |   1 +
> >  drivers/phy/freescale/phy-fsl-imx8-pcie.c | 167
> > ++++++++++++++++++++++
> >  3 files changed, 177 insertions(+)
> >  create mode 100644 drivers/phy/freescale/phy-fsl-imx8-pcie.c
> 
> From what I know, there are several quite different PCIe PHYs used in the
> different i.MX8 variants. I'm not sure if we want to stuff them all into one file.
> I guess we should be more specific here and call this imx8m-phy, or even
> imx8mm-phy.
[Richard Zhu] Good suggestions, I think imx8m-phy is better, since the i.MX8MQ/MM/MP
 have the similar architecture of the PCIe PHY implementation.

> 
> >
> > diff --git a/drivers/phy/freescale/Kconfig
> > b/drivers/phy/freescale/Kconfig index 320630ffe3cd..da078a676fbc
> > 100644
> > --- a/drivers/phy/freescale/Kconfig
> > +++ b/drivers/phy/freescale/Kconfig
> > @@ -14,3 +14,12 @@ config PHY_MIXEL_MIPI_DPHY
> >  	help
> >  	  Enable this to add support for the Mixel DSI PHY as found
> >  	  on NXP's i.MX8 family of SOCs.
> > +
> > +config PHY_FSL_IMX8_PCIE
> > +	tristate "Freescale i.MX8 PCIE PHY"
> > +	depends on OF && HAS_IOMEM
> > +	select GENERIC_PHY
> > +	default ARCH_MXC
> > +	help
> > +	  Enable this to add support for the PCIE PHY as found on i.MX8
> > +	  family of SOCs.
> > diff --git a/drivers/phy/freescale/Makefile
> > b/drivers/phy/freescale/Makefile index 1d02e3869b45..9fd467b58621
> > 100644
> > --- a/drivers/phy/freescale/Makefile
> > +++ b/drivers/phy/freescale/Makefile
> > @@ -1,3 +1,4 @@
> >  # SPDX-License-Identifier: GPL-2.0-only
> >  obj-$(CONFIG_PHY_FSL_IMX8MQ_USB)	+= phy-fsl-imx8mq-usb.o
> >  obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY)	+= phy-fsl-imx8-mipi-dphy.o
> > +obj-$(CONFIG_PHY_FSL_IMX8_PCIE)		+= phy-fsl-imx8-pcie.o
> > diff --git a/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > b/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > new file mode 100644
> > index 000000000000..ff47d6b83686
> > --- /dev/null
> > +++ b/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > @@ -0,0 +1,167 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2021 NXP
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/io.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/delay.h>
> > +#include <linux/module.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/platform_device.h>
> > +#include <dt-binding/phy/phy-fsl-imx8-pcie.h>
> > +
> > +#define IMX8MM_PCIE_PHY_CMN_REG061	0x184
> > +#define  ANA_PLL_CLK_OUT_TO_EXT_IO_EN	BIT(0)
> > +#define IMX8MM_PCIE_PHY_CMN_REG062	0x188
> > +#define  ANA_PLL_CLK_OUT_TO_EXT_IO_SEL	BIT(3)
> > +#define IMX8MM_PCIE_PHY_CMN_REG063	0x18C
> > +#define  AUX_PLL_REFCLK_SEL_SYS_PLL	GENMASK(7, 6)
> > +#define IMX8MM_PCIE_PHY_CMN_REG064	0x190
> > +#define  ANA_AUX_RX_TX_SEL_TX		BIT(7)
> > +#define  ANA_AUX_RX_TERM_GND_EN		BIT(3)
> > +#define  ANA_AUX_TX_TERM		BIT(2)
> > +#define IMX8MM_PCIE_PHY_CMN_REG065	0x194
> > +#define  ANA_AUX_RX_TERM		(BIT(7) | BIT(4))
> > +#define  ANA_AUX_TX_LVL			GENMASK(3, 0)
> > +#define IMX8MM_PCIE_PHY_CMN_REG75	0x1D4
> > +#define  PCIE_PHY_CMN_REG75_PLL_DONE	0x3
> > +#define PCIE_PHY_TRSV_REG5		0x414
> > +#define  PCIE_PHY_TRSV_REG5_GEN1_DEEMP	0x2D
> > +#define PCIE_PHY_TRSV_REG6		0x418
> > +#define  PCIE_PHY_TRSV_REG6_GEN2_DEEMP	0xF
> > +
> > +struct imx8_pcie_phy {
> > +	u32		refclk_pad_mode;
> > +	void __iomem	*base;
> > +	struct clk	*clk;
> > +	struct phy	*phy;
> > +};
> > +
> > +static int imx8_pcie_phy_init(struct phy *phy) {
> > +	int ret;
> > +	u32 val;
> > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > +
> > +	ret = readl_poll_timeout(imx8_phy->base +
> IMX8MM_PCIE_PHY_CMN_REG75,
> > +				 val, val == PCIE_PHY_CMN_REG75_PLL_DONE,
> > +				 10, 20000);
> > +	return ret;
> > +}
> > +
> > +static int imx8_pcie_phy_cal(struct phy *phy) {
> > +	u32 value, pad_mode;
> > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > +
> > +	pad_mode = imx8_phy->refclk_pad_mode;
> > +	if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
> > +		/* Configure the pad as input */
> > +		value = readl(imx8_phy->base +
> IMX8MM_PCIE_PHY_CMN_REG061);
> > +		writel(value & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
> > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
> > +	} else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
> > +		/* Configure the PHY to output the refclock via pad */
> > +		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
> > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
> > +		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
> > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
> > +		writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
> > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
> > +		value = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
> > +		writel(value | ANA_AUX_RX_TERM_GND_EN,
> > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
> > +		writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
> > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
> > +	}
> > +
> > +	/* Tune PHY de-emphasis setting to pass PCIe compliance. */
> > +	writel(PCIE_PHY_TRSV_REG5_GEN1_DEEMP,
> > +	       imx8_phy->base + PCIE_PHY_TRSV_REG5);
> > +	writel(PCIE_PHY_TRSV_REG6_GEN2_DEEMP,
> > +	       imx8_phy->base + PCIE_PHY_TRSV_REG6);
> > +
> > +	return 0;
> > +}
> > +
> > +static int imx8_pcie_phy_power_on(struct phy *phy) {
> > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > +
> > +	return clk_prepare_enable(imx8_phy->clk);
> 
> Do we need to enable this clock when the refclock is supplied externally via
> the pad?
> 
[Richard Zhu] Good question. I think this clock is not needed anymore if the refclock is sourced from external OSC.
I just enable the PLL2_100Mhz here, since when internal PLL is used as refclock, the pll2_100Mhz should be turned on.
Shall I remove the setting and just keep the callback for further extend usage(internal PLL used as refclk)?

> > +}
> > +
> > +static int imx8_pcie_phy_power_off(struct phy *phy) {
> > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > +
> > +	clk_disable_unprepare(imx8_phy->clk);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct phy_ops imx8_pcie_phy_ops = {
> > +	.init		= imx8_pcie_phy_init,
> > +	.calibrate	= imx8_pcie_phy_cal,
> > +	.power_on	= imx8_pcie_phy_power_on,
> > +	.power_off	= imx8_pcie_phy_power_off,
> > +	.owner		= THIS_MODULE,
> > +};
> > +
> > +static int imx8_pcie_phy_probe(struct platform_device *pdev) {
> > +	struct phy_provider *phy_provider;
> > +	struct device *dev = &pdev->dev;
> > +	struct device_node *np = dev->of_node;
> > +	struct imx8_pcie_phy *imx8_phy;
> > +	struct resource *res;
> > +
> > +	imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL);
> > +	if (!imx8_phy)
> > +		return -ENOMEM;
> > +
> > +	/* get PHY refclk pad mode */
> > +	of_property_read_u32(np, "fsl,refclk-pad-mode",
> > +			     &imx8_phy->refclk_pad_mode);
> > +
> > +	imx8_phy->clk = devm_clk_get(dev, "phy");
> > +	if (IS_ERR(imx8_phy->clk)) {
> > +		dev_err(dev, "failed to get imx pcie phy clock\n");
> > +		return PTR_ERR(imx8_phy->clk);
> > +	}
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	imx8_phy->base = devm_ioremap_resource(dev, res);
> > +	if (IS_ERR(imx8_phy->base))
> > +		return PTR_ERR(imx8_phy->base);
> > +
> > +	imx8_phy->phy = devm_phy_create(dev, NULL, &imx8_pcie_phy_ops);
> > +	if (IS_ERR(imx8_phy->phy))
> > +		return PTR_ERR(imx8_phy->phy);
> > +
> > +	phy_set_drvdata(imx8_phy->phy, imx8_phy);
> > +
> > +	phy_provider = devm_of_phy_provider_register(dev,
> > +of_phy_simple_xlate);
> > +
> > +	return PTR_ERR_OR_ZERO(phy_provider); }
> > +
> > +static const struct of_device_id imx8_pcie_phy_of_match[] = {
> > +	{.compatible = "fsl,imx8mm-pcie-phy",},
> > +	{ },
> > +};
> > +MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
> > +
> > +static struct platform_driver imx8_pcie_phy_driver = {
> > +	.probe	= imx8_pcie_phy_probe,
> > +	.driver = {
> > +		.name	= "imx8-pcie-phy",
> > +		.of_match_table	= imx8_pcie_phy_of_match,
> > +	}
> > +};
> > +module_platform_driver(imx8_pcie_phy_driver);
> > +
> > +MODULE_DESCRIPTION("FSL IMX8 PCIE PHY driver");
> > +MODULE_LICENSE("GPL");
> 


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

* Re: [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie standalone phy driver
  2021-09-28  7:09     ` Richard Zhu
@ 2021-09-28  8:43       ` Lucas Stach
  2021-10-11  7:47         ` Richard Zhu
  0 siblings, 1 reply; 15+ messages in thread
From: Lucas Stach @ 2021-09-28  8:43 UTC (permalink / raw)
  To: Richard Zhu, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel,
	dl-linux-imx

Hi Richard,

Am Dienstag, dem 28.09.2021 um 07:09 +0000 schrieb Richard Zhu:
> > -----Original Message-----
> > From: Lucas Stach <l.stach@pengutronix.de>
> > Sent: Monday, September 27, 2021 4:43 PM
> > To: Richard Zhu <hongxing.zhu@nxp.com>; kishon@ti.com; vkoul@kernel.org;
> > robh@kernel.org; galak@kernel.crashing.org; shawnguo@kernel.org
> > Cc: linux-phy@lists.infradead.org; devicetree@vger.kernel.org;
> > linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> > kernel@pengutronix.de; dl-linux-imx <linux-imx@nxp.com>
> > Subject: Re: [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie
> > standalone phy driver
> > 
> > Am Sonntag, dem 26.09.2021 um 15:39 +0800 schrieb Richard Zhu:
> > > Add the standalone i.MX8 PCIe PHY driver.
> > > Some reset bits should be manipulated between PHY configurations and
> > > status check(internal PLL is locked or not).
> > > So, do the PHY configuration in the phy_calibrate().
> > > And check the PHY is ready or not in the phy_init().
> > 
> > I would really like to see the PCIe controller driver side of this also, as it's hard
> > to review standalone. For example I'm not sure if some of those reset bits
> > should also be driven from the PHY driver, even if they are currently hooked
> > up to the controller driver.
> > 
> > Also I think the IOMUX GPR register handling belongs in the PHY driver, as it's
> > configuring the reference clock routing.
> > 
> [Richard Zhu] Sorry to bring inconvenience to you. I would send out the v3
>  patch-set and the i.MX8MM PCIe controller driver patches after I'm back from the
>  national holiday tomorrow(about one week). 

No problem. :) I'm just pointing out that I probably won't be able to
invest more time reviewing this before I can get the full picture.

> Although most of the IOMUX GPR bits are related to PHY, but there are some bits are
>  defined only for controller. For example, the device_type of the controller, the clkreq#
>  signal control in L1SS, and so on. We can't encapsulate all the GPR bits setting into PHY driver.
> So, it's better to let controller driver to handle the general register bits manipulations.
> How do you think about that?

I still think we should split the drivers along the functional
boundaries. It's quite confusing and probably going to be a maintenance
issues when some of the PHY handling bits are still located in the
controller driver, while we have a separate PHY driver.

As the GPR region is handled by a regmap we should have no issues
accessing even the same register from different drivers. So my vote is
on moving the GPR bits related to PHY clocking to this driver.

> 
> > > 
> > > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > > ---
> > >  drivers/phy/freescale/Kconfig             |   9 ++
> > >  drivers/phy/freescale/Makefile            |   1 +
> > >  drivers/phy/freescale/phy-fsl-imx8-pcie.c | 167
> > > ++++++++++++++++++++++
> > >  3 files changed, 177 insertions(+)
> > >  create mode 100644 drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > 
> > From what I know, there are several quite different PCIe PHYs used in the
> > different i.MX8 variants. I'm not sure if we want to stuff them all into one file.
> > I guess we should be more specific here and call this imx8m-phy, or even
> > imx8mm-phy.
> [Richard Zhu] Good suggestions, I think imx8m-phy is better, since the i.MX8MQ/MM/MP
>  have the similar architecture of the PCIe PHY implementation.
> 
> > 
> > > 
> > > diff --git a/drivers/phy/freescale/Kconfig
> > > b/drivers/phy/freescale/Kconfig index 320630ffe3cd..da078a676fbc
> > > 100644
> > > --- a/drivers/phy/freescale/Kconfig
> > > +++ b/drivers/phy/freescale/Kconfig
> > > @@ -14,3 +14,12 @@ config PHY_MIXEL_MIPI_DPHY
> > >  	help
> > >  	  Enable this to add support for the Mixel DSI PHY as found
> > >  	  on NXP's i.MX8 family of SOCs.
> > > +
> > > +config PHY_FSL_IMX8_PCIE
> > > +	tristate "Freescale i.MX8 PCIE PHY"
> > > +	depends on OF && HAS_IOMEM
> > > +	select GENERIC_PHY
> > > +	default ARCH_MXC
> > > +	help
> > > +	  Enable this to add support for the PCIE PHY as found on i.MX8
> > > +	  family of SOCs.
> > > diff --git a/drivers/phy/freescale/Makefile
> > > b/drivers/phy/freescale/Makefile index 1d02e3869b45..9fd467b58621
> > > 100644
> > > --- a/drivers/phy/freescale/Makefile
> > > +++ b/drivers/phy/freescale/Makefile
> > > @@ -1,3 +1,4 @@
> > >  # SPDX-License-Identifier: GPL-2.0-only
> > >  obj-$(CONFIG_PHY_FSL_IMX8MQ_USB)	+= phy-fsl-imx8mq-usb.o
> > >  obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY)	+= phy-fsl-imx8-mipi-dphy.o
> > > +obj-$(CONFIG_PHY_FSL_IMX8_PCIE)		+= phy-fsl-imx8-pcie.o
> > > diff --git a/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > > b/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > > new file mode 100644
> > > index 000000000000..ff47d6b83686
> > > --- /dev/null
> > > +++ b/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > > @@ -0,0 +1,167 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +/*
> > > + * Copyright 2021 NXP
> > > + */
> > > +
> > > +#include <linux/clk.h>
> > > +#include <linux/io.h>
> > > +#include <linux/iopoll.h>
> > > +#include <linux/delay.h>
> > > +#include <linux/module.h>
> > > +#include <linux/phy/phy.h>
> > > +#include <linux/platform_device.h>
> > > +#include <dt-binding/phy/phy-fsl-imx8-pcie.h>
> > > +
> > > +#define IMX8MM_PCIE_PHY_CMN_REG061	0x184
> > > +#define  ANA_PLL_CLK_OUT_TO_EXT_IO_EN	BIT(0)
> > > +#define IMX8MM_PCIE_PHY_CMN_REG062	0x188
> > > +#define  ANA_PLL_CLK_OUT_TO_EXT_IO_SEL	BIT(3)
> > > +#define IMX8MM_PCIE_PHY_CMN_REG063	0x18C
> > > +#define  AUX_PLL_REFCLK_SEL_SYS_PLL	GENMASK(7, 6)
> > > +#define IMX8MM_PCIE_PHY_CMN_REG064	0x190
> > > +#define  ANA_AUX_RX_TX_SEL_TX		BIT(7)
> > > +#define  ANA_AUX_RX_TERM_GND_EN		BIT(3)
> > > +#define  ANA_AUX_TX_TERM		BIT(2)
> > > +#define IMX8MM_PCIE_PHY_CMN_REG065	0x194
> > > +#define  ANA_AUX_RX_TERM		(BIT(7) | BIT(4))
> > > +#define  ANA_AUX_TX_LVL			GENMASK(3, 0)
> > > +#define IMX8MM_PCIE_PHY_CMN_REG75	0x1D4
> > > +#define  PCIE_PHY_CMN_REG75_PLL_DONE	0x3
> > > +#define PCIE_PHY_TRSV_REG5		0x414
> > > +#define  PCIE_PHY_TRSV_REG5_GEN1_DEEMP	0x2D
> > > +#define PCIE_PHY_TRSV_REG6		0x418
> > > +#define  PCIE_PHY_TRSV_REG6_GEN2_DEEMP	0xF
> > > +
> > > +struct imx8_pcie_phy {
> > > +	u32		refclk_pad_mode;
> > > +	void __iomem	*base;
> > > +	struct clk	*clk;
> > > +	struct phy	*phy;
> > > +};
> > > +
> > > +static int imx8_pcie_phy_init(struct phy *phy) {
> > > +	int ret;
> > > +	u32 val;
> > > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > > +
> > > +	ret = readl_poll_timeout(imx8_phy->base +
> > IMX8MM_PCIE_PHY_CMN_REG75,
> > > +				 val, val == PCIE_PHY_CMN_REG75_PLL_DONE,
> > > +				 10, 20000);
> > > +	return ret;
> > > +}
> > > +
> > > +static int imx8_pcie_phy_cal(struct phy *phy) {
> > > +	u32 value, pad_mode;
> > > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > > +
> > > +	pad_mode = imx8_phy->refclk_pad_mode;
> > > +	if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
> > > +		/* Configure the pad as input */
> > > +		value = readl(imx8_phy->base +
> > IMX8MM_PCIE_PHY_CMN_REG061);
> > > +		writel(value & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
> > > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
> > > +	} else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
> > > +		/* Configure the PHY to output the refclock via pad */
> > > +		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
> > > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
> > > +		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
> > > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
> > > +		writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
> > > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
> > > +		value = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
> > > +		writel(value | ANA_AUX_RX_TERM_GND_EN,
> > > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
> > > +		writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
> > > +		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
> > > +	}
> > > +
> > > +	/* Tune PHY de-emphasis setting to pass PCIe compliance. */
> > > +	writel(PCIE_PHY_TRSV_REG5_GEN1_DEEMP,
> > > +	       imx8_phy->base + PCIE_PHY_TRSV_REG5);
> > > +	writel(PCIE_PHY_TRSV_REG6_GEN2_DEEMP,
> > > +	       imx8_phy->base + PCIE_PHY_TRSV_REG6);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int imx8_pcie_phy_power_on(struct phy *phy) {
> > > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > > +
> > > +	return clk_prepare_enable(imx8_phy->clk);
> > 
> > Do we need to enable this clock when the refclock is supplied externally via
> > the pad?
> > 
> [Richard Zhu] Good question. I think this clock is not needed anymore if the refclock is sourced from external OSC.
> I just enable the PLL2_100Mhz here, since when internal PLL is used as refclock, the pll2_100Mhz should be turned on.
> Shall I remove the setting and just keep the callback for further extend usage(internal PLL used as refclk)?
> 
Yes, we should avoid turning on clocks that aren't needed. So the clock
enable here should be dependent on the pad-mode. When the clock is
supplied externally we don't want to enable the internal clock.

Regards,
Lucas

> > > +}
> > > +
> > > +static int imx8_pcie_phy_power_off(struct phy *phy) {
> > > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > > +
> > > +	clk_disable_unprepare(imx8_phy->clk);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct phy_ops imx8_pcie_phy_ops = {
> > > +	.init		= imx8_pcie_phy_init,
> > > +	.calibrate	= imx8_pcie_phy_cal,
> > > +	.power_on	= imx8_pcie_phy_power_on,
> > > +	.power_off	= imx8_pcie_phy_power_off,
> > > +	.owner		= THIS_MODULE,
> > > +};
> > > +
> > > +static int imx8_pcie_phy_probe(struct platform_device *pdev) {
> > > +	struct phy_provider *phy_provider;
> > > +	struct device *dev = &pdev->dev;
> > > +	struct device_node *np = dev->of_node;
> > > +	struct imx8_pcie_phy *imx8_phy;
> > > +	struct resource *res;
> > > +
> > > +	imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL);
> > > +	if (!imx8_phy)
> > > +		return -ENOMEM;
> > > +
> > > +	/* get PHY refclk pad mode */
> > > +	of_property_read_u32(np, "fsl,refclk-pad-mode",
> > > +			     &imx8_phy->refclk_pad_mode);
> > > +
> > > +	imx8_phy->clk = devm_clk_get(dev, "phy");
> > > +	if (IS_ERR(imx8_phy->clk)) {
> > > +		dev_err(dev, "failed to get imx pcie phy clock\n");
> > > +		return PTR_ERR(imx8_phy->clk);
> > > +	}
> > > +
> > > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > +	imx8_phy->base = devm_ioremap_resource(dev, res);
> > > +	if (IS_ERR(imx8_phy->base))
> > > +		return PTR_ERR(imx8_phy->base);
> > > +
> > > +	imx8_phy->phy = devm_phy_create(dev, NULL, &imx8_pcie_phy_ops);
> > > +	if (IS_ERR(imx8_phy->phy))
> > > +		return PTR_ERR(imx8_phy->phy);
> > > +
> > > +	phy_set_drvdata(imx8_phy->phy, imx8_phy);
> > > +
> > > +	phy_provider = devm_of_phy_provider_register(dev,
> > > +of_phy_simple_xlate);
> > > +
> > > +	return PTR_ERR_OR_ZERO(phy_provider); }
> > > +
> > > +static const struct of_device_id imx8_pcie_phy_of_match[] = {
> > > +	{.compatible = "fsl,imx8mm-pcie-phy",},
> > > +	{ },
> > > +};
> > > +MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
> > > +
> > > +static struct platform_driver imx8_pcie_phy_driver = {
> > > +	.probe	= imx8_pcie_phy_probe,
> > > +	.driver = {
> > > +		.name	= "imx8-pcie-phy",
> > > +		.of_match_table	= imx8_pcie_phy_of_match,
> > > +	}
> > > +};
> > > +module_platform_driver(imx8_pcie_phy_driver);
> > > +
> > > +MODULE_DESCRIPTION("FSL IMX8 PCIE PHY driver");
> > > +MODULE_LICENSE("GPL");
> > 
> 



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

* RE: [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie standalone phy driver
  2021-09-28  8:43       ` Lucas Stach
@ 2021-10-11  7:47         ` Richard Zhu
  0 siblings, 0 replies; 15+ messages in thread
From: Richard Zhu @ 2021-10-11  7:47 UTC (permalink / raw)
  To: Lucas Stach, kishon, vkoul, robh, galak, shawnguo
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, kernel,
	dl-linux-imx

> -----Original Message-----
> From: Lucas Stach <l.stach@pengutronix.de>
> Sent: Tuesday, September 28, 2021 4:44 PM
> To: Richard Zhu <hongxing.zhu@nxp.com>; kishon@ti.com; vkoul@kernel.org;
> robh@kernel.org; galak@kernel.crashing.org; shawnguo@kernel.org
> Cc: linux-phy@lists.infradead.org; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> kernel@pengutronix.de; dl-linux-imx <linux-imx@nxp.com>
> Subject: Re: [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie
> standalone phy driver
> 
> Hi Richard,
> 
> Am Dienstag, dem 28.09.2021 um 07:09 +0000 schrieb Richard Zhu:
> > > -----Original Message-----
> > > From: Lucas Stach <l.stach@pengutronix.de>
> > > Sent: Monday, September 27, 2021 4:43 PM
> > > To: Richard Zhu <hongxing.zhu@nxp.com>; kishon@ti.com;
> > > vkoul@kernel.org; robh@kernel.org; galak@kernel.crashing.org;
> > > shawnguo@kernel.org
> > > Cc: linux-phy@lists.infradead.org; devicetree@vger.kernel.org;
> > > linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> > > kernel@pengutronix.de; dl-linux-imx <linux-imx@nxp.com>
> > > Subject: Re: [PATCH v2 4/4] phy: freescale: pcie: initialize the
> > > imx8 pcie standalone phy driver
> > >
> > > Am Sonntag, dem 26.09.2021 um 15:39 +0800 schrieb Richard Zhu:
> > > > Add the standalone i.MX8 PCIe PHY driver.
> > > > Some reset bits should be manipulated between PHY configurations
> > > > and status check(internal PLL is locked or not).
> > > > So, do the PHY configuration in the phy_calibrate().
> > > > And check the PHY is ready or not in the phy_init().
> > >
> > > I would really like to see the PCIe controller driver side of this
> > > also, as it's hard to review standalone. For example I'm not sure if
> > > some of those reset bits should also be driven from the PHY driver,
> > > even if they are currently hooked up to the controller driver.
> > >
> > > Also I think the IOMUX GPR register handling belongs in the PHY
> > > driver, as it's configuring the reference clock routing.
> > >
> > [Richard Zhu] Sorry to bring inconvenience to you. I would send out
> > the v3
> >  patch-set and the i.MX8MM PCIe controller driver patches after I'm
> > back from the
> >  national holiday tomorrow(about one week).
> 
> No problem. :) I'm just pointing out that I probably won't be able to invest
> more time reviewing this before I can get the full picture.
> 
> > Although most of the IOMUX GPR bits are related to PHY, but there are
> > some bits are
> >  defined only for controller. For example, the device_type of the
> > controller, the clkreq#
> >  signal control in L1SS, and so on. We can't encapsulate all the GPR bits
> setting into PHY driver.
> > So, it's better to let controller driver to handle the general register bits
> manipulations.
> > How do you think about that?
> 
> I still think we should split the drivers along the functional boundaries. It's
> quite confusing and probably going to be a maintenance issues when some of
> the PHY handling bits are still located in the controller driver, while we have a
> separate PHY driver.
> 
> As the GPR region is handled by a regmap we should have no issues accessing
> even the same register from different drivers. So my vote is on moving the
> GPR bits related to PHY clocking to this driver.
> 
[Richard Zhu] Yes, it is. I will consider to let PHY driver manipulate PHY related GPR bits.

> >
> > > >
> > > > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > > > ---
> > > >  drivers/phy/freescale/Kconfig             |   9 ++
> > > >  drivers/phy/freescale/Makefile            |   1 +
> > > >  drivers/phy/freescale/phy-fsl-imx8-pcie.c | 167
> > > > ++++++++++++++++++++++
> > > >  3 files changed, 177 insertions(+)
> > > >  create mode 100644 drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > >
> > > From what I know, there are several quite different PCIe PHYs used
> > > in the different i.MX8 variants. I'm not sure if we want to stuff them all
> into one file.
> > > I guess we should be more specific here and call this imx8m-phy, or
> > > even imx8mm-phy.
> > [Richard Zhu] Good suggestions, I think imx8m-phy is better, since the
> > i.MX8MQ/MM/MP
> >  have the similar architecture of the PCIe PHY implementation.
> >
> > >
> > > >
> > > > diff --git a/drivers/phy/freescale/Kconfig
> > > > b/drivers/phy/freescale/Kconfig index 320630ffe3cd..da078a676fbc
> > > > 100644
> > > > --- a/drivers/phy/freescale/Kconfig
> > > > +++ b/drivers/phy/freescale/Kconfig
> > > > @@ -14,3 +14,12 @@ config PHY_MIXEL_MIPI_DPHY
> > > >  	help
> > > >  	  Enable this to add support for the Mixel DSI PHY as found
> > > >  	  on NXP's i.MX8 family of SOCs.
> > > > +
> > > > +config PHY_FSL_IMX8_PCIE
> > > > +	tristate "Freescale i.MX8 PCIE PHY"
> > > > +	depends on OF && HAS_IOMEM
> > > > +	select GENERIC_PHY
> > > > +	default ARCH_MXC
> > > > +	help
> > > > +	  Enable this to add support for the PCIE PHY as found on i.MX8
> > > > +	  family of SOCs.
> > > > diff --git a/drivers/phy/freescale/Makefile
> > > > b/drivers/phy/freescale/Makefile index 1d02e3869b45..9fd467b58621
> > > > 100644
> > > > --- a/drivers/phy/freescale/Makefile
> > > > +++ b/drivers/phy/freescale/Makefile
> > > > @@ -1,3 +1,4 @@
> > > >  # SPDX-License-Identifier: GPL-2.0-only
> > > >  obj-$(CONFIG_PHY_FSL_IMX8MQ_USB)	+= phy-fsl-imx8mq-usb.o
> > > >  obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY)	+= phy-fsl-imx8-mipi-dphy.o
> > > > +obj-$(CONFIG_PHY_FSL_IMX8_PCIE)		+= phy-fsl-imx8-pcie.o
> > > > diff --git a/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > > > b/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > > > new file mode 100644
> > > > index 000000000000..ff47d6b83686
> > > > --- /dev/null
> > > > +++ b/drivers/phy/freescale/phy-fsl-imx8-pcie.c
> > > > @@ -0,0 +1,167 @@
> > > > +// SPDX-License-Identifier: GPL-2.0+
> > > > +/*
> > > > + * Copyright 2021 NXP
> > > > + */
> > > > +
> > > > +#include <linux/clk.h>
> > > > +#include <linux/io.h>
> > > > +#include <linux/iopoll.h>
> > > > +#include <linux/delay.h>
> > > > +#include <linux/module.h>
> > > > +#include <linux/phy/phy.h>
> > > > +#include <linux/platform_device.h> #include
> > > > +<dt-binding/phy/phy-fsl-imx8-pcie.h>
> > > > +
> > > > +#define IMX8MM_PCIE_PHY_CMN_REG061	0x184
> > > > +#define  ANA_PLL_CLK_OUT_TO_EXT_IO_EN	BIT(0)
> > > > +#define IMX8MM_PCIE_PHY_CMN_REG062	0x188
> > > > +#define  ANA_PLL_CLK_OUT_TO_EXT_IO_SEL	BIT(3)
> > > > +#define IMX8MM_PCIE_PHY_CMN_REG063	0x18C
> > > > +#define  AUX_PLL_REFCLK_SEL_SYS_PLL	GENMASK(7, 6)
> > > > +#define IMX8MM_PCIE_PHY_CMN_REG064	0x190
> > > > +#define  ANA_AUX_RX_TX_SEL_TX		BIT(7)
> > > > +#define  ANA_AUX_RX_TERM_GND_EN		BIT(3)
> > > > +#define  ANA_AUX_TX_TERM		BIT(2)
> > > > +#define IMX8MM_PCIE_PHY_CMN_REG065	0x194
> > > > +#define  ANA_AUX_RX_TERM		(BIT(7) | BIT(4))
> > > > +#define  ANA_AUX_TX_LVL			GENMASK(3, 0)
> > > > +#define IMX8MM_PCIE_PHY_CMN_REG75	0x1D4
> > > > +#define  PCIE_PHY_CMN_REG75_PLL_DONE	0x3
> > > > +#define PCIE_PHY_TRSV_REG5		0x414
> > > > +#define  PCIE_PHY_TRSV_REG5_GEN1_DEEMP	0x2D
> > > > +#define PCIE_PHY_TRSV_REG6		0x418
> > > > +#define  PCIE_PHY_TRSV_REG6_GEN2_DEEMP	0xF
> > > > +
> > > > +struct imx8_pcie_phy {
> > > > +	u32		refclk_pad_mode;
> > > > +	void __iomem	*base;
> > > > +	struct clk	*clk;
> > > > +	struct phy	*phy;
> > > > +};
> > > > +
> > > > +static int imx8_pcie_phy_init(struct phy *phy) {
> > > > +	int ret;
> > > > +	u32 val;
> > > > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > > > +
> > > > +	ret = readl_poll_timeout(imx8_phy->base +
> > > IMX8MM_PCIE_PHY_CMN_REG75,
> > > > +				 val, val == PCIE_PHY_CMN_REG75_PLL_DONE,
> > > > +				 10, 20000);
> > > > +	return ret;
> > > > +}
> > > > +
> > > > +static int imx8_pcie_phy_cal(struct phy *phy) {
> > > > +	u32 value, pad_mode;
> > > > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > > > +
> > > > +	pad_mode = imx8_phy->refclk_pad_mode;
> > > > +	if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
> > > > +		/* Configure the pad as input */
> > > > +		value = readl(imx8_phy->base +
> > > IMX8MM_PCIE_PHY_CMN_REG061);
> > > > +		writel(value & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
> > > > +		       imx8_phy->base +
> IMX8MM_PCIE_PHY_CMN_REG061);
> > > > +	} else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
> > > > +		/* Configure the PHY to output the refclock via pad */
> > > > +		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
> > > > +		       imx8_phy->base +
> IMX8MM_PCIE_PHY_CMN_REG061);
> > > > +		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
> > > > +		       imx8_phy->base +
> IMX8MM_PCIE_PHY_CMN_REG062);
> > > > +		writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
> > > > +		       imx8_phy->base +
> IMX8MM_PCIE_PHY_CMN_REG063);
> > > > +		value = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
> > > > +		writel(value | ANA_AUX_RX_TERM_GND_EN,
> > > > +		       imx8_phy->base +
> IMX8MM_PCIE_PHY_CMN_REG064);
> > > > +		writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
> > > > +		       imx8_phy->base +
> IMX8MM_PCIE_PHY_CMN_REG065);
> > > > +	}
> > > > +
> > > > +	/* Tune PHY de-emphasis setting to pass PCIe compliance. */
> > > > +	writel(PCIE_PHY_TRSV_REG5_GEN1_DEEMP,
> > > > +	       imx8_phy->base + PCIE_PHY_TRSV_REG5);
> > > > +	writel(PCIE_PHY_TRSV_REG6_GEN2_DEEMP,
> > > > +	       imx8_phy->base + PCIE_PHY_TRSV_REG6);
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static int imx8_pcie_phy_power_on(struct phy *phy) {
> > > > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > > > +
> > > > +	return clk_prepare_enable(imx8_phy->clk);
> > >
> > > Do we need to enable this clock when the refclock is supplied
> > > externally via the pad?
> > >
> > [Richard Zhu] Good question. I think this clock is not needed anymore if the
> refclock is sourced from external OSC.
> > I just enable the PLL2_100Mhz here, since when internal PLL is used as
> refclock, the pll2_100Mhz should be turned on.
> > Shall I remove the setting and just keep the callback for further extend
> usage(internal PLL used as refclk)?
> >
> Yes, we should avoid turning on clocks that aren't needed. So the clock enable
> here should be dependent on the pad-mode. When the clock is supplied
> externally we don't want to enable the internal clock.
[Richard Zhu] How about that the dummy clock is used in the dts when "IMX8_PCIE_REFCLK_PAD_INPUT" mode is used?
Thus, we can keep driver simple and aligned, and use different dts definitions to specify different REFCLK modes.

> 
> Regards,
> Lucas
> 
> > > > +}
> > > > +
> > > > +static int imx8_pcie_phy_power_off(struct phy *phy) {
> > > > +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> > > > +
> > > > +	clk_disable_unprepare(imx8_phy->clk);
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static const struct phy_ops imx8_pcie_phy_ops = {
> > > > +	.init		= imx8_pcie_phy_init,
> > > > +	.calibrate	= imx8_pcie_phy_cal,
> > > > +	.power_on	= imx8_pcie_phy_power_on,
> > > > +	.power_off	= imx8_pcie_phy_power_off,
> > > > +	.owner		= THIS_MODULE,
> > > > +};
> > > > +
> > > > +static int imx8_pcie_phy_probe(struct platform_device *pdev) {
> > > > +	struct phy_provider *phy_provider;
> > > > +	struct device *dev = &pdev->dev;
> > > > +	struct device_node *np = dev->of_node;
> > > > +	struct imx8_pcie_phy *imx8_phy;
> > > > +	struct resource *res;
> > > > +
> > > > +	imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL);
> > > > +	if (!imx8_phy)
> > > > +		return -ENOMEM;
> > > > +
> > > > +	/* get PHY refclk pad mode */
> > > > +	of_property_read_u32(np, "fsl,refclk-pad-mode",
> > > > +			     &imx8_phy->refclk_pad_mode);
> > > > +
> > > > +	imx8_phy->clk = devm_clk_get(dev, "phy");
> > > > +	if (IS_ERR(imx8_phy->clk)) {
> > > > +		dev_err(dev, "failed to get imx pcie phy clock\n");
> > > > +		return PTR_ERR(imx8_phy->clk);
> > > > +	}
> > > > +
> > > > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > +	imx8_phy->base = devm_ioremap_resource(dev, res);
> > > > +	if (IS_ERR(imx8_phy->base))
> > > > +		return PTR_ERR(imx8_phy->base);
> > > > +
> > > > +	imx8_phy->phy = devm_phy_create(dev, NULL,
> &imx8_pcie_phy_ops);
> > > > +	if (IS_ERR(imx8_phy->phy))
> > > > +		return PTR_ERR(imx8_phy->phy);
> > > > +
> > > > +	phy_set_drvdata(imx8_phy->phy, imx8_phy);
> > > > +
> > > > +	phy_provider = devm_of_phy_provider_register(dev,
> > > > +of_phy_simple_xlate);
> > > > +
> > > > +	return PTR_ERR_OR_ZERO(phy_provider); }
> > > > +
> > > > +static const struct of_device_id imx8_pcie_phy_of_match[] = {
> > > > +	{.compatible = "fsl,imx8mm-pcie-phy",},
> > > > +	{ },
> > > > +};
> > > > +MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
> > > > +
> > > > +static struct platform_driver imx8_pcie_phy_driver = {
> > > > +	.probe	= imx8_pcie_phy_probe,
> > > > +	.driver = {
> > > > +		.name	= "imx8-pcie-phy",
> > > > +		.of_match_table	= imx8_pcie_phy_of_match,
> > > > +	}
> > > > +};
> > > > +module_platform_driver(imx8_pcie_phy_driver);
> > > > +
> > > > +MODULE_DESCRIPTION("FSL IMX8 PCIE PHY driver");
> > > > +MODULE_LICENSE("GPL");
> > >
> >
> 


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

end of thread, other threads:[~2021-10-11  7:47 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-26  7:39 [PATCH v2 0/4] add the imx8 pcie phy driver support Richard Zhu
2021-09-26  7:39 ` [PATCH v2 1/4] dt-bindings: phy: phy-imx8-pcie: Add binding for the pad modes of imx8 pcie phy Richard Zhu
2021-09-27  8:27   ` Lucas Stach
2021-09-28  2:28     ` Richard Zhu
2021-09-26  7:39 ` [PATCH v2 2/4] dt-bindings: phy: add imx8 pcie phy driver support Richard Zhu
2021-09-27  8:32   ` Lucas Stach
2021-09-28  2:37     ` Richard Zhu
2021-09-26  7:39 ` [PATCH v2 3/4] arm64: dts: imx8mm: add the pcie phy support Richard Zhu
2021-09-27  8:35   ` Lucas Stach
2021-09-28  2:38     ` Richard Zhu
2021-09-26  7:39 ` [PATCH v2 4/4] phy: freescale: pcie: initialize the imx8 pcie standalone phy driver Richard Zhu
2021-09-27  8:43   ` Lucas Stach
2021-09-28  7:09     ` Richard Zhu
2021-09-28  8:43       ` Lucas Stach
2021-10-11  7:47         ` Richard Zhu

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).