From: Frank Wunderlich <[email protected]>
This series adds Rockchip PCIe V3 support found on rk3568 SOC.
It is based on "Enable rk356x PCIe controller" series of Peter Geis
v8: https://patchwork.kernel.org/project/linux-rockchip/list/?series=634925
Compared to PCIeV2 which uses the Naneng combphy, pciev3
uses a dedicated pci-phy.
This Version is still an RFC/RFT because i cannot only test PCIe-slot on R2Pro
as the other is a M.2 Key-E where i don't have any Hardware.
last 3 Patches show a replacement for bifurcation setting to make it more
useful for vendor-indepent lane-mapping.
Frank Wunderlich (11):
dt-bindings: phy: rockchip: add PCIe v3 phy
dt-bindings: soc: grf: add pcie30-{phy,pipe}-grf
dt-bindings: phy: rockchip: add PCIe v3 constants
phy: rockchip: Support PCIe v3
dt-bindings: pci: add bifurcation option to Rockchip DesignWare
binding
PCI: rockchip-dwc: add PCIe bifurcation
arm64: dts: rockchip: rk3568: Add PCIe v3 nodes
arm64: dts: rockchip: Add PCIe v3 nodes to BPI-R2-Pro
dt-bindings: pci: add lane-map to rockchip PCIe binding
PCI: rockchip: add a lane-map to rockchip pcie driver
arm64: dts: rockchip: add basic lane-map and drop bifurcation from
r2pro
.../bindings/pci/rockchip-dw-pcie.yaml | 3 +
.../bindings/phy/rockchip,pcie3-phy.yaml | 84 ++++++
.../devicetree/bindings/soc/rockchip/grf.yaml | 3 +
.../boot/dts/rockchip/rk3568-bpi-r2-pro.dts | 79 +++++
arch/arm64/boot/dts/rockchip/rk3568.dtsi | 122 ++++++++
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 22 ++
drivers/phy/rockchip/Kconfig | 9 +
drivers/phy/rockchip/Makefile | 1 +
.../phy/rockchip/phy-rockchip-snps-pcie3.c | 278 ++++++++++++++++++
include/dt-bindings/phy/phy-rockchip-pcie3.h | 21 ++
include/linux/phy/pcie.h | 12 +
11 files changed, 634 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
create mode 100644 drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
create mode 100644 include/dt-bindings/phy/phy-rockchip-pcie3.h
create mode 100644 include/linux/phy/pcie.h
--
2.25.1
On Tue, Apr 26, 2022 at 03:21:28PM +0200, Frank Wunderlich wrote:
> From: Frank Wunderlich <[email protected]>
>
> This series adds Rockchip PCIe V3 support found on rk3568 SOC.
>
> It is based on "Enable rk356x PCIe controller" series of Peter Geis
> v8: https://patchwork.kernel.org/project/linux-rockchip/list/?series=634925
>
> Compared to PCIeV2 which uses the Naneng combphy, pciev3
> uses a dedicated pci-phy.
>
> This Version is still an RFC/RFT because i cannot only test PCIe-slot on R2Pro
> as the other is a M.2 Key-E where i don't have any Hardware.
>
> last 3 Patches show a replacement for bifurcation setting to make it more
> useful for vendor-indepent lane-mapping.
>
> Frank Wunderlich (11):
> dt-bindings: phy: rockchip: add PCIe v3 phy
> dt-bindings: soc: grf: add pcie30-{phy,pipe}-grf
> dt-bindings: phy: rockchip: add PCIe v3 constants
> phy: rockchip: Support PCIe v3
> dt-bindings: pci: add bifurcation option to Rockchip DesignWare
> binding
> PCI: rockchip-dwc: add PCIe bifurcation
> arm64: dts: rockchip: rk3568: Add PCIe v3 nodes
> arm64: dts: rockchip: Add PCIe v3 nodes to BPI-R2-Pro
> dt-bindings: pci: add lane-map to rockchip PCIe binding
> PCI: rockchip: add a lane-map to rockchip pcie driver
> arm64: dts: rockchip: add basic lane-map and drop bifurcation from
> r2pro
Don't just make up new prefixes; copy what's been done in the past.
PCI: rockchip-dwc: add PCIe bifurcation
PCI: rockchip: add a lane-map to rockchip pcie driver
I think we decided [1] to use "rockchip-dwc" for this driver to
distinguish it from the pcie-rockchip-host.c driver.
So both of these should use "PCI: rockchip-dwc:" as the prefix.
At least for the drivers/pci/ patches, capitalize the first word of
the subject, i.e., "Add PCIe bifurcation" and "Add lane-map ..." I
don't know the dt-bindings convention (I would use "git log --oneline"
to find out).
s/pcie/PCIe/ in subjects, commit logs, comments, etc.
Wrap commit logs to fill 75 columns and add blank lines between
paragraphs. Readers should not need to wonder "oh, the previous line
was shorter than usual; is this one a new paragraph?"
[1] https://lore.kernel.org/r/20210624180723.GA3543267@bjorn-Precision-5520
> .../bindings/pci/rockchip-dw-pcie.yaml | 3 +
> .../bindings/phy/rockchip,pcie3-phy.yaml | 84 ++++++
> .../devicetree/bindings/soc/rockchip/grf.yaml | 3 +
> .../boot/dts/rockchip/rk3568-bpi-r2-pro.dts | 79 +++++
> arch/arm64/boot/dts/rockchip/rk3568.dtsi | 122 ++++++++
> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 22 ++
> drivers/phy/rockchip/Kconfig | 9 +
> drivers/phy/rockchip/Makefile | 1 +
> .../phy/rockchip/phy-rockchip-snps-pcie3.c | 278 ++++++++++++++++++
> include/dt-bindings/phy/phy-rockchip-pcie3.h | 21 ++
> include/linux/phy/pcie.h | 12 +
> 11 files changed, 634 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
> create mode 100644 drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
> create mode 100644 include/dt-bindings/phy/phy-rockchip-pcie3.h
> create mode 100644 include/linux/phy/pcie.h
>
> --
> 2.25.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Frank Wunderlich <[email protected]>
Add a new binding file for Rockchip PCIe v3 phy driver.
Signed-off-by: Frank Wunderlich <[email protected]>
---
v2:
dt-bindings: rename yaml for PCIe v3
rockchip-pcie3-phy.yaml => rockchip,pcie3-phy.yaml
changes in pcie3 phy yaml
- change clock names to ordered const list
- extend pcie30-phymode description
- add phy-cells to required properties
- drop unevaluatedProperties
- example with 1 clock each line
- use default property instead of text describing it
- update license
---
.../bindings/phy/rockchip,pcie3-phy.yaml | 84 +++++++++++++++++++
1 file changed, 84 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
diff --git a/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
new file mode 100644
index 000000000000..3592888b5ee2
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/rockchip,pcie3-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip PCIe v3 phy
+
+maintainers:
+ - Heiko Stuebner <[email protected]>
+
+properties:
+ compatible:
+ enum:
+ - rockchip,rk3568-pcie3-phy
+ - rockchip,rk3588-pcie3-phy
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ minItems: 1
+ maxItems: 3
+
+ clock-names:
+ items:
+ - const: "refclk_m"
+ - const: "refclk_n"
+ - const: "pclk"
+
+ minItems: 1
+
+ "#phy-cells":
+ const: 0
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ const: phy
+
+ rockchip,phy-grf:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to the syscon managing the phy "general register files"
+
+ rockchip,pipe-grf:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to the syscon managing the pipe "general register files"
+
+ rockchip,pcie30-phymode:
+ $ref: '/schemas/types.yaml#/definitions/uint32'
+ description: |
+ set the phy-mode for enabling bifurcation
+ bit0: bifurcation for port 0
+ bit1: bifurcation for port 1
+ bit2: aggregation
+ constants are defined in the dt-bindings/phy/phy-rockchip-pcie3.h
+ minimum: 0x0
+ maximum: 0x4
+ default: 0x4
+
+required:
+ - compatible
+ - reg
+ - rockchip,phy-grf
+ - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/rk3568-cru.h>
+ pcie30phy: phy@fe8c0000 {
+ compatible = "rockchip,rk3568-pcie3-phy";
+ reg = <0x0 0xfe8c0000 0x0 0x20000>;
+ #phy-cells = <0>;
+ clocks = <&pmucru CLK_PCIE30PHY_REF_M>,
+ <&pmucru CLK_PCIE30PHY_REF_N>,
+ <&cru PCLK_PCIE30PHY>;
+ clock-names = "refclk_m", "refclk_n", "pclk";
+ resets = <&cru SRST_PCIE30PHY>;
+ reset-names = "phy";
+ rockchip,phy-grf = <&pcie30_phy_grf>;
+ };
--
2.25.1
From: Frank Wunderlich <[email protected]>
Add a basic lane-map to define which PCIe lanes should be
used with this controller.
Rockchip driver uses this for bifurcation (true/false) based
on lanes should be splitted across controllers or not.
On rk3568 there are 2 PCIe Controllers which share PCIe lanes.
pcie3x1: pcie@fe270000 //lane1 when using 1+1
pcie3x2: pcie@fe280000 //lane0 when using 1+1
This ends up in one Controller (pcie3x1) uses lane-map = <0 1>; and
the other lane-map = <1 0>; (pcie3x2)
This means there are 2 lanes (count of numbers), one (by position)
is mapped to the first controller, the other one is used on the other
controller.
In this driver the lane-map is simply converted to the bifurcation
bool instead of direct mapping a specific lane to a controller.
Signed-off-by: Frank Wunderlich <[email protected]>
---
v2:
- new patch
---
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 79e909df241c..21cb697a5be1 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -60,6 +60,7 @@ struct rockchip_pcie {
struct regulator *vpcie3v3;
struct irq_domain *irq_domain;
bool bifurcation;
+ u32 lane_map[2];
};
static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip,
@@ -293,8 +294,10 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rockchip_pcie *rockchip;
+ unsigned int lanecnt = 0;
struct pcie_port *pp;
int ret;
+ int len;
rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL);
if (!rockchip)
@@ -327,8 +330,16 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
}
}
- if (device_property_read_bool(dev, "bifurcation"))
- rockchip->bifurcation = true;
+ len = of_property_read_variable_u32_array(dev->of_node, "lane-map", rockchip->lane_map,
+ 2, ARRAY_SIZE(rockchip->lane_map));
+
+ for (int i = 0; i < len; i++)
+ if (rockchip->lane_map[i])
+ lanecnt++;
+
+ rockchip->bifurcation = ((lanecnt > 0) && (lanecnt != len));
+
+ dev_info(dev, "bifurcation: %s\n", rockchip->bifurcation ? "true" : "false");
ret = rockchip_pcie_phy_init(rockchip);
if (ret)
--
2.25.1
From: Frank Wunderlich <[email protected]>
Create new property for (rockchip) PCIe controller binding to
define lane mapping.
Rockchip driver uses this for bifurcation (true/false) based
on lanes should be splitted across controllers or not.
On rk3568 there are 2 PCIe Controllers which share 2 PCIe lanes.
pcie3x1: pcie@fe270000 //lane1 when using 1+1
pcie3x2: pcie@fe280000 //lane0 when using 1+1
This ends up in one Controller (pcie3x1) uses lane-map = <0 1>; and
the other lane-map = <1 0>; (pcie3x2)
This means there are 2 lanes (count of numbers), one (by position)
is mapped to the first controller, the other one is used on the other
controller.
In rockchip PCIe driver the lane-map is simply converted to the
bifurcation bool instead of direct mapping a specific lane to a
controller.
There is not yet any slot mapping below one controller.
But for binding this may be possible like:
lane-map = <1 2 3 3 4 4 4 4>;
| | | ...
lane0 | |
lane1 |
lane2
on a 8-lane phy.
This can map lane0 to port1 (number used at this position),
lane1 to port2, lanes 2+3 to port 3 and lanes 4,5,6,7 to port 4.
Signed-off-by: Frank Wunderlich <[email protected]>
---
v2:
- new patch
---
Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml
index a992970e8b85..998b20b3a9dc 100644
--- a/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml
@@ -52,6 +52,8 @@ properties:
- const: pclk
- const: aux
+ lane-map: true
+
msi-map: true
num-lanes: true
@@ -74,8 +76,6 @@ properties:
reset-names:
const: pipe
- bifurcation: true
-
vpcie3v3-supply: true
required:
@@ -115,6 +115,7 @@ examples:
"aclk_dbi", "pclk",
"aux";
device_type = "pci";
+ lane-map = <0 1>;
linux,pci-domain = <2>;
max-link-speed = <2>;
msi-map = <0x2000 &its 0x2000 0x1000>;
--
2.25.1
From: Frank Wunderlich <[email protected]>
PCIe Lanes can be split to 2 slots with bifurcation.
Add support for this in existing PCIe driver that can be enabled
by new "bifurcation" devicetree property.
Co-developed-by: Peter Geis <[email protected]>
Signed-off-by: Frank Wunderlich <[email protected]>
---
changes in v2:
- change rockchip,bifurcation to vendor unspecific bifurcation
---
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index b00832d653ea..79e909df241c 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
+#include <linux/phy/pcie.h>
#include "pcie-designware.h"
@@ -58,6 +59,7 @@ struct rockchip_pcie {
struct gpio_desc *rst_gpio;
struct regulator *vpcie3v3;
struct irq_domain *irq_domain;
+ bool bifurcation;
};
static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip,
@@ -259,6 +261,12 @@ static int rockchip_pcie_phy_init(struct rockchip_pcie *rockchip)
return dev_err_probe(dev, PTR_ERR(rockchip->phy),
"missing PHY\n");
+ if (rockchip->bifurcation) {
+ ret = phy_set_mode_ext(rockchip->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_BIFURCATION);
+ if (ret)
+ return ret;
+ }
+
ret = phy_init(rockchip->phy);
if (ret < 0)
return ret;
@@ -319,6 +327,9 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
}
}
+ if (device_property_read_bool(dev, "bifurcation"))
+ rockchip->bifurcation = true;
+
ret = rockchip_pcie_phy_init(rockchip);
if (ret)
goto disable_regulator;
--
2.25.1
From: Frank Wunderlich <[email protected]>
Add constants that can be used in devicetree and driver for
PCIe v3 phy.
Signed-off-by: Frank Wunderlich <[email protected]>
---
v2:
- new patch because splitting out this file
- rename file from snps to rockchip
---
include/dt-bindings/phy/phy-rockchip-pcie3.h | 21 ++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 include/dt-bindings/phy/phy-rockchip-pcie3.h
diff --git a/include/dt-bindings/phy/phy-rockchip-pcie3.h b/include/dt-bindings/phy/phy-rockchip-pcie3.h
new file mode 100644
index 000000000000..93e57edd337d
--- /dev/null
+++ b/include/dt-bindings/phy/phy-rockchip-pcie3.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef _DT_BINDINGS_PHY_ROCKCHIP_PCIE3
+#define _DT_BINDINGS_PHY_ROCKCHIP_PCIE3
+
+/*
+ * pcie30_phy_mode[2:0]
+ * bit2: aggregation
+ * bit1: bifurcation for port 1
+ * bit0: bifurcation for port 0
+ */
+#define PHY_MODE_PCIE_AGGREGATION 4 /* PCIe3x4 */
+#define PHY_MODE_PCIE_NANBNB 0 /* P1:PCIe3x2 + P0:PCIe3x2 */
+#define PHY_MODE_PCIE_NANBBI 1 /* P1:PCIe3x2 + P0:PCIe3x1*2 */
+#define PHY_MODE_PCIE_NABINB 2 /* P1:PCIe3x1*2 + P0:PCIe3x2 */
+#define PHY_MODE_PCIE_NABIBI 3 /* P1:PCIe3x1*2 + P0:PCIe3x1*2 */
+
+#endif /* _DT_BINDINGS_PHY_ROCKCHIP_PCIE3 */
--
2.25.1
From: Frank Wunderlich <[email protected]>
RK3568 supports PCIe v3 using not Combphy like PCIe v2 on rk3566.
It use a dedicated PCIe-phy. Add support for this.
Signed-off-by: Frank Wunderlich <[email protected]>
---
changes in v2:
- move dt-bindings header into separate patch
- use BIT-macro
- make constants better readable
- use dev_err instead of pr_*
- change dt-binding include due to renaming (phy-snps-pcie3.h => phy-rockchip-pcie3.h)
- use exclusive variant of devm_reset_control_get{,_exclusive}
- fix semicolon.cocci warnings reported by kernel test robot <[email protected]>
---
driver was taken from linux 5.10 based on in
https://github.com/JeffyCN/mirrors
which now has disappeared
---
drivers/phy/rockchip/Kconfig | 9 +
drivers/phy/rockchip/Makefile | 1 +
.../phy/rockchip/phy-rockchip-snps-pcie3.c | 278 ++++++++++++++++++
include/linux/phy/pcie.h | 12 +
4 files changed, 300 insertions(+)
create mode 100644 drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
create mode 100644 include/linux/phy/pcie.h
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 9022e395c056..94360fc96a6f 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -83,6 +83,15 @@ config PHY_ROCKCHIP_PCIE
help
Enable this to support the Rockchip PCIe PHY.
+config PHY_ROCKCHIP_SNPS_PCIE3
+ tristate "Rockchip Snps PCIe3 PHY Driver"
+ depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ select MFD_SYSCON
+ help
+ Enable this to support the Rockchip snps PCIe3 PHY.
+
config PHY_ROCKCHIP_TYPEC
tristate "Rockchip TYPEC PHY Driver"
depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
index a5041efb5b8f..7eab129230d1 100644
--- a/drivers/phy/rockchip/Makefile
+++ b/drivers/phy/rockchip/Makefile
@@ -8,5 +8,6 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o
obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
+obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o
obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
new file mode 100644
index 000000000000..e228a0f2cb72
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip PCIE3.0 phy driver
+ *
+ * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/pcie.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <dt-bindings/phy/phy-rockchip-pcie3.h>
+
+/* Register for RK3568 */
+#define GRF_PCIE30PHY_CON1 0x4
+#define GRF_PCIE30PHY_CON6 0x18
+#define GRF_PCIE30PHY_CON9 0x24
+#define GRF_PCIE30PHY_STATUS0 0x80
+#define SRAM_INIT_DONE(reg) (reg & BIT(14))
+
+/* Register for RK3588 */
+#define PHP_GRF_PCIESEL_CON 0x100
+#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0
+#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904
+#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04
+#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0))
+
+struct rockchip_p3phy_ops;
+
+struct rockchip_p3phy_priv {
+ const struct rockchip_p3phy_ops *ops;
+ void __iomem *mmio;
+ /* mode: RC, EP */
+ int mode;
+ /* pcie30_phymode: Aggregation, Bifurcation */
+ int pcie30_phymode;
+ struct regmap *phy_grf;
+ struct regmap *pipe_grf;
+ struct reset_control *p30phy;
+ struct phy *phy;
+ struct clk_bulk_data *clks;
+ int num_clks;
+ bool is_bifurcation;
+};
+
+struct rockchip_p3phy_ops {
+ int (*phy_init)(struct rockchip_p3phy_priv *priv);
+};
+
+static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
+
+ /* Actually We don't care EP/RC mode, but just record it */
+ switch (submode) {
+ case PHY_MODE_PCIE_RC:
+ priv->mode = PHY_MODE_PCIE_RC;
+ break;
+ case PHY_MODE_PCIE_EP:
+ priv->mode = PHY_MODE_PCIE_EP;
+ break;
+ case PHY_MODE_PCIE_BIFURCATION:
+ priv->is_bifurcation = true;
+ break;
+ default:
+ dev_err(&phy->dev, "%s, invalid mode\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv)
+{
+ int ret;
+ u32 reg;
+
+ /* Deassert PCIe PMA output clamp mode */
+ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9,
+ BIT(15) | BIT(31));
+ /* Set bifurcation if needed, and it doesn't care RC/EP */
+ if (priv->is_bifurcation) {
+ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
+ 0x1 | (0xf << 16));
+ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1,
+ BIT(15) | BIT(31));
+ }
+
+ reset_control_deassert(priv->p30phy);
+
+ ret = regmap_read_poll_timeout(priv->phy_grf,
+ GRF_PCIE30PHY_STATUS0,
+ reg, SRAM_INIT_DONE(reg),
+ 0, 500);
+ if (ret)
+ dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n",
+ __func__, reg);
+ return ret;
+}
+
+static const struct rockchip_p3phy_ops rk3568_ops = {
+ .phy_init = rockchip_p3phy_rk3568_init,
+};
+
+static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
+{
+ int ret;
+ u32 reg;
+
+ /* Deassert PCIe PMA output clamp mode */
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0,
+ BIT(8) | BIT(24));
+
+ reset_control_deassert(priv->p30phy);
+
+ ret = regmap_read_poll_timeout(priv->phy_grf,
+ RK3588_PCIE3PHY_GRF_PHY0_STATUS1,
+ reg, RK3588_SRAM_INIT_DONE(reg),
+ 0, 500);
+ ret |= regmap_read_poll_timeout(priv->phy_grf,
+ RK3588_PCIE3PHY_GRF_PHY1_STATUS1,
+ reg, RK3588_SRAM_INIT_DONE(reg),
+ 0, 500);
+ if (ret)
+ pr_err("%s: lock failed 0x%x, check input refclk and power supply\n",
+ __func__, reg);
+ return ret;
+}
+
+static const struct rockchip_p3phy_ops rk3588_ops = {
+ .phy_init = rockchip_p3phy_rk3588_init,
+};
+
+static int rochchip_p3phy_init(struct phy *phy)
+{
+ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
+ int ret;
+
+ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
+ if (ret) {
+ pr_err("failed to enable PCIe bulk clks %d\n", ret);
+ return ret;
+ }
+
+ reset_control_assert(priv->p30phy);
+ udelay(1);
+
+ if (priv->ops->phy_init) {
+ ret = priv->ops->phy_init(priv);
+ if (ret)
+ clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
+ }
+
+ return ret;
+}
+
+static int rochchip_p3phy_exit(struct phy *phy)
+{
+ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
+
+ clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
+ reset_control_assert(priv->p30phy);
+ return 0;
+}
+
+static const struct phy_ops rochchip_p3phy_ops = {
+ .init = rochchip_p3phy_init,
+ .exit = rochchip_p3phy_exit,
+ .set_mode = rockchip_p3phy_set_mode,
+ .owner = THIS_MODULE,
+};
+
+static int rockchip_p3phy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct device *dev = &pdev->dev;
+ struct rockchip_p3phy_priv *priv;
+ struct device_node *np = dev->of_node;
+ struct resource *res;
+ int ret;
+ u32 val, reg;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->mmio = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->mmio)) {
+ ret = PTR_ERR(priv->mmio);
+ return ret;
+ }
+
+ priv->ops = of_device_get_match_data(&pdev->dev);
+ if (!priv->ops) {
+ dev_err(&pdev->dev, "no of match data provided\n");
+ return -EINVAL;
+ }
+
+ priv->phy_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,phy-grf");
+ if (IS_ERR(priv->phy_grf)) {
+ dev_err(dev, "failed to find rockchip,phy_grf regmap\n");
+ return PTR_ERR(priv->phy_grf);
+ }
+
+ priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "rockchip,pipe-grf");
+ if (IS_ERR(priv->pipe_grf))
+ dev_info(dev, "failed to find rockchip,pipe_grf regmap\n");
+
+ ret = device_property_read_u32(dev, "rockchip,pcie30-phymode", &val);
+ if (!ret)
+ priv->pcie30_phymode = val;
+ else
+ priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION;
+
+ /* Select correct pcie30_phymode */
+ if (priv->pcie30_phymode > 4)
+ priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION;
+
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0,
+ (0x7<<16) | priv->pcie30_phymode);
+
+ /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
+ if (!IS_ERR(priv->pipe_grf)) {
+ reg = priv->pcie30_phymode & 3;
+ if (reg)
+ regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
+ (reg << 16) | reg);
+ }
+
+ priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops);
+ if (IS_ERR(priv->phy)) {
+ dev_err(dev, "failed to create combphy\n");
+ return PTR_ERR(priv->phy);
+ }
+
+ priv->p30phy = devm_reset_control_get_exclusive(dev, "phy");
+ if (IS_ERR(priv->p30phy)) {
+ dev_warn(dev, "no phy reset control specified\n");
+ priv->p30phy = NULL;
+ }
+
+ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
+ if (priv->num_clks < 1)
+ return -ENODEV;
+
+ dev_set_drvdata(dev, priv);
+ phy_set_drvdata(priv->phy, priv);
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id rockchip_p3phy_of_match[] = {
+ { .compatible = "rockchip,rk3568-pcie3-phy", .data = &rk3568_ops },
+ { .compatible = "rockchip,rk3588-pcie3-phy", .data = &rk3588_ops },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rockchip_p3phy_of_match);
+
+static struct platform_driver rockchip_p3phy_driver = {
+ .probe = rockchip_p3phy_probe,
+ .driver = {
+ .name = "rockchip-snps-pcie3-phy",
+ .of_match_table = rockchip_p3phy_of_match,
+ },
+};
+module_platform_driver(rockchip_p3phy_driver);
+MODULE_DESCRIPTION("Rockchip Synopsys PCIe 3.0 PHY driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/phy/pcie.h b/include/linux/phy/pcie.h
new file mode 100644
index 000000000000..93c997f520fe
--- /dev/null
+++ b/include/linux/phy/pcie.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ */
+#ifndef __PHY_PCIE_H
+#define __PHY_PCIE_H
+
+#define PHY_MODE_PCIE_RC 20
+#define PHY_MODE_PCIE_EP 21
+#define PHY_MODE_PCIE_BIFURCATION 22
+
+#endif
--
2.25.1
From: Frank Wunderlich <[email protected]>
Add Nodes to Bananapi-R2-Pro board to support PCIe v3 and
set PCIe related regulators to always on.
Signed-off-by: Frank Wunderlich <[email protected]>
---
changes in v2:
- underscores in nodenames
- rockchip,bifurcation to vendor unspecific bifurcation
- fix trailing space
---
.../boot/dts/rockchip/rk3568-bpi-r2-pro.dts | 79 +++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
index 2700fb18a3bc..86506d7896c6 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
@@ -74,6 +74,67 @@ vcc5v0_sys: vcc5v0-sys {
vin-supply = <&dc_12v>;
};
+ pcie30_avdd0v9: pcie30-avdd0v9 {
+ compatible = "regulator-fixed";
+ regulator-name = "pcie30_avdd0v9";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ pcie30_avdd1v8: pcie30-avdd1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "pcie30_avdd1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ /* pi6c pcie clock generator feeds both ports */
+ vcc3v3_pi6c_05: vcc3v3-pi6c-05-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pcie";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ enable-active-high;
+ gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <20000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ /* actually fed by vcc3v3_sys, dependent on pi6c clock generator */
+ vcc3v3_minipcie: vcc3v3-minipcie-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_minipcie";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ enable-active-high;
+ gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc3v3_pi6c_05>;
+ };
+
+ /* actually fed by vcc3v3_sys, dependent on pi6c clock generator */
+ vcc3v3_ngff: vcc3v3-ngff-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_ngff";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ enable-active-high;
+ gpio = <&gpio4 RK_PC1 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc3v3_pi6c_05>;
+ };
+
vbus: vbus {
compatible = "regulator-fixed";
regulator-name = "vbus";
@@ -411,6 +472,24 @@ rgmii_phy1: ethernet-phy@0 {
};
};
+&pcie30phy {
+ status = "okay";
+};
+
+&pcie3x1 {
+ bifurcation;
+ reset-gpios = <&gpio3 RK_PA1 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_ngff>;
+ status = "okay";
+};
+
+&pcie3x2 {
+ bifurcation;
+ reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_minipcie>;
+ status = "okay";
+};
+
&pinctrl {
leds {
blue_led_pin: blue-led-pin {
--
2.25.1
On 26/04/2022 15:21, Frank Wunderlich wrote:
> From: Frank Wunderlich <[email protected]>
>
> Add constants that can be used in devicetree and driver for
> PCIe v3 phy.
>
> Signed-off-by: Frank Wunderlich <[email protected]>
> ---
> v2:
> - new patch because splitting out this file
> - rename file from snps to rockchip
> ---
> include/dt-bindings/phy/phy-rockchip-pcie3.h | 21 ++++++++++++++++++++
Naming - vendor,device.
> 1 file changed, 21 insertions(+)
> create mode 100644 include/dt-bindings/phy/phy-rockchip-pcie3.h
>
> diff --git a/include/dt-bindings/phy/phy-rockchip-pcie3.h b/include/dt-bindings/phy/phy-rockchip-pcie3.h
> new file mode 100644
> index 000000000000..93e57edd337d
> --- /dev/null
> +++ b/include/dt-bindings/phy/phy-rockchip-pcie3.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
s/MIT/BSD-2-clause/ just like bindings because it is part of it. Unless
you took it from something and it is already licensed like that?
> +/*
> + * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
> + */
> +
> +#ifndef _DT_BINDINGS_PHY_ROCKCHIP_PCIE3
> +#define _DT_BINDINGS_PHY_ROCKCHIP_PCIE3
> +
> +/*
> + * pcie30_phy_mode[2:0]
> + * bit2: aggregation
> + * bit1: bifurcation for port 1
> + * bit0: bifurcation for port 0
> + */
> +#define PHY_MODE_PCIE_AGGREGATION 4 /* PCIe3x4 */
> +#define PHY_MODE_PCIE_NANBNB 0 /* P1:PCIe3x2 + P0:PCIe3x2 */
> +#define PHY_MODE_PCIE_NANBBI 1 /* P1:PCIe3x2 + P0:PCIe3x1*2 */
> +#define PHY_MODE_PCIE_NABINB 2 /* P1:PCIe3x1*2 + P0:PCIe3x2 */
> +#define PHY_MODE_PCIE_NABIBI 3 /* P1:PCIe3x1*2 + P0:PCIe3x1*2 */
> +
> +#endif /* _DT_BINDINGS_PHY_ROCKCHIP_PCIE3 */
Best regards,
Krzysztof
Hi Frank,
On Di, 2022-04-26 at 15:21 +0200, Frank Wunderlich wrote:
> + priv->p30phy = devm_reset_control_get_exclusive(dev, "phy");
> + if (IS_ERR(priv->p30phy)) {
> + dev_warn(dev, "no phy reset control specified\n");
> + priv->p30phy = NULL;
> + }
Please use devm_reset_control_get_optional_exclusive() [1] instead,
which already returns NULL if no reset control is specified, and return
on errors.
[1] https://docs.kernel.org/driver-api/reset.html#c.devm_reset_control_get_optional_exclusive
regards
Philipp
Hi
> Gesendet: Donnerstag, 28. April 2022 um 08:34 Uhr
> Von: "Krzysztof Kozlowski" <[email protected]>
>
> On 26/04/2022 15:21, Frank Wunderlich wrote:
> > From: Frank Wunderlich <[email protected]>
> >
> > include/dt-bindings/phy/phy-rockchip-pcie3.h | 21 ++++++++++++++++++++
>
> Naming - vendor,device.
ok, would rename to rockchip,pcie3-phy.h, is this ok?
> > --- /dev/null
> > +++ b/include/dt-bindings/phy/phy-rockchip-pcie3.h
> > @@ -0,0 +1,21 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>
> s/MIT/BSD-2-clause/ just like bindings because it is part of it. Unless
> you took it from something and it is already licensed like that?
took this with this license from downstream-repo, only removed snps from name and changed name of include guarding.
regards Frank
On 26/04/2022 15:21, Frank Wunderlich wrote:
> From: Frank Wunderlich <[email protected]>
>
> Add a new binding file for Rockchip PCIe v3 phy driver.
>
> Signed-off-by: Frank Wunderlich <[email protected]>
>
> ---
> v2:
> dt-bindings: rename yaml for PCIe v3
> rockchip-pcie3-phy.yaml => rockchip,pcie3-phy.yaml
>
> changes in pcie3 phy yaml
> - change clock names to ordered const list
> - extend pcie30-phymode description
> - add phy-cells to required properties
> - drop unevaluatedProperties
> - example with 1 clock each line
> - use default property instead of text describing it
> - update license
> ---
> .../bindings/phy/rockchip,pcie3-phy.yaml | 84 +++++++++++++++++++
> 1 file changed, 84 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
>
> diff --git a/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
> new file mode 100644
> index 000000000000..3592888b5ee2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
> @@ -0,0 +1,84 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/rockchip,pcie3-phy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Rockchip PCIe v3 phy
> +
> +maintainers:
> + - Heiko Stuebner <[email protected]>
> +
> +properties:
> + compatible:
> + enum:
> + - rockchip,rk3568-pcie3-phy
> + - rockchip,rk3588-pcie3-phy
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + minItems: 1
> + maxItems: 3
> +
> + clock-names:
> + items:
> + - const: "refclk_m"
> + - const: "refclk_n"
> + - const: "pclk"
Drop quotes.
> +
> + minItems: 1
I think we agreed to skip rk3588 or make the number of clocks strict?
> +
> + "#phy-cells":
> + const: 0
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + const: phy
> +
> + rockchip,phy-grf:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description: phandle to the syscon managing the phy "general register files"
> +
> + rockchip,pipe-grf:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description: phandle to the syscon managing the pipe "general register files"
> +
> + rockchip,pcie30-phymode:
> + $ref: '/schemas/types.yaml#/definitions/uint32'
No need for quotes. You don't use it in other places.
> + description: |
> + set the phy-mode for enabling bifurcation
> + bit0: bifurcation for port 0
> + bit1: bifurcation for port 1
> + bit2: aggregation
> + constants are defined in the dt-bindings/phy/phy-rockchip-pcie3.h
Full path. It should also follow vendor,device naming convention.
> + minimum: 0x0
> + maximum: 0x4
> + default: 0x4
> +
> +required:
> + - compatible
> + - reg
> + - rockchip,phy-grf
> + - "#phy-cells"
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/rk3568-cru.h>
> + pcie30phy: phy@fe8c0000 {
> + compatible = "rockchip,rk3568-pcie3-phy";
> + reg = <0x0 0xfe8c0000 0x0 0x20000>;
> + #phy-cells = <0>;
> + clocks = <&pmucru CLK_PCIE30PHY_REF_M>,
> + <&pmucru CLK_PCIE30PHY_REF_N>,
> + <&cru PCLK_PCIE30PHY>;
> + clock-names = "refclk_m", "refclk_n", "pclk";
> + resets = <&cru SRST_PCIE30PHY>;
> + reset-names = "phy";
> + rockchip,phy-grf = <&pcie30_phy_grf>;
> + };
Best regards,
Krzysztof
On 28/04/2022 11:27, Frank Wunderlich wrote:
> Hi
>
>> Gesendet: Donnerstag, 28. April 2022 um 08:34 Uhr
>> Von: "Krzysztof Kozlowski" <[email protected]>
>>
>> On 26/04/2022 15:21, Frank Wunderlich wrote:
>>> From: Frank Wunderlich <[email protected]>
>>>
>>> include/dt-bindings/phy/phy-rockchip-pcie3.h | 21 ++++++++++++++++++++
>>
>> Naming - vendor,device.
>
> ok, would rename to rockchip,pcie3-phy.h, is this ok?
Yes.
>
>>> --- /dev/null
>>> +++ b/include/dt-bindings/phy/phy-rockchip-pcie3.h
>>> @@ -0,0 +1,21 @@
>>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>>
>> s/MIT/BSD-2-clause/ just like bindings because it is part of it. Unless
>> you took it from something and it is already licensed like that?
>
> took this with this license from downstream-repo, only removed snps from name and changed name of include guarding.
Then you need to keep the original license, so it is ok.
Best regards,
Krzysztof