linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/7] PCI: amlogic: Make PCIe working reliably on AXG platforms
@ 2020-01-16 11:18 Remi Pommarel
  2020-01-16 11:18 ` [PATCH v5 1/7] dt-bindings: Add AXG PCIE PHY bindings Remi Pommarel
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Remi Pommarel @ 2020-01-16 11:18 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: Jerome Brunet, linux-amlogic, linux-kernel, devicetree, Remi Pommarel

PCIe device probing failures have been seen on AXG platforms and were
due to unreliable clock signal output. Setting HHI_MIPI_CNTL0[26] bit
in MIPI's PHY registers solved the problem. This bit controls band gap
reference.

As discussed here [1] one of these shared MIPI/PCIE analog PHY register
bits was implemented in the clock driver as CLKID_MIPI_ENABLE. This adds
a PHY driver to control this bit instead, as well as setting the band
gap one in order to get reliable PCIE communication.

While at it add another PHY driver to control PCIE only PHY registers,
making AXG code more similar to G12A platform thus allowing to remove
some specific platform handling in pci-meson driver.

Please note that CLKID_MIPI_ENABLE removable will be done in a different
serie.

Changes since v4:
 - Rename the shared MIPI/PCIe PHY to analog
 - Chain the MIPI/PCIe PHY to the PCIe one

Changes since v3:
 - Go back to the shared MIPI/PCIe phy driver solution from v2
 - Remove syscon usage
 - Add all dt-bindings documentation

Changes since v2:
 - Remove shared MIPI/PCIE device driver and use syscon to access register
   in PCIE only driver instead
 - Include devicetree documentation

Changes sinve v1:
 - Move HHI_MIPI_CNTL0 bit control in its own PHY driver
 - Add a PHY driver for PCIE_PHY registers
 - Modify pci-meson.c to make use of both PHYs and remove specific
   handling for AXG and G12A

[1] https://lkml.org/lkml/2019/12/16/119

Remi Pommarel (7):
  dt-bindings: Add AXG PCIE PHY bindings
  dt-bindings: Add AXG shared MIPI/PCIE analog PHY bindings
  dt-bindings: PCI: meson: Update PCIE bindings documentation
  arm64: dts: meson-axg: Add PCIE PHY nodes
  phy: amlogic: Add Amlogic AXG MIPI/PCIE analog PHY Driver
  phy: amlogic: Add Amlogic AXG PCIE PHY Driver
  PCI: amlogic: Use AXG PCIE

 .../bindings/pci/amlogic,meson-pcie.txt       |  22 +-
 .../amlogic,meson-axg-mipi-pcie-analog.yaml   |  33 +++
 .../bindings/phy/amlogic,meson-axg-pcie.yaml  |  48 +++++
 arch/arm64/boot/dts/amlogic/meson-axg.dtsi    |  16 ++
 drivers/pci/controller/dwc/pci-meson.c        | 116 ++---------
 drivers/phy/amlogic/Kconfig                   |  22 ++
 drivers/phy/amlogic/Makefile                  |  12 +-
 .../amlogic/phy-meson-axg-mipi-pcie-analog.c  | 188 +++++++++++++++++
 drivers/phy/amlogic/phy-meson-axg-pcie.c      | 192 ++++++++++++++++++
 9 files changed, 537 insertions(+), 112 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml
 create mode 100644 Documentation/devicetree/bindings/phy/amlogic,meson-axg-pcie.yaml
 create mode 100644 drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
 create mode 100644 drivers/phy/amlogic/phy-meson-axg-pcie.c

-- 
2.24.1


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

* [PATCH v5 1/7] dt-bindings: Add AXG PCIE PHY bindings
  2020-01-16 11:18 [PATCH v5 0/7] PCI: amlogic: Make PCIe working reliably on AXG platforms Remi Pommarel
@ 2020-01-16 11:18 ` Remi Pommarel
  2020-01-17 16:03   ` Rob Herring
  2020-01-16 11:18 ` [PATCH v5 2/7] dt-bindings: Add AXG shared MIPI/PCIE analog " Remi Pommarel
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Remi Pommarel @ 2020-01-16 11:18 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: Jerome Brunet, linux-amlogic, linux-kernel, devicetree, Remi Pommarel

Add documentation for PCIE PHYs found in AXG SoCs.

Signed-off-by: Remi Pommarel <repk@triplefau.lt>
---
 .../bindings/phy/amlogic,meson-axg-pcie.yaml  | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/amlogic,meson-axg-pcie.yaml

diff --git a/Documentation/devicetree/bindings/phy/amlogic,meson-axg-pcie.yaml b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-pcie.yaml
new file mode 100644
index 000000000000..70683946f47f
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-pcie.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/phy/amlogic,meson-axg-pcie.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Amlogic AXG PCIE PHY
+
+maintainers:
+  - Remi Pommarel <repk@triplefau.lt>
+
+properties:
+  compatible:
+    const: amlogic,axg-pcie-phy
+
+  reg:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  phys:
+    maxItems: 1
+
+  phy-names:
+    const: analog # If MIPI/PCIE analog PHY is used
+
+  "#phy-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - resets
+  - "#phy-cells"
+
+examples:
+  - |
+    #include <dt-bindings/reset/amlogic,meson-axg-reset.h>
+    #include <dt-bindings/phy/phy.h>
+    pcie_phy: pcie-phy@ff644000 {
+          compatible = "amlogic,axg-pcie-phy";
+          reg = <0x0 0xff644000 0x0 0x1c>;
+          resets = <&reset RESET_PCIE_PHY>;
+          phys = <&mipi_analog_phy PHY_TYPE_PCIE>;
+          phy-names = "analog";
+          #phy-cells = <0>;
+    };
-- 
2.24.1


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

* [PATCH v5 2/7] dt-bindings: Add AXG shared MIPI/PCIE analog PHY bindings
  2020-01-16 11:18 [PATCH v5 0/7] PCI: amlogic: Make PCIe working reliably on AXG platforms Remi Pommarel
  2020-01-16 11:18 ` [PATCH v5 1/7] dt-bindings: Add AXG PCIE PHY bindings Remi Pommarel
@ 2020-01-16 11:18 ` Remi Pommarel
  2020-01-17 16:04   ` Rob Herring
  2020-01-16 11:18 ` [PATCH v5 3/7] dt-bindings: PCI: meson: Update PCIE bindings documentation Remi Pommarel
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Remi Pommarel @ 2020-01-16 11:18 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: Jerome Brunet, linux-amlogic, linux-kernel, devicetree, Remi Pommarel

Add documentation for the shared MIPI/PCIE analog PHY found in AXG
SoCs.

Signed-off-by: Remi Pommarel <repk@triplefau.lt>
---
 .../amlogic,meson-axg-mipi-pcie-analog.yaml   | 33 +++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml

diff --git a/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml
new file mode 100644
index 000000000000..418b76c78636
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/phy/amlogic,meson-axg-mipi-pcie-analog.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Amlogic AXG shared MIPI/PCIE analog PHY
+
+maintainers:
+  - Remi Pommarel <repk@triplefau.lt>
+
+properties:
+  compatible:
+    const: amlogic,axg-mipi-pcie-analog-phy
+
+  reg:
+    maxItems: 1
+
+  "#phy-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - "#phy-cells"
+
+examples:
+  - |
+    mpphy: phy@0 {
+          compatible = "amlogic,axg-mipi-pcie-analog-phy";
+          reg = <0x0 0x0 0x0 0xc>;
+          #phy-cells = <1>;
+    };
-- 
2.24.1


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

* [PATCH v5 3/7] dt-bindings: PCI: meson: Update PCIE bindings documentation
  2020-01-16 11:18 [PATCH v5 0/7] PCI: amlogic: Make PCIe working reliably on AXG platforms Remi Pommarel
  2020-01-16 11:18 ` [PATCH v5 1/7] dt-bindings: Add AXG PCIE PHY bindings Remi Pommarel
  2020-01-16 11:18 ` [PATCH v5 2/7] dt-bindings: Add AXG shared MIPI/PCIE analog " Remi Pommarel
@ 2020-01-16 11:18 ` Remi Pommarel
  2020-01-17 16:05   ` Rob Herring
  2020-01-16 11:18 ` [PATCH v5 4/7] arm64: dts: meson-axg: Add PCIE PHY nodes Remi Pommarel
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Remi Pommarel @ 2020-01-16 11:18 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: Jerome Brunet, linux-amlogic, linux-kernel, devicetree, Remi Pommarel

Now that a new PHYs has been introduced for AXG SoC family, update
dt bindings documentation.

Please note that this breaks backward compatibility but as not a single
devicetree uses that yet that seems ok.

Signed-off-by: Remi Pommarel <repk@triplefau.lt>
---
 .../bindings/pci/amlogic,meson-pcie.txt       | 22 ++++++++-----------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt b/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt
index 84fdc422792e..b6acbe694ffb 100644
--- a/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt
@@ -18,7 +18,6 @@ Required properties:
 - reg-names: Must be
 	- "elbi"	External local bus interface registers
 	- "cfg"		Meson specific registers
-	- "phy"		Meson PCIE PHY registers for AXG SoC Family
 	- "config"	PCIe configuration space
 - reset-gpios: The GPIO to generate PCIe PERST# assert and deassert signal.
 - clocks: Must contain an entry for each entry in clock-names.
@@ -26,13 +25,13 @@ Required properties:
 	- "pclk"       PCIe GEN 100M PLL clock
 	- "port"       PCIe_x(A or B) RC clock gate
 	- "general"    PCIe Phy clock
-	- "mipi"       PCIe_x(A or B) 100M ref clock gate for AXG SoC Family
 - resets: phandle to the reset lines.
-- reset-names: must contain "phy" "port" and "apb"
-       - "phy"         Share PHY reset for AXG SoC Family
+- reset-names: must contain "port" and "apb"
        - "port"        Port A or B reset
        - "apb"         Share APB reset
-- phys: should contain a phandle to the shared phy for G12A SoC Family
+- phys: should contain a phandle to the PCIE phy
+- phy-names: must contain "pcie"
+
 - device_type:
 	should be "pci". As specified in designware-pcie.txt
 
@@ -43,9 +42,8 @@ Example configuration:
 			compatible = "amlogic,axg-pcie", "snps,dw-pcie";
 			reg = <0x0 0xf9800000 0x0 0x400000
 					0x0 0xff646000 0x0 0x2000
-					0x0 0xff644000 0x0 0x2000
 					0x0 0xf9f00000 0x0 0x100000>;
-			reg-names = "elbi", "cfg", "phy", "config";
+			reg-names = "elbi", "cfg", "config";
 			reset-gpios = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>;
 			interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>;
 			#interrupt-cells = <1>;
@@ -58,17 +56,15 @@ Example configuration:
 			ranges = <0x82000000 0 0 0x0 0xf9c00000 0 0x00300000>;
 
 			clocks = <&clkc CLKID_USB
-					&clkc CLKID_MIPI_ENABLE
 					&clkc CLKID_PCIE_A
 					&clkc CLKID_PCIE_CML_EN0>;
 			clock-names = "general",
-					"mipi",
 					"pclk",
 					"port";
-			resets = <&reset RESET_PCIE_PHY>,
-				<&reset RESET_PCIE_A>,
+			resets = <&reset RESET_PCIE_A>,
 				<&reset RESET_PCIE_APB>;
-			reset-names = "phy",
-					"port",
+			reset-names = "port",
 					"apb";
+			phys = <&pcie_phy>;
+			phy-names = "pcie";
 	};
-- 
2.24.1


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

* [PATCH v5 4/7] arm64: dts: meson-axg: Add PCIE PHY nodes
  2020-01-16 11:18 [PATCH v5 0/7] PCI: amlogic: Make PCIe working reliably on AXG platforms Remi Pommarel
                   ` (2 preceding siblings ...)
  2020-01-16 11:18 ` [PATCH v5 3/7] dt-bindings: PCI: meson: Update PCIE bindings documentation Remi Pommarel
@ 2020-01-16 11:18 ` Remi Pommarel
  2020-01-23  9:56   ` Neil Armstrong
  2020-01-16 11:18 ` [PATCH v5 5/7] phy: amlogic: Add Amlogic AXG MIPI/PCIE analog PHY Driver Remi Pommarel
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Remi Pommarel @ 2020-01-16 11:18 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: Jerome Brunet, linux-amlogic, linux-kernel, devicetree, Remi Pommarel

Enable both PCIE and shared MIPI/PCIE PHY nodes in order to make PCIE
reliable on AXG SoC.

Signed-off-by: Remi Pommarel <repk@triplefau.lt>
---
 arch/arm64/boot/dts/amlogic/meson-axg.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index 04803c3bccfa..08a178aa0133 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -12,6 +12,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
 #include <dt-bindings/reset/amlogic,meson-axg-reset.h>
+#include <dt-bindings/phy/phy.h>
 
 / {
 	compatible = "amlogic,meson-axg";
@@ -1104,6 +1105,12 @@ hiubus: bus@ff63c000 {
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x1c00>;
 
+			mipi_analog_phy: phy@0 {
+				compatible = "amlogic,axg-mipi-pcie-analog-phy";
+				reg = <0x0 0x0 0x0 0xc>;
+				#phy-cells = <1>;
+			};
+
 			sysctrl: system-controller@0 {
 				compatible = "amlogic,meson-axg-hhi-sysctrl",
 					     "simple-mfd", "syscon";
@@ -1356,6 +1363,15 @@ tdmout_c: audio-controller@580 {
 			};
 		};
 
+		pcie_phy: bus@ff644000 {
+			compatible = "amlogic,axg-pcie-phy";
+			reg = <0x0 0xff644000 0x0 0x1c>;
+			resets = <&reset RESET_PCIE_PHY>;
+			phys = <&mipi_analog_phy PHY_TYPE_PCIE>;
+			phy-names = "analog";
+			#phy-cells = <0>;
+		};
+
 		aobus: bus@ff800000 {
 			compatible = "simple-bus";
 			reg = <0x0 0xff800000 0x0 0x100000>;
-- 
2.24.1


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

* [PATCH v5 5/7] phy: amlogic: Add Amlogic AXG MIPI/PCIE analog PHY Driver
  2020-01-16 11:18 [PATCH v5 0/7] PCI: amlogic: Make PCIe working reliably on AXG platforms Remi Pommarel
                   ` (3 preceding siblings ...)
  2020-01-16 11:18 ` [PATCH v5 4/7] arm64: dts: meson-axg: Add PCIE PHY nodes Remi Pommarel
@ 2020-01-16 11:18 ` Remi Pommarel
  2020-01-23  9:37   ` Jerome Brunet
  2020-01-16 11:18 ` [PATCH v5 6/7] phy: amlogic: Add Amlogic AXG PCIE " Remi Pommarel
  2020-01-16 11:18 ` [PATCH v5 7/7] PCI: amlogic: Use AXG PCIE Remi Pommarel
  6 siblings, 1 reply; 18+ messages in thread
From: Remi Pommarel @ 2020-01-16 11:18 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: Jerome Brunet, linux-amlogic, linux-kernel, devicetree, Remi Pommarel

This adds support for the MIPI analog PHY which is also used for PCIE
found in the Amlogic AXG SoC Family.

MIPI or PCIE selection is done by the #phy-cells, making the mode
static and exclusive.

For now only PCIE fonctionality is supported.

This PHY will be used to replace the mipi_enable clock gating logic
which was mistakenly added in the clock subsystem. This also activate
a non documented band gap bit in those registers that allows reliable
PCIE clock signal generation on AXG platforms.

Signed-off-by: Remi Pommarel <repk@triplefau.lt>
---
 drivers/phy/amlogic/Kconfig                   |  11 +
 drivers/phy/amlogic/Makefile                  |  11 +-
 .../amlogic/phy-meson-axg-mipi-pcie-analog.c  | 188 ++++++++++++++++++
 3 files changed, 205 insertions(+), 5 deletions(-)
 create mode 100644 drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c

diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
index af774ac2b934..8c9cf2403591 100644
--- a/drivers/phy/amlogic/Kconfig
+++ b/drivers/phy/amlogic/Kconfig
@@ -59,3 +59,14 @@ config PHY_MESON_G12A_USB3_PCIE
 	  Enable this to support the Meson USB3 + PCIE Combo PHY found
 	  in Meson G12A SoCs.
 	  If unsure, say N.
+
+config PHY_MESON_AXG_MIPI_PCIE_ANALOG
+	tristate "Meson AXG MIPI + PCIE analog PHY driver"
+	default ARCH_MESON
+	depends on OF && (ARCH_MESON || COMPILE_TEST)
+	select GENERIC_PHY
+	select REGMAP_MMIO
+	help
+	  Enable this to support the Meson MIPI + PCIE analog PHY
+	  found in Meson AXG SoCs.
+	  If unsure, say N.
diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile
index 11d1c42ac2be..0aecf92d796a 100644
--- a/drivers/phy/amlogic/Makefile
+++ b/drivers/phy/amlogic/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_PHY_MESON8B_USB2)		+= phy-meson8b-usb2.o
-obj-$(CONFIG_PHY_MESON_GXL_USB2)	+= phy-meson-gxl-usb2.o
-obj-$(CONFIG_PHY_MESON_G12A_USB2)	+= phy-meson-g12a-usb2.o
-obj-$(CONFIG_PHY_MESON_GXL_USB3)	+= phy-meson-gxl-usb3.o
-obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE)	+= phy-meson-g12a-usb3-pcie.o
+obj-$(CONFIG_PHY_MESON8B_USB2)			+= phy-meson8b-usb2.o
+obj-$(CONFIG_PHY_MESON_GXL_USB2)		+= phy-meson-gxl-usb2.o
+obj-$(CONFIG_PHY_MESON_G12A_USB2)		+= phy-meson-g12a-usb2.o
+obj-$(CONFIG_PHY_MESON_GXL_USB3)		+= phy-meson-gxl-usb3.o
+obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE)		+= phy-meson-g12a-usb3-pcie.o
+obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG)	+= phy-meson-axg-mipi-pcie-analog.o
diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
new file mode 100644
index 000000000000..1431cbf885e1
--- /dev/null
+++ b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Amlogic AXG MIPI + PCIE analog PHY driver
+ *
+ * Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
+ */
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/phy/phy.h>
+
+#define HHI_MIPI_CNTL0 0x00
+#define		HHI_MIPI_CNTL0_COMMON_BLOCK	GENMASK(31, 28)
+#define		HHI_MIPI_CNTL0_ENABLE		BIT(29)
+#define		HHI_MIPI_CNTL0_BANDGAP		BIT(26)
+#define		HHI_MIPI_CNTL0_DECODE_TO_RTERM	GENMASK(15, 12)
+#define		HHI_MIPI_CNTL0_OUTPUT_EN	BIT(3)
+
+#define HHI_MIPI_CNTL1 0x01
+#define		HHI_MIPI_CNTL1_CH0_CML_PDR_EN	BIT(12)
+#define		HHI_MIPI_CNTL1_LP_ABILITY	GENMASK(5, 4)
+#define		HHI_MIPI_CNTL1_LP_RESISTER	BIT(3)
+#define		HHI_MIPI_CNTL1_INPUT_SETTING	BIT(2)
+#define		HHI_MIPI_CNTL1_INPUT_SEL	BIT(1)
+#define		HHI_MIPI_CNTL1_PRBS7_EN		BIT(0)
+
+#define HHI_MIPI_CNTL2 0x02
+#define		HHI_MIPI_CNTL2_CH_PU		GENMASK(31, 25)
+#define		HHI_MIPI_CNTL2_CH_CTL		GENMASK(24, 19)
+#define		HHI_MIPI_CNTL2_CH0_DIGDR_EN	BIT(18)
+#define		HHI_MIPI_CNTL2_CH_DIGDR_EN	BIT(17)
+#define		HHI_MIPI_CNTL2_LPULPS_EN	BIT(16)
+#define		HHI_MIPI_CNTL2_CH_EN(n)		BIT(15 - (n))
+#define		HHI_MIPI_CNTL2_CH0_LP_CTL	GENMASK(10, 1)
+
+struct phy_axg_mipi_pcie_analog_priv {
+	struct phy *phy;
+	unsigned int mode;
+	struct regmap *regmap;
+};
+
+static const struct regmap_config phy_axg_mipi_pcie_analog_regmap_conf = {
+	.reg_bits = 8,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = HHI_MIPI_CNTL2,
+};
+
+static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy)
+{
+	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
+
+	/* MIPI not supported yet */
+	if (priv->mode != PHY_TYPE_PCIE)
+		return -EINVAL;
+
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
+
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
+	return 0;
+}
+
+static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy)
+{
+	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
+
+	/* MIPI not supported yet */
+	if (priv->mode != PHY_TYPE_PCIE)
+		return -EINVAL;
+
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   HHI_MIPI_CNTL0_BANDGAP, 0);
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   HHI_MIPI_CNTL0_ENABLE, 0);
+	return 0;
+}
+
+static int phy_axg_mipi_pcie_analog_init(struct phy *phy)
+{
+	return 0;
+}
+
+static int phy_axg_mipi_pcie_analog_exit(struct phy *phy)
+{
+	return 0;
+}
+
+static const struct phy_ops phy_axg_mipi_pcie_analog_ops = {
+	.init = phy_axg_mipi_pcie_analog_init,
+	.exit = phy_axg_mipi_pcie_analog_exit,
+	.power_on = phy_axg_mipi_pcie_analog_power_on,
+	.power_off = phy_axg_mipi_pcie_analog_power_off,
+	.owner = THIS_MODULE,
+};
+
+static struct phy *phy_axg_mipi_pcie_analog_xlate(struct device *dev,
+						  struct of_phandle_args *args)
+{
+	struct phy_axg_mipi_pcie_analog_priv *priv = dev_get_drvdata(dev);
+	unsigned int mode;
+
+	if (args->args_count != 1) {
+		dev_err(dev, "invalid number of arguments\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	mode = args->args[0];
+
+	/* MIPI mode is not supported yet */
+	if (mode != PHY_TYPE_PCIE) {
+		dev_err(dev, "invalid phy mode select argument\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	priv->mode = mode;
+	return priv->phy;
+}
+
+static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy;
+	struct device *dev = &pdev->dev;
+	struct phy_axg_mipi_pcie_analog_priv *priv;
+	struct device_node *np = dev->of_node;
+	struct regmap *map;
+	struct resource *res;
+	void __iomem *base;
+	int ret;
+
+	priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base)) {
+		dev_err(dev, "failed to get regmap base\n");
+		return PTR_ERR(base);
+	}
+
+	map = devm_regmap_init_mmio(dev, base,
+				    &phy_axg_mipi_pcie_analog_regmap_conf);
+	if (IS_ERR(map)) {
+		dev_err(dev, "failed to get HHI regmap\n");
+		return PTR_ERR(map);
+	}
+	priv->regmap = map;
+
+	priv->phy = devm_phy_create(dev, np, &phy_axg_mipi_pcie_analog_ops);
+	if (IS_ERR(priv->phy)) {
+		ret = PTR_ERR(priv->phy);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "failed to create PHY\n");
+		return ret;
+	}
+
+	phy_set_drvdata(priv->phy, priv);
+	dev_set_drvdata(dev, priv);
+
+	phy = devm_of_phy_provider_register(dev,
+					    phy_axg_mipi_pcie_analog_xlate);
+
+	return PTR_ERR_OR_ZERO(phy);
+}
+
+static const struct of_device_id phy_axg_mipi_pcie_analog_of_match[] = {
+	{
+		.compatible = "amlogic,axg-mipi-pcie-analog-phy",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, phy_axg_mipi_pcie_analog_of_match);
+
+static struct platform_driver phy_axg_mipi_pcie_analog_driver = {
+	.probe = phy_axg_mipi_pcie_analog_probe,
+	.driver = {
+		.name = "phy-axg-mipi-pcie-analog",
+		.of_match_table = phy_axg_mipi_pcie_analog_of_match,
+	},
+};
+module_platform_driver(phy_axg_mipi_pcie_analog_driver);
+
+MODULE_AUTHOR("Remi Pommarel <repk@triplefau.lt>");
+MODULE_DESCRIPTION("Amlogic AXG MIPI + PCIE analog PHY driver");
+MODULE_LICENSE("GPL v2");
-- 
2.24.1


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

* [PATCH v5 6/7] phy: amlogic: Add Amlogic AXG PCIE PHY Driver
  2020-01-16 11:18 [PATCH v5 0/7] PCI: amlogic: Make PCIe working reliably on AXG platforms Remi Pommarel
                   ` (4 preceding siblings ...)
  2020-01-16 11:18 ` [PATCH v5 5/7] phy: amlogic: Add Amlogic AXG MIPI/PCIE analog PHY Driver Remi Pommarel
@ 2020-01-16 11:18 ` Remi Pommarel
  2020-01-23  9:44   ` Jerome Brunet
  2020-01-16 11:18 ` [PATCH v5 7/7] PCI: amlogic: Use AXG PCIE Remi Pommarel
  6 siblings, 1 reply; 18+ messages in thread
From: Remi Pommarel @ 2020-01-16 11:18 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: Jerome Brunet, linux-amlogic, linux-kernel, devicetree, Remi Pommarel

This adds support for the PCI PHY found in the Amlogic AXG SoC Family.
This will allow to mutualize code in pci-meson.c between AXG and G12A
SoC.

This PHY can chain and use an optional analog PHY, which is used on
AXG platform to have reliable PCIe communication.

Signed-off-by: Remi Pommarel <repk@triplefau.lt>
---
 drivers/phy/amlogic/Kconfig              |  11 ++
 drivers/phy/amlogic/Makefile             |   1 +
 drivers/phy/amlogic/phy-meson-axg-pcie.c | 192 +++++++++++++++++++++++
 3 files changed, 204 insertions(+)
 create mode 100644 drivers/phy/amlogic/phy-meson-axg-pcie.c

diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
index 8c9cf2403591..71801e30d601 100644
--- a/drivers/phy/amlogic/Kconfig
+++ b/drivers/phy/amlogic/Kconfig
@@ -60,6 +60,17 @@ config PHY_MESON_G12A_USB3_PCIE
 	  in Meson G12A SoCs.
 	  If unsure, say N.
 
+config PHY_MESON_AXG_PCIE
+	tristate "Meson AXG PCIE PHY driver"
+	default ARCH_MESON
+	depends on OF && (ARCH_MESON || COMPILE_TEST)
+	select GENERIC_PHY
+	select REGMAP_MMIO
+	help
+	  Enable this to support the Meson MIPI + PCIE PHY found
+	  in Meson AXG SoCs.
+	  If unsure, say N.
+
 config PHY_MESON_AXG_MIPI_PCIE_ANALOG
 	tristate "Meson AXG MIPI + PCIE analog PHY driver"
 	default ARCH_MESON
diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile
index 0aecf92d796a..e2baa133f7af 100644
--- a/drivers/phy/amlogic/Makefile
+++ b/drivers/phy/amlogic/Makefile
@@ -4,4 +4,5 @@ obj-$(CONFIG_PHY_MESON_GXL_USB2)		+= phy-meson-gxl-usb2.o
 obj-$(CONFIG_PHY_MESON_G12A_USB2)		+= phy-meson-g12a-usb2.o
 obj-$(CONFIG_PHY_MESON_GXL_USB3)		+= phy-meson-gxl-usb3.o
 obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE)		+= phy-meson-g12a-usb3-pcie.o
+obj-$(CONFIG_PHY_MESON_AXG_PCIE)		+= phy-meson-axg-pcie.o
 obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG)	+= phy-meson-axg-mipi-pcie-analog.o
diff --git a/drivers/phy/amlogic/phy-meson-axg-pcie.c b/drivers/phy/amlogic/phy-meson-axg-pcie.c
new file mode 100644
index 000000000000..0c5d0732cd1c
--- /dev/null
+++ b/drivers/phy/amlogic/phy-meson-axg-pcie.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Amlogic AXG PCIE PHY driver
+ *
+ * Copyright (C) 2020 Remi Pommarel <repk@triplefau.lt>
+ */
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/platform_device.h>
+#include <linux/bitfield.h>
+#include <dt-bindings/phy/phy.h>
+
+#define MESON_PCIE_REG0 0x00
+#define		MESON_PCIE_COMMON_CLK	BIT(4)
+#define		MESON_PCIE_PORT_SEL	GENMASK(3, 2)
+#define		MESON_PCIE_CLK		BIT(1)
+#define		MESON_PCIE_POWERDOWN	BIT(0)
+
+#define MESON_PCIE_TWO_X1		FIELD_PREP(MESON_PCIE_PORT_SEL, 0x3)
+#define MESON_PCIE_COMMON_REF_CLK	FIELD_PREP(MESON_PCIE_COMMON_CLK, 0x1)
+#define MESON_PCIE_PHY_INIT		(MESON_PCIE_TWO_X1 |		\
+					 MESON_PCIE_COMMON_REF_CLK)
+#define MESON_PCIE_RESET_DELAY		500
+
+struct phy_axg_pcie_priv {
+	struct phy *phy;
+	struct phy *analog;
+	struct regmap *regmap;
+	struct reset_control *reset;
+};
+
+static const struct regmap_config phy_axg_pcie_regmap_conf = {
+	.reg_bits = 8,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = MESON_PCIE_REG0,
+};
+
+static int phy_axg_pcie_power_on(struct phy *phy)
+{
+	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
+	int ret;
+
+	ret = phy_power_on(priv->analog);
+	if (ret != 0)
+		return ret;
+
+	regmap_update_bits(priv->regmap, MESON_PCIE_REG0,
+			   MESON_PCIE_POWERDOWN, 0);
+	return 0;
+}
+
+static int phy_axg_pcie_power_off(struct phy *phy)
+{
+	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
+	int ret;
+
+	ret = phy_power_off(priv->analog);
+	if (ret != 0)
+		return ret;
+
+	regmap_update_bits(priv->regmap, MESON_PCIE_REG0,
+			   MESON_PCIE_POWERDOWN, 1);
+	return 0;
+}
+
+static int phy_axg_pcie_init(struct phy *phy)
+{
+	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
+	int ret;
+
+	ret = phy_init(priv->analog);
+	if (ret != 0)
+		return ret;
+
+	regmap_write(priv->regmap, MESON_PCIE_REG0, MESON_PCIE_PHY_INIT);
+	return reset_control_reset(priv->reset);
+}
+
+static int phy_axg_pcie_exit(struct phy *phy)
+{
+	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
+	int ret;
+
+	ret = phy_exit(priv->analog);
+	if (ret != 0)
+		return ret;
+
+	return reset_control_reset(priv->reset);
+}
+
+static int phy_axg_pcie_reset(struct phy *phy)
+{
+	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
+	int ret = 0;
+
+	ret = phy_reset(priv->analog);
+	if (ret != 0)
+		goto out;
+
+	ret = reset_control_assert(priv->reset);
+	if (ret != 0)
+		goto out;
+	udelay(MESON_PCIE_RESET_DELAY);
+
+	ret = reset_control_deassert(priv->reset);
+	if (ret != 0)
+		goto out;
+	udelay(MESON_PCIE_RESET_DELAY);
+
+out:
+	return ret;
+}
+
+static const struct phy_ops phy_axg_pcie_ops = {
+	.init = phy_axg_pcie_init,
+	.exit = phy_axg_pcie_exit,
+	.power_on = phy_axg_pcie_power_on,
+	.power_off = phy_axg_pcie_power_off,
+	.reset = phy_axg_pcie_reset,
+	.owner = THIS_MODULE,
+};
+
+static int phy_axg_pcie_probe(struct platform_device *pdev)
+{
+	struct phy_provider *pphy;
+	struct device *dev = &pdev->dev;
+	struct phy_axg_pcie_priv *priv;
+	struct device_node *np = dev->of_node;
+	struct resource *res;
+	void __iomem *base;
+	int ret;
+
+	priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->phy = devm_phy_create(dev, np, &phy_axg_pcie_ops);
+	if (IS_ERR(priv->phy)) {
+		ret = PTR_ERR(priv->phy);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "failed to create PHY\n");
+		return ret;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	priv->regmap = devm_regmap_init_mmio(dev, base,
+					     &phy_axg_pcie_regmap_conf);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	priv->reset = devm_reset_control_array_get(dev, false, false);
+	if (IS_ERR(priv->reset))
+		return PTR_ERR(priv->reset);
+
+	priv->analog = devm_phy_optional_get(dev, "analog");
+	if (IS_ERR(priv->analog))
+		return PTR_ERR(priv->analog);
+
+	phy_set_drvdata(priv->phy, priv);
+	dev_set_drvdata(dev, priv);
+	pphy = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+	return PTR_ERR_OR_ZERO(pphy);
+}
+
+static const struct of_device_id phy_axg_pcie_of_match[] = {
+	{
+		.compatible = "amlogic,axg-pcie-phy",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, phy_axg_pcie_of_match);
+
+static struct platform_driver phy_axg_pcie_driver = {
+	.probe = phy_axg_pcie_probe,
+	.driver = {
+		.name = "phy-axg-pcie",
+		.of_match_table = phy_axg_pcie_of_match,
+	},
+};
+module_platform_driver(phy_axg_pcie_driver);
+
+MODULE_AUTHOR("Remi Pommarel <repk@triplefau.lt>");
+MODULE_DESCRIPTION("Amlogic AXG PCIE PHY driver");
+MODULE_LICENSE("GPL v2");
-- 
2.24.1


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

* [PATCH v5 7/7] PCI: amlogic: Use AXG PCIE
  2020-01-16 11:18 [PATCH v5 0/7] PCI: amlogic: Make PCIe working reliably on AXG platforms Remi Pommarel
                   ` (5 preceding siblings ...)
  2020-01-16 11:18 ` [PATCH v5 6/7] phy: amlogic: Add Amlogic AXG PCIE " Remi Pommarel
@ 2020-01-16 11:18 ` Remi Pommarel
  2020-01-16 20:13   ` Bjorn Helgaas
  2020-01-23  9:52   ` Jerome Brunet
  6 siblings, 2 replies; 18+ messages in thread
From: Remi Pommarel @ 2020-01-16 11:18 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: Jerome Brunet, linux-amlogic, linux-kernel, devicetree, Remi Pommarel

Now that PCIE PHY has been introduced for AXG, the whole has_shared_phy
logic can be mutualized between AXG and G12A platforms.

This new PHY makes use of the optional shared MIPI/PCIE analog PHY
found on AXG platforms, which need to be used in order to have reliable
PCIE communications.

Signed-off-by: Remi Pommarel <repk@triplefau.lt>
---
 drivers/pci/controller/dwc/pci-meson.c | 116 +++++--------------------
 1 file changed, 22 insertions(+), 94 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 3772b02a5c55..3715dceca1bf 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -66,7 +66,6 @@
 #define PORT_CLK_RATE			100000000UL
 #define MAX_PAYLOAD_SIZE		256
 #define MAX_READ_REQ_SIZE		256
-#define MESON_PCIE_PHY_POWERUP		0x1c
 #define PCIE_RESET_DELAY		500
 #define PCIE_SHARED_RESET		1
 #define PCIE_NORMAL_RESET		0
@@ -81,26 +80,19 @@ enum pcie_data_rate {
 struct meson_pcie_mem_res {
 	void __iomem *elbi_base;
 	void __iomem *cfg_base;
-	void __iomem *phy_base;
 };
 
 struct meson_pcie_clk_res {
 	struct clk *clk;
-	struct clk *mipi_gate;
 	struct clk *port_clk;
 	struct clk *general_clk;
 };
 
 struct meson_pcie_rc_reset {
-	struct reset_control *phy;
 	struct reset_control *port;
 	struct reset_control *apb;
 };
 
-struct meson_pcie_param {
-	bool has_shared_phy;
-};
-
 struct meson_pcie {
 	struct dw_pcie pci;
 	struct meson_pcie_mem_res mem_res;
@@ -108,7 +100,6 @@ struct meson_pcie {
 	struct meson_pcie_rc_reset mrst;
 	struct gpio_desc *reset_gpio;
 	struct phy *phy;
-	const struct meson_pcie_param *param;
 };
 
 static struct reset_control *meson_pcie_get_reset(struct meson_pcie *mp,
@@ -130,13 +121,6 @@ static int meson_pcie_get_resets(struct meson_pcie *mp)
 {
 	struct meson_pcie_rc_reset *mrst = &mp->mrst;
 
-	if (!mp->param->has_shared_phy) {
-		mrst->phy = meson_pcie_get_reset(mp, "phy", PCIE_SHARED_RESET);
-		if (IS_ERR(mrst->phy))
-			return PTR_ERR(mrst->phy);
-		reset_control_deassert(mrst->phy);
-	}
-
 	mrst->port = meson_pcie_get_reset(mp, "port", PCIE_NORMAL_RESET);
 	if (IS_ERR(mrst->port))
 		return PTR_ERR(mrst->port);
@@ -162,22 +146,6 @@ static void __iomem *meson_pcie_get_mem(struct platform_device *pdev,
 	return devm_ioremap_resource(dev, res);
 }
 
-static void __iomem *meson_pcie_get_mem_shared(struct platform_device *pdev,
-					       struct meson_pcie *mp,
-					       const char *id)
-{
-	struct device *dev = mp->pci.dev;
-	struct resource *res;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, id);
-	if (!res) {
-		dev_err(dev, "No REG resource %s\n", id);
-		return ERR_PTR(-ENXIO);
-	}
-
-	return devm_ioremap(dev, res->start, resource_size(res));
-}
-
 static int meson_pcie_get_mems(struct platform_device *pdev,
 			       struct meson_pcie *mp)
 {
@@ -189,14 +157,6 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
 	if (IS_ERR(mp->mem_res.cfg_base))
 		return PTR_ERR(mp->mem_res.cfg_base);
 
-	/* Meson AXG SoC has two PCI controllers use same phy register */
-	if (!mp->param->has_shared_phy) {
-		mp->mem_res.phy_base =
-			meson_pcie_get_mem_shared(pdev, mp, "phy");
-		if (IS_ERR(mp->mem_res.phy_base))
-			return PTR_ERR(mp->mem_res.phy_base);
-	}
-
 	return 0;
 }
 
@@ -204,37 +164,33 @@ static int meson_pcie_power_on(struct meson_pcie *mp)
 {
 	int ret = 0;
 
-	if (mp->param->has_shared_phy) {
-		ret = phy_init(mp->phy);
-		if (ret)
-			return ret;
+	ret = phy_init(mp->phy);
+	if (ret)
+		return ret;
 
-		ret = phy_power_on(mp->phy);
-		if (ret) {
-			phy_exit(mp->phy);
-			return ret;
-		}
-	} else
-		writel(MESON_PCIE_PHY_POWERUP, mp->mem_res.phy_base);
+	ret = phy_power_on(mp->phy);
+	if (ret) {
+		phy_exit(mp->phy);
+		return ret;
+	}
 
 	return 0;
 }
 
+static void meson_pcie_power_off(struct meson_pcie *mp)
+{
+	phy_power_off(mp->phy);
+	phy_exit(mp->phy);
+}
+
 static int meson_pcie_reset(struct meson_pcie *mp)
 {
 	struct meson_pcie_rc_reset *mrst = &mp->mrst;
 	int ret = 0;
 
-	if (mp->param->has_shared_phy) {
-		ret = phy_reset(mp->phy);
-		if (ret)
-			return ret;
-	} else {
-		reset_control_assert(mrst->phy);
-		udelay(PCIE_RESET_DELAY);
-		reset_control_deassert(mrst->phy);
-		udelay(PCIE_RESET_DELAY);
-	}
+	ret = phy_reset(mp->phy);
+	if (ret)
+		return ret;
 
 	reset_control_assert(mrst->port);
 	reset_control_assert(mrst->apb);
@@ -286,12 +242,6 @@ static int meson_pcie_probe_clocks(struct meson_pcie *mp)
 	if (IS_ERR(res->port_clk))
 		return PTR_ERR(res->port_clk);
 
-	if (!mp->param->has_shared_phy) {
-		res->mipi_gate = meson_pcie_probe_clock(dev, "mipi", 0);
-		if (IS_ERR(res->mipi_gate))
-			return PTR_ERR(res->mipi_gate);
-	}
-
 	res->general_clk = meson_pcie_probe_clock(dev, "general", 0);
 	if (IS_ERR(res->general_clk))
 		return PTR_ERR(res->general_clk);
@@ -562,7 +512,6 @@ static const struct dw_pcie_ops dw_pcie_ops = {
 
 static int meson_pcie_probe(struct platform_device *pdev)
 {
-	const struct meson_pcie_param *match_data;
 	struct device *dev = &pdev->dev;
 	struct dw_pcie *pci;
 	struct meson_pcie *mp;
@@ -576,17 +525,10 @@ static int meson_pcie_probe(struct platform_device *pdev)
 	pci->dev = dev;
 	pci->ops = &dw_pcie_ops;
 
-	match_data = of_device_get_match_data(dev);
-	if (!match_data) {
-		dev_err(dev, "failed to get match data\n");
-		return -ENODEV;
-	}
-	mp->param = match_data;
-
-	if (mp->param->has_shared_phy) {
-		mp->phy = devm_phy_get(dev, "pcie");
-		if (IS_ERR(mp->phy))
-			return PTR_ERR(mp->phy);
+	mp->phy = devm_phy_get(dev, "pcie");
+	if (IS_ERR(mp->phy)) {
+		dev_err(dev, "get phy failed, %ld\n", PTR_ERR(mp->phy));
+		return PTR_ERR(mp->phy);
 	}
 
 	mp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
@@ -636,30 +578,16 @@ static int meson_pcie_probe(struct platform_device *pdev)
 	return 0;
 
 err_phy:
-	if (mp->param->has_shared_phy) {
-		phy_power_off(mp->phy);
-		phy_exit(mp->phy);
-	}
-
+	meson_pcie_power_off(mp);
 	return ret;
 }
 
-static struct meson_pcie_param meson_pcie_axg_param = {
-	.has_shared_phy = false,
-};
-
-static struct meson_pcie_param meson_pcie_g12a_param = {
-	.has_shared_phy = true,
-};
-
 static const struct of_device_id meson_pcie_of_match[] = {
 	{
 		.compatible = "amlogic,axg-pcie",
-		.data = &meson_pcie_axg_param,
 	},
 	{
 		.compatible = "amlogic,g12a-pcie",
-		.data = &meson_pcie_g12a_param,
 	},
 	{},
 };
-- 
2.24.1


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

* Re: [PATCH v5 7/7] PCI: amlogic: Use AXG PCIE
  2020-01-16 11:18 ` [PATCH v5 7/7] PCI: amlogic: Use AXG PCIE Remi Pommarel
@ 2020-01-16 20:13   ` Bjorn Helgaas
  2020-01-23 10:00     ` Neil Armstrong
  2020-01-23  9:52   ` Jerome Brunet
  1 sibling, 1 reply; 18+ messages in thread
From: Bjorn Helgaas @ 2020-01-16 20:13 UTC (permalink / raw)
  To: Remi Pommarel
  Cc: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Neil Armstrong, Martin Blumenstingl,
	Rob Herring, Jerome Brunet, linux-amlogic, linux-kernel,
	devicetree, linux-pci

[+cc linux-pci, series at https://lore.kernel.org/r/20200116111850.23690-1-repk@triplefau.lt]

On Thu, Jan 16, 2020 at 12:18:50PM +0100, Remi Pommarel wrote:
> Now that PCIE PHY has been introduced for AXG, the whole has_shared_phy
> logic can be mutualized between AXG and G12A platforms.
> 
> This new PHY makes use of the optional shared MIPI/PCIE analog PHY
> found on AXG platforms, which need to be used in order to have reliable
> PCIE communications.
> 
> Signed-off-by: Remi Pommarel <repk@triplefau.lt>
> ---
>  drivers/pci/controller/dwc/pci-meson.c | 116 +++++--------------------
>  1 file changed, 22 insertions(+), 94 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
> index 3772b02a5c55..3715dceca1bf 100644
> --- a/drivers/pci/controller/dwc/pci-meson.c
> +++ b/drivers/pci/controller/dwc/pci-meson.c
> @@ -66,7 +66,6 @@
>  #define PORT_CLK_RATE			100000000UL
>  #define MAX_PAYLOAD_SIZE		256
>  #define MAX_READ_REQ_SIZE		256
> -#define MESON_PCIE_PHY_POWERUP		0x1c
>  #define PCIE_RESET_DELAY		500
>  #define PCIE_SHARED_RESET		1
>  #define PCIE_NORMAL_RESET		0
> @@ -81,26 +80,19 @@ enum pcie_data_rate {
>  struct meson_pcie_mem_res {
>  	void __iomem *elbi_base;
>  	void __iomem *cfg_base;
> -	void __iomem *phy_base;
>  };
>  
>  struct meson_pcie_clk_res {
>  	struct clk *clk;
> -	struct clk *mipi_gate;
>  	struct clk *port_clk;
>  	struct clk *general_clk;
>  };
>  
>  struct meson_pcie_rc_reset {
> -	struct reset_control *phy;
>  	struct reset_control *port;
>  	struct reset_control *apb;
>  };
>  
> -struct meson_pcie_param {
> -	bool has_shared_phy;
> -};
> -
>  struct meson_pcie {
>  	struct dw_pcie pci;
>  	struct meson_pcie_mem_res mem_res;
> @@ -108,7 +100,6 @@ struct meson_pcie {
>  	struct meson_pcie_rc_reset mrst;
>  	struct gpio_desc *reset_gpio;
>  	struct phy *phy;
> -	const struct meson_pcie_param *param;
>  };
>  
>  static struct reset_control *meson_pcie_get_reset(struct meson_pcie *mp,
> @@ -130,13 +121,6 @@ static int meson_pcie_get_resets(struct meson_pcie *mp)
>  {
>  	struct meson_pcie_rc_reset *mrst = &mp->mrst;
>  
> -	if (!mp->param->has_shared_phy) {
> -		mrst->phy = meson_pcie_get_reset(mp, "phy", PCIE_SHARED_RESET);
> -		if (IS_ERR(mrst->phy))
> -			return PTR_ERR(mrst->phy);
> -		reset_control_deassert(mrst->phy);
> -	}
> -
>  	mrst->port = meson_pcie_get_reset(mp, "port", PCIE_NORMAL_RESET);
>  	if (IS_ERR(mrst->port))
>  		return PTR_ERR(mrst->port);
> @@ -162,22 +146,6 @@ static void __iomem *meson_pcie_get_mem(struct platform_device *pdev,
>  	return devm_ioremap_resource(dev, res);
>  }
>  
> -static void __iomem *meson_pcie_get_mem_shared(struct platform_device *pdev,
> -					       struct meson_pcie *mp,
> -					       const char *id)
> -{
> -	struct device *dev = mp->pci.dev;
> -	struct resource *res;
> -
> -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, id);
> -	if (!res) {
> -		dev_err(dev, "No REG resource %s\n", id);
> -		return ERR_PTR(-ENXIO);
> -	}
> -
> -	return devm_ioremap(dev, res->start, resource_size(res));
> -}
> -
>  static int meson_pcie_get_mems(struct platform_device *pdev,
>  			       struct meson_pcie *mp)
>  {
> @@ -189,14 +157,6 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
>  	if (IS_ERR(mp->mem_res.cfg_base))
>  		return PTR_ERR(mp->mem_res.cfg_base);
>  
> -	/* Meson AXG SoC has two PCI controllers use same phy register */
> -	if (!mp->param->has_shared_phy) {
> -		mp->mem_res.phy_base =
> -			meson_pcie_get_mem_shared(pdev, mp, "phy");
> -		if (IS_ERR(mp->mem_res.phy_base))
> -			return PTR_ERR(mp->mem_res.phy_base);
> -	}
> -
>  	return 0;
>  }
>  
> @@ -204,37 +164,33 @@ static int meson_pcie_power_on(struct meson_pcie *mp)
>  {
>  	int ret = 0;
>  
> -	if (mp->param->has_shared_phy) {
> -		ret = phy_init(mp->phy);
> -		if (ret)
> -			return ret;
> +	ret = phy_init(mp->phy);
> +	if (ret)
> +		return ret;
>  
> -		ret = phy_power_on(mp->phy);
> -		if (ret) {
> -			phy_exit(mp->phy);
> -			return ret;
> -		}
> -	} else
> -		writel(MESON_PCIE_PHY_POWERUP, mp->mem_res.phy_base);
> +	ret = phy_power_on(mp->phy);
> +	if (ret) {
> +		phy_exit(mp->phy);
> +		return ret;
> +	}
>  
>  	return 0;
>  }
>  
> +static void meson_pcie_power_off(struct meson_pcie *mp)
> +{
> +	phy_power_off(mp->phy);
> +	phy_exit(mp->phy);
> +}
> +
>  static int meson_pcie_reset(struct meson_pcie *mp)
>  {
>  	struct meson_pcie_rc_reset *mrst = &mp->mrst;
>  	int ret = 0;
>  
> -	if (mp->param->has_shared_phy) {
> -		ret = phy_reset(mp->phy);
> -		if (ret)
> -			return ret;
> -	} else {
> -		reset_control_assert(mrst->phy);
> -		udelay(PCIE_RESET_DELAY);
> -		reset_control_deassert(mrst->phy);
> -		udelay(PCIE_RESET_DELAY);
> -	}
> +	ret = phy_reset(mp->phy);
> +	if (ret)
> +		return ret;
>  
>  	reset_control_assert(mrst->port);
>  	reset_control_assert(mrst->apb);
> @@ -286,12 +242,6 @@ static int meson_pcie_probe_clocks(struct meson_pcie *mp)
>  	if (IS_ERR(res->port_clk))
>  		return PTR_ERR(res->port_clk);
>  
> -	if (!mp->param->has_shared_phy) {
> -		res->mipi_gate = meson_pcie_probe_clock(dev, "mipi", 0);
> -		if (IS_ERR(res->mipi_gate))
> -			return PTR_ERR(res->mipi_gate);
> -	}
> -
>  	res->general_clk = meson_pcie_probe_clock(dev, "general", 0);
>  	if (IS_ERR(res->general_clk))
>  		return PTR_ERR(res->general_clk);
> @@ -562,7 +512,6 @@ static const struct dw_pcie_ops dw_pcie_ops = {
>  
>  static int meson_pcie_probe(struct platform_device *pdev)
>  {
> -	const struct meson_pcie_param *match_data;
>  	struct device *dev = &pdev->dev;
>  	struct dw_pcie *pci;
>  	struct meson_pcie *mp;
> @@ -576,17 +525,10 @@ static int meson_pcie_probe(struct platform_device *pdev)
>  	pci->dev = dev;
>  	pci->ops = &dw_pcie_ops;
>  
> -	match_data = of_device_get_match_data(dev);
> -	if (!match_data) {
> -		dev_err(dev, "failed to get match data\n");
> -		return -ENODEV;
> -	}
> -	mp->param = match_data;
> -
> -	if (mp->param->has_shared_phy) {
> -		mp->phy = devm_phy_get(dev, "pcie");
> -		if (IS_ERR(mp->phy))
> -			return PTR_ERR(mp->phy);
> +	mp->phy = devm_phy_get(dev, "pcie");
> +	if (IS_ERR(mp->phy)) {
> +		dev_err(dev, "get phy failed, %ld\n", PTR_ERR(mp->phy));
> +		return PTR_ERR(mp->phy);
>  	}
>  
>  	mp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
> @@ -636,30 +578,16 @@ static int meson_pcie_probe(struct platform_device *pdev)
>  	return 0;
>  
>  err_phy:
> -	if (mp->param->has_shared_phy) {
> -		phy_power_off(mp->phy);
> -		phy_exit(mp->phy);
> -	}
> -
> +	meson_pcie_power_off(mp);
>  	return ret;
>  }
>  
> -static struct meson_pcie_param meson_pcie_axg_param = {
> -	.has_shared_phy = false,
> -};
> -
> -static struct meson_pcie_param meson_pcie_g12a_param = {
> -	.has_shared_phy = true,
> -};
> -
>  static const struct of_device_id meson_pcie_of_match[] = {
>  	{
>  		.compatible = "amlogic,axg-pcie",
> -		.data = &meson_pcie_axg_param,
>  	},
>  	{
>  		.compatible = "amlogic,g12a-pcie",
> -		.data = &meson_pcie_g12a_param,
>  	},
>  	{},
>  };
> -- 
> 2.24.1
> 

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

* Re: [PATCH v5 1/7] dt-bindings: Add AXG PCIE PHY bindings
  2020-01-16 11:18 ` [PATCH v5 1/7] dt-bindings: Add AXG PCIE PHY bindings Remi Pommarel
@ 2020-01-17 16:03   ` Rob Herring
  0 siblings, 0 replies; 18+ messages in thread
From: Rob Herring @ 2020-01-17 16:03 UTC (permalink / raw)
  To: Remi Pommarel
  Cc: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Jerome Brunet, linux-amlogic, linux-kernel,
	devicetree, Remi Pommarel

On Thu, 16 Jan 2020 12:18:44 +0100, Remi Pommarel wrote:
> Add documentation for PCIE PHYs found in AXG SoCs.
> 
> Signed-off-by: Remi Pommarel <repk@triplefau.lt>
> ---
>  .../bindings/phy/amlogic,meson-axg-pcie.yaml  | 48 +++++++++++++++++++
>  1 file changed, 48 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/amlogic,meson-axg-pcie.yaml
> 

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

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

* Re: [PATCH v5 2/7] dt-bindings: Add AXG shared MIPI/PCIE analog PHY bindings
  2020-01-16 11:18 ` [PATCH v5 2/7] dt-bindings: Add AXG shared MIPI/PCIE analog " Remi Pommarel
@ 2020-01-17 16:04   ` Rob Herring
  0 siblings, 0 replies; 18+ messages in thread
From: Rob Herring @ 2020-01-17 16:04 UTC (permalink / raw)
  To: Remi Pommarel
  Cc: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Jerome Brunet, linux-amlogic, linux-kernel,
	devicetree, Remi Pommarel

On Thu, 16 Jan 2020 12:18:45 +0100, Remi Pommarel wrote:
> Add documentation for the shared MIPI/PCIE analog PHY found in AXG
> SoCs.
> 
> Signed-off-by: Remi Pommarel <repk@triplefau.lt>
> ---
>  .../amlogic,meson-axg-mipi-pcie-analog.yaml   | 33 +++++++++++++++++++
>  1 file changed, 33 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml
> 

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

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

* Re: [PATCH v5 3/7] dt-bindings: PCI: meson: Update PCIE bindings documentation
  2020-01-16 11:18 ` [PATCH v5 3/7] dt-bindings: PCI: meson: Update PCIE bindings documentation Remi Pommarel
@ 2020-01-17 16:05   ` Rob Herring
  0 siblings, 0 replies; 18+ messages in thread
From: Rob Herring @ 2020-01-17 16:05 UTC (permalink / raw)
  To: Remi Pommarel
  Cc: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Jerome Brunet, linux-amlogic, linux-kernel,
	devicetree, Remi Pommarel

On Thu, 16 Jan 2020 12:18:46 +0100, Remi Pommarel wrote:
> Now that a new PHYs has been introduced for AXG SoC family, update
> dt bindings documentation.
> 
> Please note that this breaks backward compatibility but as not a single
> devicetree uses that yet that seems ok.
> 
> Signed-off-by: Remi Pommarel <repk@triplefau.lt>
> ---
>  .../bindings/pci/amlogic,meson-pcie.txt       | 22 ++++++++-----------
>  1 file changed, 9 insertions(+), 13 deletions(-)
> 

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

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

* Re: [PATCH v5 5/7] phy: amlogic: Add Amlogic AXG MIPI/PCIE analog PHY Driver
  2020-01-16 11:18 ` [PATCH v5 5/7] phy: amlogic: Add Amlogic AXG MIPI/PCIE analog PHY Driver Remi Pommarel
@ 2020-01-23  9:37   ` Jerome Brunet
  0 siblings, 0 replies; 18+ messages in thread
From: Jerome Brunet @ 2020-01-23  9:37 UTC (permalink / raw)
  To: Remi Pommarel, Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: linux-amlogic, linux-kernel, devicetree


On Thu 16 Jan 2020 at 12:18, Remi Pommarel <repk@triplefau.lt> wrote:

> This adds support for the MIPI analog PHY which is also used for PCIE
> found in the Amlogic AXG SoC Family.
>
> MIPI or PCIE selection is done by the #phy-cells, making the mode
> static and exclusive.
>
> For now only PCIE fonctionality is supported.
>
> This PHY will be used to replace the mipi_enable clock gating logic
> which was mistakenly added in the clock subsystem. This also activate
> a non documented band gap bit in those registers that allows reliable
> PCIE clock signal generation on AXG platforms.
>

I don't the phy subsystem much but this looks sane and aligned with what
was discussed for this Amlogic SoC.

Thanks for this Remi !

Acked-by: Jerome Brunet <jbrunet@baylibre.com>

> Signed-off-by: Remi Pommarel <repk@triplefau.lt>
> ---
>  drivers/phy/amlogic/Kconfig                   |  11 +
>  drivers/phy/amlogic/Makefile                  |  11 +-
>  .../amlogic/phy-meson-axg-mipi-pcie-analog.c  | 188 ++++++++++++++++++
>  3 files changed, 205 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
>
> diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
> index af774ac2b934..8c9cf2403591 100644
> --- a/drivers/phy/amlogic/Kconfig
> +++ b/drivers/phy/amlogic/Kconfig
> @@ -59,3 +59,14 @@ config PHY_MESON_G12A_USB3_PCIE
>  	  Enable this to support the Meson USB3 + PCIE Combo PHY found
>  	  in Meson G12A SoCs.
>  	  If unsure, say N.
> +
> +config PHY_MESON_AXG_MIPI_PCIE_ANALOG
> +	tristate "Meson AXG MIPI + PCIE analog PHY driver"
> +	default ARCH_MESON
> +	depends on OF && (ARCH_MESON || COMPILE_TEST)
> +	select GENERIC_PHY
> +	select REGMAP_MMIO
> +	help
> +	  Enable this to support the Meson MIPI + PCIE analog PHY
> +	  found in Meson AXG SoCs.
> +	  If unsure, say N.
> diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile
> index 11d1c42ac2be..0aecf92d796a 100644
> --- a/drivers/phy/amlogic/Makefile
> +++ b/drivers/phy/amlogic/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0-only
> -obj-$(CONFIG_PHY_MESON8B_USB2)		+= phy-meson8b-usb2.o
> -obj-$(CONFIG_PHY_MESON_GXL_USB2)	+= phy-meson-gxl-usb2.o
> -obj-$(CONFIG_PHY_MESON_G12A_USB2)	+= phy-meson-g12a-usb2.o
> -obj-$(CONFIG_PHY_MESON_GXL_USB3)	+= phy-meson-gxl-usb3.o
> -obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE)	+= phy-meson-g12a-usb3-pcie.o
> +obj-$(CONFIG_PHY_MESON8B_USB2)			+= phy-meson8b-usb2.o
> +obj-$(CONFIG_PHY_MESON_GXL_USB2)		+= phy-meson-gxl-usb2.o
> +obj-$(CONFIG_PHY_MESON_G12A_USB2)		+= phy-meson-g12a-usb2.o
> +obj-$(CONFIG_PHY_MESON_GXL_USB3)		+= phy-meson-gxl-usb3.o
> +obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE)		+= phy-meson-g12a-usb3-pcie.o
> +obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG)	+= phy-meson-axg-mipi-pcie-analog.o
> diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
> new file mode 100644
> index 000000000000..1431cbf885e1
> --- /dev/null
> +++ b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
> @@ -0,0 +1,188 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Amlogic AXG MIPI + PCIE analog PHY driver
> + *
> + * Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
> + */
> +#include <linux/module.h>
> +#include <linux/phy/phy.h>
> +#include <linux/regmap.h>
> +#include <linux/platform_device.h>
> +#include <dt-bindings/phy/phy.h>
> +
> +#define HHI_MIPI_CNTL0 0x00
> +#define		HHI_MIPI_CNTL0_COMMON_BLOCK	GENMASK(31, 28)
> +#define		HHI_MIPI_CNTL0_ENABLE		BIT(29)
> +#define		HHI_MIPI_CNTL0_BANDGAP		BIT(26)
> +#define		HHI_MIPI_CNTL0_DECODE_TO_RTERM	GENMASK(15, 12)
> +#define		HHI_MIPI_CNTL0_OUTPUT_EN	BIT(3)
> +
> +#define HHI_MIPI_CNTL1 0x01
> +#define		HHI_MIPI_CNTL1_CH0_CML_PDR_EN	BIT(12)
> +#define		HHI_MIPI_CNTL1_LP_ABILITY	GENMASK(5, 4)
> +#define		HHI_MIPI_CNTL1_LP_RESISTER	BIT(3)
> +#define		HHI_MIPI_CNTL1_INPUT_SETTING	BIT(2)
> +#define		HHI_MIPI_CNTL1_INPUT_SEL	BIT(1)
> +#define		HHI_MIPI_CNTL1_PRBS7_EN		BIT(0)
> +
> +#define HHI_MIPI_CNTL2 0x02
> +#define		HHI_MIPI_CNTL2_CH_PU		GENMASK(31, 25)
> +#define		HHI_MIPI_CNTL2_CH_CTL		GENMASK(24, 19)
> +#define		HHI_MIPI_CNTL2_CH0_DIGDR_EN	BIT(18)
> +#define		HHI_MIPI_CNTL2_CH_DIGDR_EN	BIT(17)
> +#define		HHI_MIPI_CNTL2_LPULPS_EN	BIT(16)
> +#define		HHI_MIPI_CNTL2_CH_EN(n)		BIT(15 - (n))
> +#define		HHI_MIPI_CNTL2_CH0_LP_CTL	GENMASK(10, 1)
> +
> +struct phy_axg_mipi_pcie_analog_priv {
> +	struct phy *phy;
> +	unsigned int mode;
> +	struct regmap *regmap;
> +};
> +
> +static const struct regmap_config phy_axg_mipi_pcie_analog_regmap_conf = {
> +	.reg_bits = 8,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.max_register = HHI_MIPI_CNTL2,
> +};
> +
> +static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy)
> +{
> +	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
> +
> +	/* MIPI not supported yet */
> +	if (priv->mode != PHY_TYPE_PCIE)
> +		return -EINVAL;
> +
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			   HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
> +
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			   HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
> +	return 0;
> +}
> +
> +static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy)
> +{
> +	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
> +
> +	/* MIPI not supported yet */
> +	if (priv->mode != PHY_TYPE_PCIE)
> +		return -EINVAL;
> +
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			   HHI_MIPI_CNTL0_BANDGAP, 0);
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			   HHI_MIPI_CNTL0_ENABLE, 0);
> +	return 0;
> +}
> +
> +static int phy_axg_mipi_pcie_analog_init(struct phy *phy)
> +{
> +	return 0;
> +}
> +
> +static int phy_axg_mipi_pcie_analog_exit(struct phy *phy)
> +{
> +	return 0;
> +}
> +
> +static const struct phy_ops phy_axg_mipi_pcie_analog_ops = {
> +	.init = phy_axg_mipi_pcie_analog_init,
> +	.exit = phy_axg_mipi_pcie_analog_exit,
> +	.power_on = phy_axg_mipi_pcie_analog_power_on,
> +	.power_off = phy_axg_mipi_pcie_analog_power_off,
> +	.owner = THIS_MODULE,
> +};
> +
> +static struct phy *phy_axg_mipi_pcie_analog_xlate(struct device *dev,
> +						  struct of_phandle_args *args)
> +{
> +	struct phy_axg_mipi_pcie_analog_priv *priv = dev_get_drvdata(dev);
> +	unsigned int mode;
> +
> +	if (args->args_count != 1) {
> +		dev_err(dev, "invalid number of arguments\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	mode = args->args[0];
> +
> +	/* MIPI mode is not supported yet */
> +	if (mode != PHY_TYPE_PCIE) {
> +		dev_err(dev, "invalid phy mode select argument\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	priv->mode = mode;
> +	return priv->phy;
> +}
> +
> +static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
> +{
> +	struct phy_provider *phy;
> +	struct device *dev = &pdev->dev;
> +	struct phy_axg_mipi_pcie_analog_priv *priv;
> +	struct device_node *np = dev->of_node;
> +	struct regmap *map;
> +	struct resource *res;
> +	void __iomem *base;
> +	int ret;
> +
> +	priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(base)) {
> +		dev_err(dev, "failed to get regmap base\n");
> +		return PTR_ERR(base);
> +	}
> +
> +	map = devm_regmap_init_mmio(dev, base,
> +				    &phy_axg_mipi_pcie_analog_regmap_conf);
> +	if (IS_ERR(map)) {
> +		dev_err(dev, "failed to get HHI regmap\n");
> +		return PTR_ERR(map);
> +	}
> +	priv->regmap = map;
> +
> +	priv->phy = devm_phy_create(dev, np, &phy_axg_mipi_pcie_analog_ops);
> +	if (IS_ERR(priv->phy)) {
> +		ret = PTR_ERR(priv->phy);
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(dev, "failed to create PHY\n");
> +		return ret;
> +	}
> +
> +	phy_set_drvdata(priv->phy, priv);
> +	dev_set_drvdata(dev, priv);
> +
> +	phy = devm_of_phy_provider_register(dev,
> +					    phy_axg_mipi_pcie_analog_xlate);
> +
> +	return PTR_ERR_OR_ZERO(phy);
> +}
> +
> +static const struct of_device_id phy_axg_mipi_pcie_analog_of_match[] = {
> +	{
> +		.compatible = "amlogic,axg-mipi-pcie-analog-phy",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, phy_axg_mipi_pcie_analog_of_match);
> +
> +static struct platform_driver phy_axg_mipi_pcie_analog_driver = {
> +	.probe = phy_axg_mipi_pcie_analog_probe,
> +	.driver = {
> +		.name = "phy-axg-mipi-pcie-analog",
> +		.of_match_table = phy_axg_mipi_pcie_analog_of_match,
> +	},
> +};
> +module_platform_driver(phy_axg_mipi_pcie_analog_driver);
> +
> +MODULE_AUTHOR("Remi Pommarel <repk@triplefau.lt>");
> +MODULE_DESCRIPTION("Amlogic AXG MIPI + PCIE analog PHY driver");
> +MODULE_LICENSE("GPL v2");


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

* Re: [PATCH v5 6/7] phy: amlogic: Add Amlogic AXG PCIE PHY Driver
  2020-01-16 11:18 ` [PATCH v5 6/7] phy: amlogic: Add Amlogic AXG PCIE " Remi Pommarel
@ 2020-01-23  9:44   ` Jerome Brunet
  2020-01-23 10:56     ` Remi Pommarel
  0 siblings, 1 reply; 18+ messages in thread
From: Jerome Brunet @ 2020-01-23  9:44 UTC (permalink / raw)
  To: Remi Pommarel, Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: linux-amlogic, linux-kernel, devicetree


On Thu 16 Jan 2020 at 12:18, Remi Pommarel <repk@triplefau.lt> wrote:

> This adds support for the PCI PHY found in the Amlogic AXG SoC Family.
> This will allow to mutualize code in pci-meson.c between AXG and G12A
> SoC.
>
> This PHY can chain and use an optional analog PHY, which is used on
> AXG platform to have reliable PCIe communication.
>
> Signed-off-by: Remi Pommarel <repk@triplefau.lt>
> ---
>  drivers/phy/amlogic/Kconfig              |  11 ++
>  drivers/phy/amlogic/Makefile             |   1 +
>  drivers/phy/amlogic/phy-meson-axg-pcie.c | 192 +++++++++++++++++++++++
>  3 files changed, 204 insertions(+)
>  create mode 100644 drivers/phy/amlogic/phy-meson-axg-pcie.c
>
> diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
> index 8c9cf2403591..71801e30d601 100644
> --- a/drivers/phy/amlogic/Kconfig
> +++ b/drivers/phy/amlogic/Kconfig
> @@ -60,6 +60,17 @@ config PHY_MESON_G12A_USB3_PCIE
>  	  in Meson G12A SoCs.
>  	  If unsure, say N.
>  
> +config PHY_MESON_AXG_PCIE
> +	tristate "Meson AXG PCIE PHY driver"
> +	default ARCH_MESON
> +	depends on OF && (ARCH_MESON || COMPILE_TEST)
> +	select GENERIC_PHY
> +	select REGMAP_MMIO
> +	help
> +	  Enable this to support the Meson MIPI + PCIE PHY found
> +	  in Meson AXG SoCs.
> +	  If unsure, say N.
> +
>  config PHY_MESON_AXG_MIPI_PCIE_ANALOG
>  	tristate "Meson AXG MIPI + PCIE analog PHY driver"
>  	default ARCH_MESON
> diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile
> index 0aecf92d796a..e2baa133f7af 100644
> --- a/drivers/phy/amlogic/Makefile
> +++ b/drivers/phy/amlogic/Makefile
> @@ -4,4 +4,5 @@ obj-$(CONFIG_PHY_MESON_GXL_USB2)		+= phy-meson-gxl-usb2.o
>  obj-$(CONFIG_PHY_MESON_G12A_USB2)		+= phy-meson-g12a-usb2.o
>  obj-$(CONFIG_PHY_MESON_GXL_USB3)		+= phy-meson-gxl-usb3.o
>  obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE)		+= phy-meson-g12a-usb3-pcie.o
> +obj-$(CONFIG_PHY_MESON_AXG_PCIE)		+= phy-meson-axg-pcie.o
>  obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG)	+= phy-meson-axg-mipi-pcie-analog.o
> diff --git a/drivers/phy/amlogic/phy-meson-axg-pcie.c b/drivers/phy/amlogic/phy-meson-axg-pcie.c
> new file mode 100644
> index 000000000000..0c5d0732cd1c
> --- /dev/null
> +++ b/drivers/phy/amlogic/phy-meson-axg-pcie.c
> @@ -0,0 +1,192 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Amlogic AXG PCIE PHY driver
> + *
> + * Copyright (C) 2020 Remi Pommarel <repk@triplefau.lt>
> + */
> +#include <linux/module.h>
> +#include <linux/phy/phy.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +#include <linux/platform_device.h>
> +#include <linux/bitfield.h>
> +#include <dt-bindings/phy/phy.h>
> +
> +#define MESON_PCIE_REG0 0x00
> +#define		MESON_PCIE_COMMON_CLK	BIT(4)
> +#define		MESON_PCIE_PORT_SEL	GENMASK(3, 2)
> +#define		MESON_PCIE_CLK		BIT(1)
> +#define		MESON_PCIE_POWERDOWN	BIT(0)
> +
> +#define MESON_PCIE_TWO_X1		FIELD_PREP(MESON_PCIE_PORT_SEL, 0x3)
> +#define MESON_PCIE_COMMON_REF_CLK	FIELD_PREP(MESON_PCIE_COMMON_CLK, 0x1)
> +#define MESON_PCIE_PHY_INIT		(MESON_PCIE_TWO_X1 |		\
> +					 MESON_PCIE_COMMON_REF_CLK)
> +#define MESON_PCIE_RESET_DELAY		500
> +
> +struct phy_axg_pcie_priv {
> +	struct phy *phy;
> +	struct phy *analog;
> +	struct regmap *regmap;
> +	struct reset_control *reset;
> +};
> +
> +static const struct regmap_config phy_axg_pcie_regmap_conf = {
> +	.reg_bits = 8,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.max_register = MESON_PCIE_REG0,
> +};
> +
> +static int phy_axg_pcie_power_on(struct phy *phy)
> +{
> +	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
> +	int ret;
> +
> +	ret = phy_power_on(priv->analog);
> +	if (ret != 0)
> +		return ret;
> +
> +	regmap_update_bits(priv->regmap, MESON_PCIE_REG0,
> +			   MESON_PCIE_POWERDOWN, 0);
> +	return 0;
> +}
> +
> +static int phy_axg_pcie_power_off(struct phy *phy)
> +{
> +	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
> +	int ret;
> +
> +	ret = phy_power_off(priv->analog);
> +	if (ret != 0)
> +		return ret;
> +
> +	regmap_update_bits(priv->regmap, MESON_PCIE_REG0,
> +			   MESON_PCIE_POWERDOWN, 1);
> +	return 0;
> +}
> +
> +static int phy_axg_pcie_init(struct phy *phy)
> +{
> +	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
> +	int ret;
> +
> +	ret = phy_init(priv->analog);
> +	if (ret != 0)
> +		return ret;
> +
> +	regmap_write(priv->regmap, MESON_PCIE_REG0, MESON_PCIE_PHY_INIT);
> +	return reset_control_reset(priv->reset);
> +}
> +
> +static int phy_axg_pcie_exit(struct phy *phy)
> +{
> +	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
> +	int ret;
> +
> +	ret = phy_exit(priv->analog);
> +	if (ret != 0)
> +		return ret;
> +
> +	return reset_control_reset(priv->reset);
> +}
> +
> +static int phy_axg_pcie_reset(struct phy *phy)
> +{
> +	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
> +	int ret = 0;
> +
> +	ret = phy_reset(priv->analog);
> +	if (ret != 0)
> +		goto out;
> +
> +	ret = reset_control_assert(priv->reset);
> +	if (ret != 0)
> +		goto out;
> +	udelay(MESON_PCIE_RESET_DELAY);
> +
> +	ret = reset_control_deassert(priv->reset);
> +	if (ret != 0)
> +		goto out;
> +	udelay(MESON_PCIE_RESET_DELAY);
> +
> +out:
> +	return ret;
> +}
> +
> +static const struct phy_ops phy_axg_pcie_ops = {
> +	.init = phy_axg_pcie_init,
> +	.exit = phy_axg_pcie_exit,
> +	.power_on = phy_axg_pcie_power_on,
> +	.power_off = phy_axg_pcie_power_off,
> +	.reset = phy_axg_pcie_reset,
> +	.owner = THIS_MODULE,
> +};
> +
> +static int phy_axg_pcie_probe(struct platform_device *pdev)
> +{
> +	struct phy_provider *pphy;
> +	struct device *dev = &pdev->dev;
> +	struct phy_axg_pcie_priv *priv;
> +	struct device_node *np = dev->of_node;
> +	struct resource *res;
> +	void __iomem *base;
> +	int ret;
> +
> +	priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->phy = devm_phy_create(dev, np, &phy_axg_pcie_ops);
> +	if (IS_ERR(priv->phy)) {
> +		ret = PTR_ERR(priv->phy);
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(dev, "failed to create PHY\n");
> +		return ret;
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	priv->regmap = devm_regmap_init_mmio(dev, base,
> +					     &phy_axg_pcie_regmap_conf);
> +	if (IS_ERR(priv->regmap))
> +		return PTR_ERR(priv->regmap);
> +
> +	priv->reset = devm_reset_control_array_get(dev, false, false);
> +	if (IS_ERR(priv->reset))
> +		return PTR_ERR(priv->reset);
> +
> +	priv->analog = devm_phy_optional_get(dev, "analog");
> +	if (IS_ERR(priv->analog))
> +		return PTR_ERR(priv->analog);

Isn't required for on the axg platform for the pcie to work reliably ?
Does this driver support another SoC ?

> +
> +	phy_set_drvdata(priv->phy, priv);
> +	dev_set_drvdata(dev, priv);
> +	pphy = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> +	return PTR_ERR_OR_ZERO(pphy);
> +}
> +
> +static const struct of_device_id phy_axg_pcie_of_match[] = {
> +	{
> +		.compatible = "amlogic,axg-pcie-phy",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, phy_axg_pcie_of_match);
> +
> +static struct platform_driver phy_axg_pcie_driver = {
> +	.probe = phy_axg_pcie_probe,
> +	.driver = {
> +		.name = "phy-axg-pcie",
> +		.of_match_table = phy_axg_pcie_of_match,
> +	},
> +};
> +module_platform_driver(phy_axg_pcie_driver);
> +
> +MODULE_AUTHOR("Remi Pommarel <repk@triplefau.lt>");
> +MODULE_DESCRIPTION("Amlogic AXG PCIE PHY driver");
> +MODULE_LICENSE("GPL v2");


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

* Re: [PATCH v5 7/7] PCI: amlogic: Use AXG PCIE
  2020-01-16 11:18 ` [PATCH v5 7/7] PCI: amlogic: Use AXG PCIE Remi Pommarel
  2020-01-16 20:13   ` Bjorn Helgaas
@ 2020-01-23  9:52   ` Jerome Brunet
  1 sibling, 0 replies; 18+ messages in thread
From: Jerome Brunet @ 2020-01-23  9:52 UTC (permalink / raw)
  To: Remi Pommarel, Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring
  Cc: linux-amlogic, linux-kernel, devicetree


On Thu 16 Jan 2020 at 12:18, Remi Pommarel <repk@triplefau.lt> wrote:

> Now that PCIE PHY has been introduced for AXG, the whole has_shared_phy
> logic can be mutualized between AXG and G12A platforms.

This simply the driver and make it a lot easier to follow ! Thanks !

>
> This new PHY makes use of the optional shared MIPI/PCIE analog PHY
> found on AXG platforms, which need to be used in order to have reliable
> PCIE communications.

I'm a bit confused by the optional part ... from the probe of this
driver, it does not seems optional ?

>
> Signed-off-by: Remi Pommarel <repk@triplefau.lt>
> ---
>  drivers/pci/controller/dwc/pci-meson.c | 116 +++++--------------------
>  1 file changed, 22 insertions(+), 94 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
> index 3772b02a5c55..3715dceca1bf 100644
> --- a/drivers/pci/controller/dwc/pci-meson.c
> +++ b/drivers/pci/controller/dwc/pci-meson.c
> @@ -66,7 +66,6 @@
>  #define PORT_CLK_RATE			100000000UL
>  #define MAX_PAYLOAD_SIZE		256
>  #define MAX_READ_REQ_SIZE		256
> -#define MESON_PCIE_PHY_POWERUP		0x1c
>  #define PCIE_RESET_DELAY		500
>  #define PCIE_SHARED_RESET		1
>  #define PCIE_NORMAL_RESET		0
> @@ -81,26 +80,19 @@ enum pcie_data_rate {
>  struct meson_pcie_mem_res {
>  	void __iomem *elbi_base;
>  	void __iomem *cfg_base;
> -	void __iomem *phy_base;
>  };
>  
>  struct meson_pcie_clk_res {
>  	struct clk *clk;
> -	struct clk *mipi_gate;
>  	struct clk *port_clk;
>  	struct clk *general_clk;
>  };
>  
>  struct meson_pcie_rc_reset {
> -	struct reset_control *phy;
>  	struct reset_control *port;
>  	struct reset_control *apb;
>  };
>  
> -struct meson_pcie_param {
> -	bool has_shared_phy;
> -};
> -
>  struct meson_pcie {
>  	struct dw_pcie pci;
>  	struct meson_pcie_mem_res mem_res;
> @@ -108,7 +100,6 @@ struct meson_pcie {
>  	struct meson_pcie_rc_reset mrst;
>  	struct gpio_desc *reset_gpio;
>  	struct phy *phy;
> -	const struct meson_pcie_param *param;
>  };
>  
>  static struct reset_control *meson_pcie_get_reset(struct meson_pcie *mp,
> @@ -130,13 +121,6 @@ static int meson_pcie_get_resets(struct meson_pcie *mp)
>  {
>  	struct meson_pcie_rc_reset *mrst = &mp->mrst;
>  
> -	if (!mp->param->has_shared_phy) {
> -		mrst->phy = meson_pcie_get_reset(mp, "phy", PCIE_SHARED_RESET);
> -		if (IS_ERR(mrst->phy))
> -			return PTR_ERR(mrst->phy);
> -		reset_control_deassert(mrst->phy);
> -	}
> -
>  	mrst->port = meson_pcie_get_reset(mp, "port", PCIE_NORMAL_RESET);
>  	if (IS_ERR(mrst->port))
>  		return PTR_ERR(mrst->port);
> @@ -162,22 +146,6 @@ static void __iomem *meson_pcie_get_mem(struct platform_device *pdev,
>  	return devm_ioremap_resource(dev, res);
>  }
>  
> -static void __iomem *meson_pcie_get_mem_shared(struct platform_device *pdev,
> -					       struct meson_pcie *mp,
> -					       const char *id)
> -{
> -	struct device *dev = mp->pci.dev;
> -	struct resource *res;
> -
> -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, id);
> -	if (!res) {
> -		dev_err(dev, "No REG resource %s\n", id);
> -		return ERR_PTR(-ENXIO);
> -	}
> -
> -	return devm_ioremap(dev, res->start, resource_size(res));
> -}
> -
>  static int meson_pcie_get_mems(struct platform_device *pdev,
>  			       struct meson_pcie *mp)
>  {
> @@ -189,14 +157,6 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
>  	if (IS_ERR(mp->mem_res.cfg_base))
>  		return PTR_ERR(mp->mem_res.cfg_base);
>  
> -	/* Meson AXG SoC has two PCI controllers use same phy register */
> -	if (!mp->param->has_shared_phy) {
> -		mp->mem_res.phy_base =
> -			meson_pcie_get_mem_shared(pdev, mp, "phy");
> -		if (IS_ERR(mp->mem_res.phy_base))
> -			return PTR_ERR(mp->mem_res.phy_base);
> -	}
> -
>  	return 0;
>  }
>  
> @@ -204,37 +164,33 @@ static int meson_pcie_power_on(struct meson_pcie *mp)
>  {
>  	int ret = 0;
>  
> -	if (mp->param->has_shared_phy) {
> -		ret = phy_init(mp->phy);
> -		if (ret)
> -			return ret;
> +	ret = phy_init(mp->phy);
> +	if (ret)
> +		return ret;
>  
> -		ret = phy_power_on(mp->phy);
> -		if (ret) {
> -			phy_exit(mp->phy);
> -			return ret;
> -		}
> -	} else
> -		writel(MESON_PCIE_PHY_POWERUP, mp->mem_res.phy_base);
> +	ret = phy_power_on(mp->phy);
> +	if (ret) {
> +		phy_exit(mp->phy);
> +		return ret;
> +	}
>  
>  	return 0;
>  }
>  
> +static void meson_pcie_power_off(struct meson_pcie *mp)
> +{
> +	phy_power_off(mp->phy);
> +	phy_exit(mp->phy);
> +}
> +
>  static int meson_pcie_reset(struct meson_pcie *mp)
>  {
>  	struct meson_pcie_rc_reset *mrst = &mp->mrst;
>  	int ret = 0;
>  
> -	if (mp->param->has_shared_phy) {
> -		ret = phy_reset(mp->phy);
> -		if (ret)
> -			return ret;
> -	} else {
> -		reset_control_assert(mrst->phy);
> -		udelay(PCIE_RESET_DELAY);
> -		reset_control_deassert(mrst->phy);
> -		udelay(PCIE_RESET_DELAY);
> -	}
> +	ret = phy_reset(mp->phy);
> +	if (ret)
> +		return ret;
>  
>  	reset_control_assert(mrst->port);
>  	reset_control_assert(mrst->apb);
> @@ -286,12 +242,6 @@ static int meson_pcie_probe_clocks(struct meson_pcie *mp)
>  	if (IS_ERR(res->port_clk))
>  		return PTR_ERR(res->port_clk);
>  
> -	if (!mp->param->has_shared_phy) {
> -		res->mipi_gate = meson_pcie_probe_clock(dev, "mipi", 0);
> -		if (IS_ERR(res->mipi_gate))
> -			return PTR_ERR(res->mipi_gate);
> -	}
> -
>  	res->general_clk = meson_pcie_probe_clock(dev, "general", 0);
>  	if (IS_ERR(res->general_clk))
>  		return PTR_ERR(res->general_clk);
> @@ -562,7 +512,6 @@ static const struct dw_pcie_ops dw_pcie_ops = {
>  
>  static int meson_pcie_probe(struct platform_device *pdev)
>  {
> -	const struct meson_pcie_param *match_data;
>  	struct device *dev = &pdev->dev;
>  	struct dw_pcie *pci;
>  	struct meson_pcie *mp;
> @@ -576,17 +525,10 @@ static int meson_pcie_probe(struct platform_device *pdev)
>  	pci->dev = dev;
>  	pci->ops = &dw_pcie_ops;
>  
> -	match_data = of_device_get_match_data(dev);
> -	if (!match_data) {
> -		dev_err(dev, "failed to get match data\n");
> -		return -ENODEV;
> -	}
> -	mp->param = match_data;
> -
> -	if (mp->param->has_shared_phy) {
> -		mp->phy = devm_phy_get(dev, "pcie");
> -		if (IS_ERR(mp->phy))
> -			return PTR_ERR(mp->phy);
> +	mp->phy = devm_phy_get(dev, "pcie");
> +	if (IS_ERR(mp->phy)) {
> +		dev_err(dev, "get phy failed, %ld\n", PTR_ERR(mp->phy));
> +		return PTR_ERR(mp->phy);
>  	}
>  
>  	mp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
> @@ -636,30 +578,16 @@ static int meson_pcie_probe(struct platform_device *pdev)
>  	return 0;
>  
>  err_phy:
> -	if (mp->param->has_shared_phy) {
> -		phy_power_off(mp->phy);
> -		phy_exit(mp->phy);
> -	}
> -
> +	meson_pcie_power_off(mp);
>  	return ret;
>  }
>  
> -static struct meson_pcie_param meson_pcie_axg_param = {
> -	.has_shared_phy = false,
> -};
> -
> -static struct meson_pcie_param meson_pcie_g12a_param = {
> -	.has_shared_phy = true,
> -};
> -
>  static const struct of_device_id meson_pcie_of_match[] = {
>  	{
>  		.compatible = "amlogic,axg-pcie",
> -		.data = &meson_pcie_axg_param,
>  	},
>  	{
>  		.compatible = "amlogic,g12a-pcie",
> -		.data = &meson_pcie_g12a_param,
>  	},
>  	{},
>  };


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

* Re: [PATCH v5 4/7] arm64: dts: meson-axg: Add PCIE PHY nodes
  2020-01-16 11:18 ` [PATCH v5 4/7] arm64: dts: meson-axg: Add PCIE PHY nodes Remi Pommarel
@ 2020-01-23  9:56   ` Neil Armstrong
  0 siblings, 0 replies; 18+ messages in thread
From: Neil Armstrong @ 2020-01-23  9:56 UTC (permalink / raw)
  To: Remi Pommarel, Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Martin Blumenstingl,
	Rob Herring
  Cc: Jerome Brunet, linux-amlogic, linux-kernel, devicetree

On 16/01/2020 12:18, Remi Pommarel wrote:
> Enable both PCIE and shared MIPI/PCIE PHY nodes in order to make PCIE
> reliable on AXG SoC.
> 
> Signed-off-by: Remi Pommarel <repk@triplefau.lt>
> ---
>  arch/arm64/boot/dts/amlogic/meson-axg.dtsi | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
> index 04803c3bccfa..08a178aa0133 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
> @@ -12,6 +12,7 @@
>  #include <dt-bindings/interrupt-controller/arm-gic.h>
>  #include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
>  #include <dt-bindings/reset/amlogic,meson-axg-reset.h>
> +#include <dt-bindings/phy/phy.h>
>  
>  / {
>  	compatible = "amlogic,meson-axg";
> @@ -1104,6 +1105,12 @@ hiubus: bus@ff63c000 {
>  			#size-cells = <2>;
>  			ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x1c00>;
>  
> +			mipi_analog_phy: phy@0 {
> +				compatible = "amlogic,axg-mipi-pcie-analog-phy";
> +				reg = <0x0 0x0 0x0 0xc>;
> +				#phy-cells = <1>;
> +			};
> +
>  			sysctrl: system-controller@0 {
>  				compatible = "amlogic,meson-axg-hhi-sysctrl",
>  					     "simple-mfd", "syscon";
> @@ -1356,6 +1363,15 @@ tdmout_c: audio-controller@580 {
>  			};
>  		};
>  
> +		pcie_phy: bus@ff644000 {
> +			compatible = "amlogic,axg-pcie-phy";
> +			reg = <0x0 0xff644000 0x0 0x1c>;
> +			resets = <&reset RESET_PCIE_PHY>;
> +			phys = <&mipi_analog_phy PHY_TYPE_PCIE>;
> +			phy-names = "analog";
> +			#phy-cells = <0>;
> +		};
> +
>  		aobus: bus@ff800000 {
>  			compatible = "simple-bus";
>  			reg = <0x0 0xff800000 0x0 0x100000>;
> 

Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>

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

* Re: [PATCH v5 7/7] PCI: amlogic: Use AXG PCIE
  2020-01-16 20:13   ` Bjorn Helgaas
@ 2020-01-23 10:00     ` Neil Armstrong
  0 siblings, 0 replies; 18+ messages in thread
From: Neil Armstrong @ 2020-01-23 10:00 UTC (permalink / raw)
  To: Bjorn Helgaas, Remi Pommarel
  Cc: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Martin Blumenstingl, Rob Herring,
	Jerome Brunet, linux-amlogic, linux-kernel, devicetree,
	linux-pci

On 16/01/2020 21:13, Bjorn Helgaas wrote:
> [+cc linux-pci, series at https://lore.kernel.org/r/20200116111850.23690-1-repk@triplefau.lt]
> 
> On Thu, Jan 16, 2020 at 12:18:50PM +0100, Remi Pommarel wrote:
>> Now that PCIE PHY has been introduced for AXG, the whole has_shared_phy
>> logic can be mutualized between AXG and G12A platforms.
>>
>> This new PHY makes use of the optional shared MIPI/PCIE analog PHY
>> found on AXG platforms, which need to be used in order to have reliable
>> PCIE communications.
>>
>> Signed-off-by: Remi Pommarel <repk@triplefau.lt>
>> ---
>>  drivers/pci/controller/dwc/pci-meson.c | 116 +++++--------------------
>>  1 file changed, 22 insertions(+), 94 deletions(-)
>>
>> diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
>> index 3772b02a5c55..3715dceca1bf 100644
>> --- a/drivers/pci/controller/dwc/pci-meson.c
>> +++ b/drivers/pci/controller/dwc/pci-meson.c
>> @@ -66,7 +66,6 @@
>>  #define PORT_CLK_RATE			100000000UL
>>  #define MAX_PAYLOAD_SIZE		256
>>  #define MAX_READ_REQ_SIZE		256
>> -#define MESON_PCIE_PHY_POWERUP		0x1c
>>  #define PCIE_RESET_DELAY		500
>>  #define PCIE_SHARED_RESET		1
>>  #define PCIE_NORMAL_RESET		0
>> @@ -81,26 +80,19 @@ enum pcie_data_rate {
>>  struct meson_pcie_mem_res {
>>  	void __iomem *elbi_base;
>>  	void __iomem *cfg_base;
>> -	void __iomem *phy_base;
>>  };
>>  
>>  struct meson_pcie_clk_res {
>>  	struct clk *clk;
>> -	struct clk *mipi_gate;
>>  	struct clk *port_clk;
>>  	struct clk *general_clk;
>>  };
>>  
>>  struct meson_pcie_rc_reset {
>> -	struct reset_control *phy;
>>  	struct reset_control *port;
>>  	struct reset_control *apb;
>>  };
>>  
>> -struct meson_pcie_param {
>> -	bool has_shared_phy;
>> -};
>> -
>>  struct meson_pcie {
>>  	struct dw_pcie pci;
>>  	struct meson_pcie_mem_res mem_res;
>> @@ -108,7 +100,6 @@ struct meson_pcie {
>>  	struct meson_pcie_rc_reset mrst;
>>  	struct gpio_desc *reset_gpio;
>>  	struct phy *phy;
>> -	const struct meson_pcie_param *param;
>>  };
>>  
>>  static struct reset_control *meson_pcie_get_reset(struct meson_pcie *mp,
>> @@ -130,13 +121,6 @@ static int meson_pcie_get_resets(struct meson_pcie *mp)
>>  {
>>  	struct meson_pcie_rc_reset *mrst = &mp->mrst;
>>  
>> -	if (!mp->param->has_shared_phy) {
>> -		mrst->phy = meson_pcie_get_reset(mp, "phy", PCIE_SHARED_RESET);
>> -		if (IS_ERR(mrst->phy))
>> -			return PTR_ERR(mrst->phy);
>> -		reset_control_deassert(mrst->phy);
>> -	}
>> -
>>  	mrst->port = meson_pcie_get_reset(mp, "port", PCIE_NORMAL_RESET);
>>  	if (IS_ERR(mrst->port))
>>  		return PTR_ERR(mrst->port);
>> @@ -162,22 +146,6 @@ static void __iomem *meson_pcie_get_mem(struct platform_device *pdev,
>>  	return devm_ioremap_resource(dev, res);
>>  }
>>  
>> -static void __iomem *meson_pcie_get_mem_shared(struct platform_device *pdev,
>> -					       struct meson_pcie *mp,
>> -					       const char *id)
>> -{
>> -	struct device *dev = mp->pci.dev;
>> -	struct resource *res;
>> -
>> -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, id);
>> -	if (!res) {
>> -		dev_err(dev, "No REG resource %s\n", id);
>> -		return ERR_PTR(-ENXIO);
>> -	}
>> -
>> -	return devm_ioremap(dev, res->start, resource_size(res));
>> -}
>> -
>>  static int meson_pcie_get_mems(struct platform_device *pdev,
>>  			       struct meson_pcie *mp)
>>  {
>> @@ -189,14 +157,6 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
>>  	if (IS_ERR(mp->mem_res.cfg_base))
>>  		return PTR_ERR(mp->mem_res.cfg_base);
>>  
>> -	/* Meson AXG SoC has two PCI controllers use same phy register */
>> -	if (!mp->param->has_shared_phy) {
>> -		mp->mem_res.phy_base =
>> -			meson_pcie_get_mem_shared(pdev, mp, "phy");
>> -		if (IS_ERR(mp->mem_res.phy_base))
>> -			return PTR_ERR(mp->mem_res.phy_base);
>> -	}
>> -
>>  	return 0;
>>  }
>>  
>> @@ -204,37 +164,33 @@ static int meson_pcie_power_on(struct meson_pcie *mp)
>>  {
>>  	int ret = 0;
>>  
>> -	if (mp->param->has_shared_phy) {
>> -		ret = phy_init(mp->phy);
>> -		if (ret)
>> -			return ret;
>> +	ret = phy_init(mp->phy);
>> +	if (ret)
>> +		return ret;
>>  
>> -		ret = phy_power_on(mp->phy);
>> -		if (ret) {
>> -			phy_exit(mp->phy);
>> -			return ret;
>> -		}
>> -	} else
>> -		writel(MESON_PCIE_PHY_POWERUP, mp->mem_res.phy_base);
>> +	ret = phy_power_on(mp->phy);
>> +	if (ret) {
>> +		phy_exit(mp->phy);
>> +		return ret;
>> +	}
>>  
>>  	return 0;
>>  }
>>  
>> +static void meson_pcie_power_off(struct meson_pcie *mp)
>> +{
>> +	phy_power_off(mp->phy);
>> +	phy_exit(mp->phy);
>> +}
>> +
>>  static int meson_pcie_reset(struct meson_pcie *mp)
>>  {
>>  	struct meson_pcie_rc_reset *mrst = &mp->mrst;
>>  	int ret = 0;
>>  
>> -	if (mp->param->has_shared_phy) {
>> -		ret = phy_reset(mp->phy);
>> -		if (ret)
>> -			return ret;
>> -	} else {
>> -		reset_control_assert(mrst->phy);
>> -		udelay(PCIE_RESET_DELAY);
>> -		reset_control_deassert(mrst->phy);
>> -		udelay(PCIE_RESET_DELAY);
>> -	}
>> +	ret = phy_reset(mp->phy);
>> +	if (ret)
>> +		return ret;
>>  
>>  	reset_control_assert(mrst->port);
>>  	reset_control_assert(mrst->apb);
>> @@ -286,12 +242,6 @@ static int meson_pcie_probe_clocks(struct meson_pcie *mp)
>>  	if (IS_ERR(res->port_clk))
>>  		return PTR_ERR(res->port_clk);
>>  
>> -	if (!mp->param->has_shared_phy) {
>> -		res->mipi_gate = meson_pcie_probe_clock(dev, "mipi", 0);
>> -		if (IS_ERR(res->mipi_gate))
>> -			return PTR_ERR(res->mipi_gate);
>> -	}
>> -
>>  	res->general_clk = meson_pcie_probe_clock(dev, "general", 0);
>>  	if (IS_ERR(res->general_clk))
>>  		return PTR_ERR(res->general_clk);
>> @@ -562,7 +512,6 @@ static const struct dw_pcie_ops dw_pcie_ops = {
>>  
>>  static int meson_pcie_probe(struct platform_device *pdev)
>>  {
>> -	const struct meson_pcie_param *match_data;
>>  	struct device *dev = &pdev->dev;
>>  	struct dw_pcie *pci;
>>  	struct meson_pcie *mp;
>> @@ -576,17 +525,10 @@ static int meson_pcie_probe(struct platform_device *pdev)
>>  	pci->dev = dev;
>>  	pci->ops = &dw_pcie_ops;
>>  
>> -	match_data = of_device_get_match_data(dev);
>> -	if (!match_data) {
>> -		dev_err(dev, "failed to get match data\n");
>> -		return -ENODEV;
>> -	}
>> -	mp->param = match_data;
>> -
>> -	if (mp->param->has_shared_phy) {
>> -		mp->phy = devm_phy_get(dev, "pcie");
>> -		if (IS_ERR(mp->phy))
>> -			return PTR_ERR(mp->phy);
>> +	mp->phy = devm_phy_get(dev, "pcie");
>> +	if (IS_ERR(mp->phy)) {
>> +		dev_err(dev, "get phy failed, %ld\n", PTR_ERR(mp->phy));
>> +		return PTR_ERR(mp->phy);
>>  	}
>>  
>>  	mp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
>> @@ -636,30 +578,16 @@ static int meson_pcie_probe(struct platform_device *pdev)
>>  	return 0;
>>  
>>  err_phy:
>> -	if (mp->param->has_shared_phy) {
>> -		phy_power_off(mp->phy);
>> -		phy_exit(mp->phy);
>> -	}
>> -
>> +	meson_pcie_power_off(mp);
>>  	return ret;
>>  }
>>  
>> -static struct meson_pcie_param meson_pcie_axg_param = {
>> -	.has_shared_phy = false,
>> -};
>> -
>> -static struct meson_pcie_param meson_pcie_g12a_param = {
>> -	.has_shared_phy = true,
>> -};
>> -
>>  static const struct of_device_id meson_pcie_of_match[] = {
>>  	{
>>  		.compatible = "amlogic,axg-pcie",
>> -		.data = &meson_pcie_axg_param,
>>  	},
>>  	{
>>  		.compatible = "amlogic,g12a-pcie",
>> -		.data = &meson_pcie_g12a_param,
>>  	},
>>  	{},
>>  };
>> -- 
>> 2.24.1
>>

Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>

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

* Re: [PATCH v5 6/7] phy: amlogic: Add Amlogic AXG PCIE PHY Driver
  2020-01-23  9:44   ` Jerome Brunet
@ 2020-01-23 10:56     ` Remi Pommarel
  0 siblings, 0 replies; 18+ messages in thread
From: Remi Pommarel @ 2020-01-23 10:56 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Kishon Vijay Abraham I, Yue Wang, Kevin Hilman,
	Lorenzo Pieralisi, Bjorn Helgaas, Neil Armstrong,
	Martin Blumenstingl, Rob Herring, linux-amlogic, linux-kernel,
	devicetree

On Thu, Jan 23, 2020 at 10:44:43AM +0100, Jerome Brunet wrote:
> 
> On Thu 16 Jan 2020 at 12:18, Remi Pommarel <repk@triplefau.lt> wrote:
> 
> > This adds support for the PCI PHY found in the Amlogic AXG SoC Family.
> > This will allow to mutualize code in pci-meson.c between AXG and G12A
> > SoC.
> >
> > This PHY can chain and use an optional analog PHY, which is used on
> > AXG platform to have reliable PCIe communication.
> >
> > Signed-off-by: Remi Pommarel <repk@triplefau.lt>
> > ---
> >  drivers/phy/amlogic/Kconfig              |  11 ++
> >  drivers/phy/amlogic/Makefile             |   1 +
> >  drivers/phy/amlogic/phy-meson-axg-pcie.c | 192 +++++++++++++++++++++++
> >  3 files changed, 204 insertions(+)
> >  create mode 100644 drivers/phy/amlogic/phy-meson-axg-pcie.c
> >
> > diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
> > index 8c9cf2403591..71801e30d601 100644
> > --- a/drivers/phy/amlogic/Kconfig
> > +++ b/drivers/phy/amlogic/Kconfig
> > @@ -60,6 +60,17 @@ config PHY_MESON_G12A_USB3_PCIE
> >  	  in Meson G12A SoCs.
> >  	  If unsure, say N.
> >  
> > +config PHY_MESON_AXG_PCIE
> > +	tristate "Meson AXG PCIE PHY driver"
> > +	default ARCH_MESON
> > +	depends on OF && (ARCH_MESON || COMPILE_TEST)
> > +	select GENERIC_PHY
> > +	select REGMAP_MMIO
> > +	help
> > +	  Enable this to support the Meson MIPI + PCIE PHY found
> > +	  in Meson AXG SoCs.
> > +	  If unsure, say N.
> > +
> >  config PHY_MESON_AXG_MIPI_PCIE_ANALOG
> >  	tristate "Meson AXG MIPI + PCIE analog PHY driver"
> >  	default ARCH_MESON
> > diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile
> > index 0aecf92d796a..e2baa133f7af 100644
> > --- a/drivers/phy/amlogic/Makefile
> > +++ b/drivers/phy/amlogic/Makefile
> > @@ -4,4 +4,5 @@ obj-$(CONFIG_PHY_MESON_GXL_USB2)		+= phy-meson-gxl-usb2.o
> >  obj-$(CONFIG_PHY_MESON_G12A_USB2)		+= phy-meson-g12a-usb2.o
> >  obj-$(CONFIG_PHY_MESON_GXL_USB3)		+= phy-meson-gxl-usb3.o
> >  obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE)		+= phy-meson-g12a-usb3-pcie.o
> > +obj-$(CONFIG_PHY_MESON_AXG_PCIE)		+= phy-meson-axg-pcie.o
> >  obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG)	+= phy-meson-axg-mipi-pcie-analog.o
> > diff --git a/drivers/phy/amlogic/phy-meson-axg-pcie.c b/drivers/phy/amlogic/phy-meson-axg-pcie.c
> > new file mode 100644
> > index 000000000000..0c5d0732cd1c
> > --- /dev/null
> > +++ b/drivers/phy/amlogic/phy-meson-axg-pcie.c
> > @@ -0,0 +1,192 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Amlogic AXG PCIE PHY driver
> > + *
> > + * Copyright (C) 2020 Remi Pommarel <repk@triplefau.lt>
> > + */
> > +#include <linux/module.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/regmap.h>
> > +#include <linux/reset.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/bitfield.h>
> > +#include <dt-bindings/phy/phy.h>
> > +
> > +#define MESON_PCIE_REG0 0x00
> > +#define		MESON_PCIE_COMMON_CLK	BIT(4)
> > +#define		MESON_PCIE_PORT_SEL	GENMASK(3, 2)
> > +#define		MESON_PCIE_CLK		BIT(1)
> > +#define		MESON_PCIE_POWERDOWN	BIT(0)
> > +
> > +#define MESON_PCIE_TWO_X1		FIELD_PREP(MESON_PCIE_PORT_SEL, 0x3)
> > +#define MESON_PCIE_COMMON_REF_CLK	FIELD_PREP(MESON_PCIE_COMMON_CLK, 0x1)
> > +#define MESON_PCIE_PHY_INIT		(MESON_PCIE_TWO_X1 |		\
> > +					 MESON_PCIE_COMMON_REF_CLK)
> > +#define MESON_PCIE_RESET_DELAY		500
> > +
> > +struct phy_axg_pcie_priv {
> > +	struct phy *phy;
> > +	struct phy *analog;
> > +	struct regmap *regmap;
> > +	struct reset_control *reset;
> > +};
> > +
> > +static const struct regmap_config phy_axg_pcie_regmap_conf = {
> > +	.reg_bits = 8,
> > +	.val_bits = 32,
> > +	.reg_stride = 4,
> > +	.max_register = MESON_PCIE_REG0,
> > +};
> > +
> > +static int phy_axg_pcie_power_on(struct phy *phy)
> > +{
> > +	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
> > +	int ret;
> > +
> > +	ret = phy_power_on(priv->analog);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	regmap_update_bits(priv->regmap, MESON_PCIE_REG0,
> > +			   MESON_PCIE_POWERDOWN, 0);
> > +	return 0;
> > +}
> > +
> > +static int phy_axg_pcie_power_off(struct phy *phy)
> > +{
> > +	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
> > +	int ret;
> > +
> > +	ret = phy_power_off(priv->analog);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	regmap_update_bits(priv->regmap, MESON_PCIE_REG0,
> > +			   MESON_PCIE_POWERDOWN, 1);
> > +	return 0;
> > +}
> > +
> > +static int phy_axg_pcie_init(struct phy *phy)
> > +{
> > +	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
> > +	int ret;
> > +
> > +	ret = phy_init(priv->analog);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	regmap_write(priv->regmap, MESON_PCIE_REG0, MESON_PCIE_PHY_INIT);
> > +	return reset_control_reset(priv->reset);
> > +}
> > +
> > +static int phy_axg_pcie_exit(struct phy *phy)
> > +{
> > +	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
> > +	int ret;
> > +
> > +	ret = phy_exit(priv->analog);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	return reset_control_reset(priv->reset);
> > +}
> > +
> > +static int phy_axg_pcie_reset(struct phy *phy)
> > +{
> > +	struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
> > +	int ret = 0;
> > +
> > +	ret = phy_reset(priv->analog);
> > +	if (ret != 0)
> > +		goto out;
> > +
> > +	ret = reset_control_assert(priv->reset);
> > +	if (ret != 0)
> > +		goto out;
> > +	udelay(MESON_PCIE_RESET_DELAY);
> > +
> > +	ret = reset_control_deassert(priv->reset);
> > +	if (ret != 0)
> > +		goto out;
> > +	udelay(MESON_PCIE_RESET_DELAY);
> > +
> > +out:
> > +	return ret;
> > +}
> > +
> > +static const struct phy_ops phy_axg_pcie_ops = {
> > +	.init = phy_axg_pcie_init,
> > +	.exit = phy_axg_pcie_exit,
> > +	.power_on = phy_axg_pcie_power_on,
> > +	.power_off = phy_axg_pcie_power_off,
> > +	.reset = phy_axg_pcie_reset,
> > +	.owner = THIS_MODULE,
> > +};
> > +
> > +static int phy_axg_pcie_probe(struct platform_device *pdev)
> > +{
> > +	struct phy_provider *pphy;
> > +	struct device *dev = &pdev->dev;
> > +	struct phy_axg_pcie_priv *priv;
> > +	struct device_node *np = dev->of_node;
> > +	struct resource *res;
> > +	void __iomem *base;
> > +	int ret;
> > +
> > +	priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	priv->phy = devm_phy_create(dev, np, &phy_axg_pcie_ops);
> > +	if (IS_ERR(priv->phy)) {
> > +		ret = PTR_ERR(priv->phy);
> > +		if (ret != -EPROBE_DEFER)
> > +			dev_err(dev, "failed to create PHY\n");
> > +		return ret;
> > +	}
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	base = devm_ioremap_resource(dev, res);
> > +	if (IS_ERR(base))
> > +		return PTR_ERR(base);
> > +
> > +	priv->regmap = devm_regmap_init_mmio(dev, base,
> > +					     &phy_axg_pcie_regmap_conf);
> > +	if (IS_ERR(priv->regmap))
> > +		return PTR_ERR(priv->regmap);
> > +
> > +	priv->reset = devm_reset_control_array_get(dev, false, false);
> > +	if (IS_ERR(priv->reset))
> > +		return PTR_ERR(priv->reset);
> > +
> > +	priv->analog = devm_phy_optional_get(dev, "analog");
> > +	if (IS_ERR(priv->analog))
> > +		return PTR_ERR(priv->analog);
> 
> Isn't required for on the axg platform for the pcie to work reliably ?
> Does this driver support another SoC ?
> 

That is just me being overly cautious here. It is indeed required on AXG
SoC to have pcie working reliably.

Will change that in next patchset version.

Thanks.

> > +
> > +	phy_set_drvdata(priv->phy, priv);
> > +	dev_set_drvdata(dev, priv);
> > +	pphy = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> > +
> > +	return PTR_ERR_OR_ZERO(pphy);
> > +}
> > +
> > +static const struct of_device_id phy_axg_pcie_of_match[] = {
> > +	{
> > +		.compatible = "amlogic,axg-pcie-phy",
> > +	},
> > +	{ },
> > +};
> > +MODULE_DEVICE_TABLE(of, phy_axg_pcie_of_match);
> > +
> > +static struct platform_driver phy_axg_pcie_driver = {
> > +	.probe = phy_axg_pcie_probe,
> > +	.driver = {
> > +		.name = "phy-axg-pcie",
> > +		.of_match_table = phy_axg_pcie_of_match,
> > +	},
> > +};
> > +module_platform_driver(phy_axg_pcie_driver);
> > +
> > +MODULE_AUTHOR("Remi Pommarel <repk@triplefau.lt>");
> > +MODULE_DESCRIPTION("Amlogic AXG PCIE PHY driver");
> > +MODULE_LICENSE("GPL v2");
> 

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

end of thread, other threads:[~2020-01-23 10:47 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-16 11:18 [PATCH v5 0/7] PCI: amlogic: Make PCIe working reliably on AXG platforms Remi Pommarel
2020-01-16 11:18 ` [PATCH v5 1/7] dt-bindings: Add AXG PCIE PHY bindings Remi Pommarel
2020-01-17 16:03   ` Rob Herring
2020-01-16 11:18 ` [PATCH v5 2/7] dt-bindings: Add AXG shared MIPI/PCIE analog " Remi Pommarel
2020-01-17 16:04   ` Rob Herring
2020-01-16 11:18 ` [PATCH v5 3/7] dt-bindings: PCI: meson: Update PCIE bindings documentation Remi Pommarel
2020-01-17 16:05   ` Rob Herring
2020-01-16 11:18 ` [PATCH v5 4/7] arm64: dts: meson-axg: Add PCIE PHY nodes Remi Pommarel
2020-01-23  9:56   ` Neil Armstrong
2020-01-16 11:18 ` [PATCH v5 5/7] phy: amlogic: Add Amlogic AXG MIPI/PCIE analog PHY Driver Remi Pommarel
2020-01-23  9:37   ` Jerome Brunet
2020-01-16 11:18 ` [PATCH v5 6/7] phy: amlogic: Add Amlogic AXG PCIE " Remi Pommarel
2020-01-23  9:44   ` Jerome Brunet
2020-01-23 10:56     ` Remi Pommarel
2020-01-16 11:18 ` [PATCH v5 7/7] PCI: amlogic: Use AXG PCIE Remi Pommarel
2020-01-16 20:13   ` Bjorn Helgaas
2020-01-23 10:00     ` Neil Armstrong
2020-01-23  9:52   ` Jerome Brunet

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