Devicetree
 help / color / mirror / Atom feed
* [PATCH v4 0/6] riscv: spacemit: Add PCIe RC controller support for K3
@ 2026-07-09  4:00 Inochi Amaoto
  2026-07-09  4:00 ` [PATCH v4 1/6] PCI: spacemit-k1: Add device data support Inochi Amaoto
                   ` (5 more replies)
  0 siblings, 6 replies; 30+ messages in thread
From: Inochi Amaoto @ 2026-07-09  4:00 UTC (permalink / raw)
  To: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Inochi Amaoto, Frank Li, Nam Cao, Qiang Yu,
	Krishna Chaitanya Chundru, Xincheng Zhang, Alex Elder,
	Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

The PCIe controller on Spacemit K3 is almost a standard Synopsys
Designware PCIe IP with extra control and external MSI controller
(IMSIC).

Add binding and driver support for PCIe RC controller support on K3.

Changed from v3:
- https://lore.kernel.org/linux-pci/20260703020003.485436-1-inochiama@gmail.com/
patch 5:
1. Add missing interrupt/interrupt-names check for K1

Changed from v2:
- https://lore.kernel.org/linux-pci/20260517014841.254085-1-inochiama@gmail.com/
patch 2:
1. Use unify PCIe phy get/enable/exit function for both K1 and K3.
patch 3:
1. New patch for updating device id for both K1/K3
patch 5:
1. Reuse binding for spacemit,k1-pcie-host
patch 6:
1. Multiple cleanup for the logic already generalized in the previous
   patches.
2. Use generic description for the Kconfig entry.

Changed from v1:
patch 1:
1. Remove post_init callback.
patch 2:
1. Fix devm_kmalloc_array arguments order and error check.
patch 3:
1. Apply Rob's tag.
2. Change check from oneOf to anyOf.
3. Fix spelling mistakes in commit message.
patch 4:
1. Add comment about PHY handle.
2. Remove interrupt "app".
3. Fix spelling mistakes in commit message.
patch 5:
1. Remove all logic related to link up interrupt.
2. Clean up all unused macros.
3. Fix devm_kmalloc_array arguments order and error check.
4. Remove unnecessary start_link logic.
5. Make all magic number as a macro.
6. Fix spelling mistakes in code and commit message.

Inochi Amaoto (6):
  PCI: spacemit-k1: Add device data support
  PCI: spacemit-k1: Add multiple PHY handles support
  PCI: spacemit-k1: Add device id update helper
  dt-bindings: PCI: snps,dw-pcie: Add msi-parent for MSI handle check
  dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller
  PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support

 .../devicetree/bindings/pci/snps,dw-pcie.yaml |   7 +-
 .../bindings/pci/spacemit,k1-pcie-host.yaml   |  50 +++-
 drivers/pci/controller/dwc/Kconfig            |   4 +-
 drivers/pci/controller/dwc/pcie-spacemit-k1.c | 237 ++++++++++++++++--
 4 files changed, 271 insertions(+), 27 deletions(-)

--
2.55.0


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

* [PATCH v4 1/6] PCI: spacemit-k1: Add device data support
  2026-07-09  4:00 [PATCH v4 0/6] riscv: spacemit: Add PCIe RC controller support for K3 Inochi Amaoto
@ 2026-07-09  4:00 ` Inochi Amaoto
  2026-07-09  4:05   ` sashiko-bot
                     ` (2 more replies)
  2026-07-09  4:00 ` [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support Inochi Amaoto
                   ` (4 subsequent siblings)
  5 siblings, 3 replies; 30+ messages in thread
From: Inochi Amaoto @ 2026-07-09  4:00 UTC (permalink / raw)
  To: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Inochi Amaoto, Frank Li, Nam Cao, Qiang Yu,
	Krishna Chaitanya Chundru, Xincheng Zhang, Alex Elder,
	Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

To reuse the K1 PCIe driver logic for K3 PCIe controller, add device
data to handle the K1 specific logic and make room for the incoming
logic for K3.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
 drivers/pci/controller/dwc/pcie-spacemit-k1.c | 30 ++++++++++++++++---
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
index be20a520255b..f6ae8ff3589a 100644
--- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
+++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
@@ -49,8 +49,17 @@
 #define PCIE_CONTROL_LOGIC			0x0004
 #define PCIE_SOFT_RESET			BIT(0)
 
+struct k1_pcie;
+
+struct k1_pcie_device_data {
+	const struct dw_pcie_host_ops *host_ops;
+	const struct dw_pcie_ops *ops;
+	int (*parse_port)(struct k1_pcie *k1);
+};
+
 struct k1_pcie {
 	struct dw_pcie pci;
+	const struct k1_pcie_device_data *data;
 	struct phy *phy;
 	void __iomem *link;
 	struct regmap *pmu;	/* Errors ignored; MMIO-backed regmap */
@@ -278,14 +287,21 @@ static int k1_pcie_parse_port(struct k1_pcie *k1)
 
 static int k1_pcie_probe(struct platform_device *pdev)
 {
+	const struct k1_pcie_device_data *data;
 	struct device *dev = &pdev->dev;
 	struct k1_pcie *k1;
 	int ret;
 
+	data = device_get_match_data(dev);
+	if (!data)
+		return -ENODEV;
+
 	k1 = devm_kzalloc(dev, sizeof(*k1), GFP_KERNEL);
 	if (!k1)
 		return -ENOMEM;
 
+	k1->data = data;
+
 	k1->pmu = syscon_regmap_lookup_by_phandle_args(dev_of_node(dev),
 						       SYSCON_APMU, 1,
 						       &k1->pmu_off);
@@ -299,11 +315,11 @@ static int k1_pcie_probe(struct platform_device *pdev)
 				     "failed to map \"link\" registers\n");
 
 	k1->pci.dev = dev;
-	k1->pci.ops = &k1_pcie_ops;
+	k1->pci.ops = data->ops;
 	k1->pci.pp.num_vectors = MAX_MSI_IRQS;
 	dw_pcie_cap_set(&k1->pci, REQ_RES);
 
-	k1->pci.pp.ops = &k1_pcie_host_ops;
+	k1->pci.pp.ops = data->host_ops;
 
 	/* Hold the PHY in reset until we start the link */
 	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CLK_RESET_CONTROL,
@@ -320,7 +336,7 @@ static int k1_pcie_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, k1);
 
-	ret = k1_pcie_parse_port(k1);
+	ret = data->parse_port(k1);
 	if (ret)
 		return dev_err_probe(dev, ret, "failed to parse root port\n");
 
@@ -338,8 +354,14 @@ static void k1_pcie_remove(struct platform_device *pdev)
 	dw_pcie_host_deinit(&k1->pci.pp);
 }
 
+static const struct k1_pcie_device_data k1_pcie_device_data = {
+	.host_ops	= &k1_pcie_host_ops,
+	.ops		= &k1_pcie_ops,
+	.parse_port	= k1_pcie_parse_port,
+};
+
 static const struct of_device_id k1_pcie_of_match_table[] = {
-	{ .compatible = "spacemit,k1-pcie", },
+	{ .compatible = "spacemit,k1-pcie", .data = &k1_pcie_device_data},
 	{ }
 };
 
-- 
2.55.0


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

* [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-09  4:00 [PATCH v4 0/6] riscv: spacemit: Add PCIe RC controller support for K3 Inochi Amaoto
  2026-07-09  4:00 ` [PATCH v4 1/6] PCI: spacemit-k1: Add device data support Inochi Amaoto
@ 2026-07-09  4:00 ` Inochi Amaoto
  2026-07-09  4:09   ` sashiko-bot
                     ` (2 more replies)
  2026-07-09  4:00 ` [PATCH v4 3/6] PCI: spacemit-k1: Add device id update helper Inochi Amaoto
                   ` (3 subsequent siblings)
  5 siblings, 3 replies; 30+ messages in thread
From: Inochi Amaoto @ 2026-07-09  4:00 UTC (permalink / raw)
  To: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Inochi Amaoto, Frank Li, Nam Cao, Qiang Yu,
	Krishna Chaitanya Chundru, Xincheng Zhang, Alex Elder,
	Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

The PCIe controller on Spacemit K3 may use multiple PHYs at the
same time. The feature is not support by the current driver.
So extend the PHY definition to support multiple PHY handles.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
 drivers/pci/controller/dwc/pcie-spacemit-k1.c | 70 ++++++++++++++++---
 1 file changed, 59 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
index f6ae8ff3589a..e22ecbd09579 100644
--- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
+++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
@@ -55,12 +55,14 @@ struct k1_pcie_device_data {
 	const struct dw_pcie_host_ops *host_ops;
 	const struct dw_pcie_ops *ops;
 	int (*parse_port)(struct k1_pcie *k1);
+	unsigned int max_phy_count;
 };
 
 struct k1_pcie {
 	struct dw_pcie pci;
 	const struct k1_pcie_device_data *data;
-	struct phy *phy;
+	struct phy **phy;
+	unsigned int phy_count;
 	void __iomem *link;
 	struct regmap *pmu;	/* Errors ignored; MMIO-backed regmap */
 	u32 pmu_off;
@@ -119,6 +121,54 @@ static void k1_pcie_disable_resources(struct k1_pcie *k1)
 	clk_bulk_disable_unprepare(ARRAY_SIZE(pci->app_clks), pci->app_clks);
 }
 
+static int k1_pcie_get_phy_handle(struct k1_pcie *k1, struct device_node *node)
+{
+	const struct k1_pcie_device_data *data = k1->data;
+	struct device *dev = k1->pci.dev;
+	unsigned int i;
+
+	k1->phy = devm_kmalloc_array(dev, data->max_phy_count,
+				     sizeof(*k1->phy), GFP_KERNEL);
+	if (!k1->phy)
+		return -ENOMEM;
+
+	for (i = 0; i < data->max_phy_count; i++) {
+		k1->phy[i] = devm_of_phy_get_by_index(dev, node, i);
+		if (IS_ERR(k1->phy[i])) {
+			if (PTR_ERR(k1->phy[i]) == -ENODEV)
+				break;
+
+			return PTR_ERR(k1->phy[i]);
+		}
+	}
+
+	k1->phy_count = i;
+	if (k1->phy_count == 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int k1_pcie_enable_phy(struct k1_pcie *k1)
+{
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < k1->phy_count; i++) {
+		ret = phy_init(k1->phy[i]);
+		if (ret)
+			goto err_phy;
+	}
+
+	return 0;
+
+err_phy:
+	while (i--)
+		phy_exit(k1->phy[i]);
+
+	return ret;
+}
+
 /* FIXME: Disable ASPM L1 to avoid errors reported on some NVMe drives */
 static void k1_pcie_disable_aspm_l1(struct k1_pcie *k1)
 {
@@ -174,7 +224,7 @@ static int k1_pcie_init(struct dw_pcie_rp *pp)
 	 */
 	regmap_set_bits(k1->pmu, reset_ctrl, DEVICE_TYPE_RC | PCIE_AUX_PWR_DET);
 
-	ret = phy_init(k1->phy);
+	ret = k1_pcie_enable_phy(k1);
 	if (ret) {
 		k1_pcie_disable_resources(k1);
 
@@ -194,12 +244,14 @@ static void k1_pcie_deinit(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 	struct k1_pcie *k1 = to_k1_pcie(pci);
+	int i;
 
 	/* Assert fundamental reset (drive PERST# low) */
 	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CLK_RESET_CONTROL,
 			PCIE_RC_PERST);
 
-	phy_exit(k1->phy);
+	for (i = 0; i < k1->phy_count; i++)
+		phy_exit(k1->phy[i]);
 
 	k1_pcie_disable_resources(k1);
 }
@@ -266,23 +318,18 @@ static int k1_pcie_parse_port(struct k1_pcie *k1)
 {
 	struct device *dev = k1->pci.dev;
 	struct device_node *root_port;
-	struct phy *phy;
+	int ret;
 
 	/* We assume only one root port */
 	root_port = of_get_next_available_child(dev_of_node(dev), NULL);
 	if (!root_port)
 		return -EINVAL;
 
-	phy = devm_of_phy_get(dev, root_port, NULL);
+	ret = k1_pcie_get_phy_handle(k1, root_port);
 
 	of_node_put(root_port);
 
-	if (IS_ERR(phy))
-		return PTR_ERR(phy);
-
-	k1->phy = phy;
-
-	return 0;
+	return ret;
 }
 
 static int k1_pcie_probe(struct platform_device *pdev)
@@ -358,6 +405,7 @@ static const struct k1_pcie_device_data k1_pcie_device_data = {
 	.host_ops	= &k1_pcie_host_ops,
 	.ops		= &k1_pcie_ops,
 	.parse_port	= k1_pcie_parse_port,
+	.max_phy_count	= 1,
 };
 
 static const struct of_device_id k1_pcie_of_match_table[] = {
-- 
2.55.0


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

* [PATCH v4 3/6] PCI: spacemit-k1: Add device id update helper
  2026-07-09  4:00 [PATCH v4 0/6] riscv: spacemit: Add PCIe RC controller support for K3 Inochi Amaoto
  2026-07-09  4:00 ` [PATCH v4 1/6] PCI: spacemit-k1: Add device data support Inochi Amaoto
  2026-07-09  4:00 ` [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support Inochi Amaoto
@ 2026-07-09  4:00 ` Inochi Amaoto
  2026-07-09  4:06   ` sashiko-bot
  2026-07-10 16:01   ` Alex Elder
  2026-07-09  4:00 ` [PATCH v4 4/6] dt-bindings: PCI: snps,dw-pcie: Add msi-parent for MSI handle check Inochi Amaoto
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 30+ messages in thread
From: Inochi Amaoto @ 2026-07-09  4:00 UTC (permalink / raw)
  To: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Inochi Amaoto, Frank Li, Nam Cao, Qiang Yu,
	Krishna Chaitanya Chundru, Xincheng Zhang, Alex Elder,
	Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

Both K1 and K3 needs to set vendor id and device id, add a helper function
to simplify this.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
 drivers/pci/controller/dwc/pcie-spacemit-k1.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
index e22ecbd09579..31aac056b68e 100644
--- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
+++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
@@ -56,6 +56,7 @@ struct k1_pcie_device_data {
 	const struct dw_pcie_ops *ops;
 	int (*parse_port)(struct k1_pcie *k1);
 	unsigned int max_phy_count;
+	unsigned int device_id;
 };
 
 struct k1_pcie {
@@ -186,6 +187,16 @@ static void k1_pcie_disable_aspm_l1(struct k1_pcie *k1)
 	dw_pcie_dbi_ro_wr_dis(pci);
 }
 
+static void k1_pcie_set_device_id(struct k1_pcie *k1)
+{
+	struct dw_pcie *pci = &k1->pci;
+
+	dw_pcie_dbi_ro_wr_en(pci);
+	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, PCI_VENDOR_ID_SPACEMIT);
+	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, k1->data->device_id);
+	dw_pcie_dbi_ro_wr_dis(pci);
+}
+
 static int k1_pcie_init(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -201,10 +212,7 @@ static int k1_pcie_init(struct dw_pcie_rp *pp)
 		return ret;
 
 	/* Set the PCI vendor and device ID */
-	dw_pcie_dbi_ro_wr_en(pci);
-	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, PCI_VENDOR_ID_SPACEMIT);
-	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, PCI_DEVICE_ID_SPACEMIT_K1);
-	dw_pcie_dbi_ro_wr_dis(pci);
+	k1_pcie_set_device_id(k1);
 
 	/*
 	 * Start by asserting fundamental reset (drive PERST# low).  The
@@ -406,6 +414,7 @@ static const struct k1_pcie_device_data k1_pcie_device_data = {
 	.ops		= &k1_pcie_ops,
 	.parse_port	= k1_pcie_parse_port,
 	.max_phy_count	= 1,
+	.device_id	= PCI_DEVICE_ID_SPACEMIT_K1,
 };
 
 static const struct of_device_id k1_pcie_of_match_table[] = {
-- 
2.55.0


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

* [PATCH v4 4/6] dt-bindings: PCI: snps,dw-pcie: Add msi-parent for MSI handle check
  2026-07-09  4:00 [PATCH v4 0/6] riscv: spacemit: Add PCIe RC controller support for K3 Inochi Amaoto
                   ` (2 preceding siblings ...)
  2026-07-09  4:00 ` [PATCH v4 3/6] PCI: spacemit-k1: Add device id update helper Inochi Amaoto
@ 2026-07-09  4:00 ` Inochi Amaoto
  2026-07-09  4:06   ` sashiko-bot
  2026-07-10 16:01   ` Alex Elder
  2026-07-09  4:00 ` [PATCH v4 5/6] dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller Inochi Amaoto
  2026-07-09  4:00 ` [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support Inochi Amaoto
  5 siblings, 2 replies; 30+ messages in thread
From: Inochi Amaoto @ 2026-07-09  4:00 UTC (permalink / raw)
  To: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Inochi Amaoto, Frank Li, Nam Cao, Qiang Yu,
	Krishna Chaitanya Chundru, Xincheng Zhang, Alex Elder,
	Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

The IMSIC device on RISC-V based system does not require ID
remapping for MSI. So this device only needs "msi-parent"
property for IMSIC-based SoC, and the "msi-map" is not a
necessary property.

Add new condition for MSI handling on IMSIC based SoC.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
---
 Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
index b3216141881c..91bbbc8924f6 100644
--- a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
@@ -27,8 +27,11 @@ allOf:
   - $ref: /schemas/pci/snps,dw-pcie-common.yaml#
   - if:
       not:
-        required:
-          - msi-map
+        anyOf:
+          - required:
+              - msi-map
+          - required:
+              - msi-parent
     then:
       properties:
         interrupt-names:
-- 
2.55.0


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

* [PATCH v4 5/6] dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller
  2026-07-09  4:00 [PATCH v4 0/6] riscv: spacemit: Add PCIe RC controller support for K3 Inochi Amaoto
                   ` (3 preceding siblings ...)
  2026-07-09  4:00 ` [PATCH v4 4/6] dt-bindings: PCI: snps,dw-pcie: Add msi-parent for MSI handle check Inochi Amaoto
@ 2026-07-09  4:00 ` Inochi Amaoto
  2026-07-09  4:09   ` sashiko-bot
  2026-07-10 16:01   ` Alex Elder
  2026-07-09  4:00 ` [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support Inochi Amaoto
  5 siblings, 2 replies; 30+ messages in thread
From: Inochi Amaoto @ 2026-07-09  4:00 UTC (permalink / raw)
  To: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Inochi Amaoto, Frank Li, Nam Cao, Qiang Yu,
	Krishna Chaitanya Chundru, Xincheng Zhang, Alex Elder,
	Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

Add binding support for the PCIe controller on the SpacemiT K3 SoC.
This controller is almost a standard Synopsys DesignWare PCIe IP,
with some extra link and reset state control.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
 .../bindings/pci/spacemit,k1-pcie-host.yaml   | 50 ++++++++++++++++---
 1 file changed, 43 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml b/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml
index c4c00b5fcdc0..54817d6fd9af 100644
--- a/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml
+++ b/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml
@@ -14,26 +14,29 @@ description: >
   PCIe IP.  The controller uses the DesignWare built-in MSI interrupt
   controller, and supports 256 MSIs.
 
-allOf:
-  - $ref: /schemas/pci/snps,dw-pcie.yaml#
-
 properties:
   compatible:
-    const: spacemit,k1-pcie
+    enum:
+      - spacemit,k1-pcie
+      - spacemit,k3-pcie
 
   reg:
+    minItems: 4
     items:
       - description: DesignWare PCIe registers
       - description: ATU address space
       - description: PCIe configuration space
       - description: Link control registers
+      - description: Data Bus Interface (DBI) shadow registers.
 
   reg-names:
+    minItems: 4
     items:
       - const: dbi
       - const: atu
       - const: config
       - const: link
+      - const: dbi2
 
   clocks:
     items:
@@ -66,6 +69,8 @@ properties:
   interrupt-names:
     const: msi
 
+  msi-parent: true
+
   spacemit,apmu:
     $ref: /schemas/types.yaml#/definitions/phandle-array
     description:
@@ -84,7 +89,8 @@ patternProperties:
 
     properties:
       phys:
-        maxItems: 1
+        minItems: 1
+        maxItems: 6
 
       vpcie3v3-supply:
         description:
@@ -96,13 +102,43 @@ patternProperties:
 
     unevaluatedProperties: false
 
+allOf:
+  - $ref: /schemas/pci/snps,dw-pcie.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: spacemit,k1-pcie
+    then:
+      properties:
+        reg:
+          maxItems: 4
+
+        reg-names:
+          maxItems: 4
+
+      patternProperties:
+        '^pcie@':
+          properties:
+            phys:
+              maxItems: 1
+
+      required:
+        - interrupts
+        - interrupt-names
+    else:
+      properties:
+        reg:
+          minItems: 5
+
+        reg-names:
+          minItems: 5
+
 required:
   - clocks
   - clock-names
   - resets
   - reset-names
-  - interrupts
-  - interrupt-names
   - spacemit,apmu
 
 unevaluatedProperties: false
-- 
2.55.0


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

* [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support
  2026-07-09  4:00 [PATCH v4 0/6] riscv: spacemit: Add PCIe RC controller support for K3 Inochi Amaoto
                   ` (4 preceding siblings ...)
  2026-07-09  4:00 ` [PATCH v4 5/6] dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller Inochi Amaoto
@ 2026-07-09  4:00 ` Inochi Amaoto
  2026-07-09  4:12   ` sashiko-bot
                     ` (2 more replies)
  5 siblings, 3 replies; 30+ messages in thread
From: Inochi Amaoto @ 2026-07-09  4:00 UTC (permalink / raw)
  To: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Inochi Amaoto, Frank Li, Nam Cao, Qiang Yu,
	Krishna Chaitanya Chundru, Xincheng Zhang, Alex Elder,
	Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

The PCIe controller on Spacemit K3 is almost a standard Synopsys
DesignWare PCIe IP with extra link and reset control. Unlike
the PCIe controller on K1, this controller supports external MSI
interrupt controller and can use multiple PHYs at the same time.

Add driver to support PCIe controller on Spacemit K3 PCIe.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
 drivers/pci/controller/dwc/Kconfig            |   4 +-
 drivers/pci/controller/dwc/pcie-spacemit-k1.c | 126 ++++++++++++++++++
 2 files changed, 128 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index aa0b784c85b4..dacbac5cc35c 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -440,7 +440,7 @@ config PCIE_SOPHGO_DW
 	  Sophgo SoCs.
 
 config PCIE_SPACEMIT_K1
-	tristate "SpacemiT K1 PCIe controller (host mode)"
+	tristate "SpacemiT PCIe controller (host mode)"
 	depends on ARCH_SPACEMIT || COMPILE_TEST
 	depends on HAS_IOMEM
 	select PCIE_DW_HOST
@@ -448,7 +448,7 @@ config PCIE_SPACEMIT_K1
 	default ARCH_SPACEMIT
 	help
 	  Enables support for the DesignWare based PCIe controller in
-	  the SpacemiT K1 SoC operating in host mode.  Three controllers
+	  the SpacemiT SoC operating in host mode. Three controllers
 	  are available on the K1 SoC; the first of these shares a PHY
 	  with a USB 3.0 host controller (one or the other can be used).
 
diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
index 31aac056b68e..680acc93f539 100644
--- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
+++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
@@ -23,6 +23,7 @@
 
 #define PCI_VENDOR_ID_SPACEMIT		0x201f
 #define PCI_DEVICE_ID_SPACEMIT_K1	0x0001
+#define PCI_DEVICE_ID_SPACEMIT_K3	0x0002
 
 /* Offsets and field definitions for link management registers */
 #define K1_PHY_AHB_IRQ_EN			0x0000
@@ -32,8 +33,18 @@
 #define SMLH_LINK_UP			BIT(1)
 #define RDLH_LINK_UP			BIT(12)
 
+#define INTR_STATUS				0x0010
+
 #define INTR_ENABLE				0x0014
 #define MSI_CTRL_INT			BIT(11)
+#define RDLH_LINK_UP_INT		BIT(20)
+
+#define K3_PHY_AHB_IRQSTATUS_INTX		0x0008
+
+#define K3_ADDR_INTR_STATUS1			0x0018
+
+#define K3_CACHE_MSTR_AWCACHE_MODE	GENMASK(14, 11)
+#define K3_CACHE_MSTR_AWCACHE_BEHAVIOR	0xf
 
 /* Some controls require APMU regmap access */
 #define SYSCON_APMU			"spacemit,apmu"
@@ -48,6 +59,9 @@
 
 #define PCIE_CONTROL_LOGIC			0x0004
 #define PCIE_SOFT_RESET			BIT(0)
+#define PCIE_PERSTN_OE			BIT(24)
+#define PCIE_PERSTN_OUT			BIT(25)
+#define PCIE_IGNORE_PERSTN		BIT(31)
 
 struct k1_pcie;
 
@@ -340,6 +354,109 @@ static int k1_pcie_parse_port(struct k1_pcie *k1)
 	return ret;
 }
 
+static int k3_pcie_init(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct k1_pcie *k1 = to_k1_pcie(pci);
+	u32 reset_ctrl = k1->pmu_off + PCIE_CLK_RESET_CONTROL;
+	u32 val;
+	int ret;
+
+	regmap_clear_bits(k1->pmu, reset_ctrl, LTSSM_EN);
+
+	k1_pcie_toggle_soft_reset(k1);
+
+	ret = k1_pcie_enable_resources(k1);
+	if (ret)
+		return ret;
+
+	regmap_set_bits(k1->pmu, reset_ctrl, PCIE_AUX_PWR_DET);
+	regmap_clear_bits(k1->pmu, reset_ctrl, APP_HOLD_PHY_RST);
+
+	ret = k1_pcie_enable_phy(k1);
+	if (ret) {
+		k1_pcie_disable_resources(k1);
+		return ret;
+	}
+
+	/* K3: Set IGNORE_PERSTN and drive PERSTN_OE high (assert reset) */
+	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CONTROL_LOGIC,
+			PCIE_IGNORE_PERSTN | PCIE_PERSTN_OE | PCIE_PERSTN_OUT);
+	usleep_range(1000, 2000);
+	regmap_clear_bits(k1->pmu, k1->pmu_off + PCIE_CONTROL_LOGIC, PCIE_PERSTN_OUT);
+
+	msleep(PCIE_T_PVPERL_MS);
+
+	/*
+	 * Put the controller in root complex mode, and indicate that
+	 * Vaux (3.3v) is present.
+	 */
+	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CONTROL_LOGIC,
+			PCIE_PERSTN_OUT | PCIE_PERSTN_OE);
+
+	val = dw_pcie_readl_dbi(pci, GEN3_EQ_CONTROL_OFF);
+	val = u32_replace_bits(val, BIT(7),
+			       GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC);
+	dw_pcie_writel_dbi(pci, GEN3_EQ_CONTROL_OFF, val);
+
+	k1_pcie_set_device_id(k1);
+
+	/* Finally, as a workaround, disable ASPM L1 */
+	k1_pcie_disable_aspm_l1(k1);
+
+	return 0;
+}
+
+static int k3_pcie_msi_host_init(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	u32 val;
+
+	dw_pcie_dbi_ro_wr_en(pci);
+
+	val = dw_pcie_readl_dbi(pci, COHERENCY_CONTROL_3_OFF);
+	val = u32_replace_bits(val, K3_CACHE_MSTR_AWCACHE_BEHAVIOR,
+			       K3_CACHE_MSTR_AWCACHE_MODE);
+	dw_pcie_writel_dbi(pci, COHERENCY_CONTROL_3_OFF, val);
+
+	dw_pcie_dbi_ro_wr_dis(pci);
+
+	return 0;
+}
+
+static const struct dw_pcie_host_ops k3_pcie_host_ops = {
+	.init		= k3_pcie_init,
+	.deinit		= k1_pcie_deinit,
+	.msi_init	= k3_pcie_msi_host_init,
+};
+
+static const struct dw_pcie_ops k3_pcie_ops = {
+	.link_up	= k1_pcie_link_up,
+	.start_link	= k1_pcie_start_link,
+	.stop_link	= k1_pcie_stop_link,
+};
+
+static void k3_pcie_clear_irq_status(struct k1_pcie *k1,
+				     u32 *status0, u32 *status1, u32 *status2)
+{
+	*status0 = readl_relaxed(k1->link + K3_PHY_AHB_IRQSTATUS_INTX);
+	*status1 = readl_relaxed(k1->link + INTR_STATUS);
+	*status2 = readl_relaxed(k1->link + K3_ADDR_INTR_STATUS1);
+
+	writel_relaxed(*status0, k1->link + K3_PHY_AHB_IRQSTATUS_INTX);
+	writel_relaxed(*status1, k1->link + INTR_STATUS);
+	writel_relaxed(*status2, k1->link + K3_ADDR_INTR_STATUS1);
+}
+
+static int k3_pcie_parse_port(struct k1_pcie *k1)
+{
+	u32 status0, status1, status2;
+
+	k3_pcie_clear_irq_status(k1, &status0, &status1, &status2);
+
+	return k1_pcie_parse_port(k1);
+}
+
 static int k1_pcie_probe(struct platform_device *pdev)
 {
 	const struct k1_pcie_device_data *data;
@@ -417,8 +534,17 @@ static const struct k1_pcie_device_data k1_pcie_device_data = {
 	.device_id	= PCI_DEVICE_ID_SPACEMIT_K1,
 };
 
+static const struct k1_pcie_device_data k3_pcie_device_data = {
+	.host_ops	= &k3_pcie_host_ops,
+	.ops		= &k3_pcie_ops,
+	.parse_port	= k3_pcie_parse_port,
+	.max_phy_count	= 6,
+	.device_id	= PCI_DEVICE_ID_SPACEMIT_K3,
+};
+
 static const struct of_device_id k1_pcie_of_match_table[] = {
 	{ .compatible = "spacemit,k1-pcie", .data = &k1_pcie_device_data},
+	{ .compatible = "spacemit,k3-pcie", .data = &k3_pcie_device_data},
 	{ }
 };
 
-- 
2.55.0


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

* Re: [PATCH v4 1/6] PCI: spacemit-k1: Add device data support
  2026-07-09  4:00 ` [PATCH v4 1/6] PCI: spacemit-k1: Add device data support Inochi Amaoto
@ 2026-07-09  4:05   ` sashiko-bot
  2026-07-09  7:09   ` Andy Shevchenko
  2026-07-10 16:01   ` Alex Elder
  2 siblings, 0 replies; 30+ messages in thread
From: sashiko-bot @ 2026-07-09  4:05 UTC (permalink / raw)
  To: Inochi Amaoto; +Cc: robh, conor+dt, linux-pci, devicetree

> To reuse the K1 PCIe driver logic for K3 PCIe controller, add device
> data to handle the K1 specific logic and make room for the incoming
> logic for K3.
> 
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260709040027.958400-1-inochiama@gmail.com?part=1


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

* Re: [PATCH v4 4/6] dt-bindings: PCI: snps,dw-pcie: Add msi-parent for MSI handle check
  2026-07-09  4:00 ` [PATCH v4 4/6] dt-bindings: PCI: snps,dw-pcie: Add msi-parent for MSI handle check Inochi Amaoto
@ 2026-07-09  4:06   ` sashiko-bot
  2026-07-10 16:01   ` Alex Elder
  1 sibling, 0 replies; 30+ messages in thread
From: sashiko-bot @ 2026-07-09  4:06 UTC (permalink / raw)
  To: Inochi Amaoto; +Cc: devicetree, robh, conor+dt, linux-pci

> The IMSIC device on RISC-V based system does not require ID
> remapping for MSI. So this device only needs "msi-parent"
> property for IMSIC-based SoC, and the "msi-map" is not a
> necessary property.
> 
> Add new condition for MSI handling on IMSIC based SoC.
> 
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260709040027.958400-1-inochiama@gmail.com?part=4


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

* Re: [PATCH v4 3/6] PCI: spacemit-k1: Add device id update helper
  2026-07-09  4:00 ` [PATCH v4 3/6] PCI: spacemit-k1: Add device id update helper Inochi Amaoto
@ 2026-07-09  4:06   ` sashiko-bot
  2026-07-10 16:01   ` Alex Elder
  1 sibling, 0 replies; 30+ messages in thread
From: sashiko-bot @ 2026-07-09  4:06 UTC (permalink / raw)
  To: Inochi Amaoto; +Cc: conor+dt, linux-pci, robh, devicetree

> Both K1 and K3 needs to set vendor id and device id, add a helper function
> to simplify this.
> 
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260709040027.958400-1-inochiama@gmail.com?part=3


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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-09  4:00 ` [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support Inochi Amaoto
@ 2026-07-09  4:09   ` sashiko-bot
  2026-07-09  7:16   ` Andy Shevchenko
  2026-07-10 16:01   ` Alex Elder
  2 siblings, 0 replies; 30+ messages in thread
From: sashiko-bot @ 2026-07-09  4:09 UTC (permalink / raw)
  To: Inochi Amaoto; +Cc: robh, devicetree, linux-pci, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] `k1_pcie_deinit()` tears down the PHY array in forward order instead of the standard reverse order used in the initialization error path.
--

--- Patch [2]: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support ---
commit afd1a474faf7e619be1db1da6684dbf945adb2fa
Author: Inochi Amaoto <inochiama@gmail.com>

PCI: spacemit-k1: Add multiple PHY handles support

This commit extends the Spacemit K3 PCIe controller driver to support
multiple PHY handles, as the hardware may use multiple PHYs simultaneously.
It replaces the single PHY reference with an array of PHYs and updates the
initialization and teardown paths to iterate over them.

> diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> index f6ae8ff3589a9..e22ecbd095798 100644
> --- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> +++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c

[ ... ]

> @@ -194,12 +244,14 @@ static void k1_pcie_deinit(struct dw_pcie_rp *pp)
>  {
>  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
>  	struct k1_pcie *k1 = to_k1_pcie(pci);
> +	int i;
>  
>  	/* Assert fundamental reset (drive PERST# low) */
>  	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CLK_RESET_CONTROL,
>  			PCIE_RC_PERST);
>  
> -	phy_exit(k1->phy);
> +	for (i = 0; i < k1->phy_count; i++)
> +		phy_exit(k1->phy[i]);

[Severity: Low]
Does this code need to exit the PHYs in reverse order?

The k1_pcie_enable_phy() function cleans up in reverse order during an
initialization error:

err_phy:
	while (i--)
		phy_exit(k1->phy[i]);

Would it be safer to use reverse-order teardown here in k1_pcie_deinit()
as well to ensure consistency and avoid potential issues if the PHYs
have interdependencies?

>  
>  	k1_pcie_disable_resources(k1);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260709040027.958400-1-inochiama@gmail.com?part=2

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

* Re: [PATCH v4 5/6] dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller
  2026-07-09  4:00 ` [PATCH v4 5/6] dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller Inochi Amaoto
@ 2026-07-09  4:09   ` sashiko-bot
  2026-07-10 16:01   ` Alex Elder
  1 sibling, 0 replies; 30+ messages in thread
From: sashiko-bot @ 2026-07-09  4:09 UTC (permalink / raw)
  To: Inochi Amaoto; +Cc: conor+dt, devicetree, linux-pci, robh

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The `spacemit,k3-pcie` variant drops the requirement for `interrupts` without enforcing an alternative like `msi-parent` or `msi-map`, allowing incomplete device tree nodes to silently pass validation.
--

--- Patch [5]: [PATCH v4 5/6] dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller ---
commit 2fd5f19d10e79ab1400e6aaebad38037440b1cb4
Author: Inochi Amaoto <inochiama@gmail.com>

dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller

This commit adds device tree binding support for the PCIe controller on the
SpacemiT K3 SoC. It introduces a new compatible string and modifies the
schema constraints to accommodate differing register counts and interrupt
configurations between the K1 and K3 variants.

> diff --git a/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml b/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml
> index c4c00b5fcdc0c..54817d6fd9afe 100644
> --- a/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml
> +++ b/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml

[ ... ]

> @@ -102,13 +102,43 @@ patternProperties:
>  
>      unevaluatedProperties: false
>  
> +allOf:
> +  - $ref: /schemas/pci/snps,dw-pcie.yaml#
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: spacemit,k1-pcie
> +    then:

[ ... ]

> +      required:
> +        - interrupts
> +        - interrupt-names
> +    else:
> +      properties:
> +        reg:
> +          minItems: 5
> +
> +        reg-names:
> +          minItems: 5

[Severity: Medium]
Since interrupts and interrupt-names were removed from the global required
list below, should this else block enforce an alternative interrupt
requirement for the spacemit,k3-pcie controller, such as msi-parent or
msi-map?

Does this regression allow device tree nodes for spacemit,k3-pcie that are
missing both interrupts and msi-parent to silently pass schema validation,
potentially failing at runtime due to lacking an MSI domain or interrupt
line?

>  required:
>    - clocks
>    - clock-names
>    - resets
>    - reset-names
> -  - interrupts
> -  - interrupt-names
>    - spacemit,apmu
>  
>  unevaluatedProperties: false

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260709040027.958400-1-inochiama@gmail.com?part=5

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

* Re: [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support
  2026-07-09  4:00 ` [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support Inochi Amaoto
@ 2026-07-09  4:12   ` sashiko-bot
  2026-07-09  7:21   ` Andy Shevchenko
  2026-07-10 16:01   ` Alex Elder
  2 siblings, 0 replies; 30+ messages in thread
From: sashiko-bot @ 2026-07-09  4:12 UTC (permalink / raw)
  To: Inochi Amaoto; +Cc: devicetree, conor+dt, linux-pci, robh

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] k3_pcie_parse_port() accesses memory-mapped registers before the hardware clocks are enabled and resets are deasserted, causing a synchronous external abort.
- [High] k3_pcie_msi_host_init() misuses the .msi_init callback to configure general AXI cache coherency, which breaks DMA coherency if MSI is disabled.
- [Medium] The K3 controller reuses k1_pcie_deinit() for its .deinit callback, which uses an incompatible mechanism to assert PERST#, leaving the PCIe endpoint without a proper hard reset upon driver unbind or probe failure.
- [Low] Misleading copy-pasted comment regarding root complex mode and Vaux configuration.
--

--- Patch [6]: [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support ---
commit b7987f86bd7e30a14ad7fab3615f89d71ad70fed
Author: Inochi Amaoto <inochiama@gmail.com>

PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support

This commit adds support for the PCIe controller on the Spacemit K3 SoC. It
introduces the K3-specific initialization sequence, operations, and interrupt
handling, while reusing the existing Spacemit K1 driver structure.

> diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> index 31aac056b68ed..680acc93f5395 100644
> --- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> +++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c

[ ... ]

> @@ -340,6 +354,109 @@ static int k1_pcie_parse_port(struct k1_pcie *k1)
>  	return ret;
>  }
>  
> +static int k3_pcie_init(struct dw_pcie_rp *pp)
> +{

[ ... ]

> +	/*
> +	 * Put the controller in root complex mode, and indicate that
> +	 * Vaux (3.3v) is present.
> +	 */
> +	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CONTROL_LOGIC,
> +			PCIE_PERSTN_OUT | PCIE_PERSTN_OE);

[Severity: Low]
This isn't a bug, but does this comment match the code beneath it?

The code seems to only toggle PERST# via PCIE_PERSTN_OUT and PCIE_PERSTN_OE,
whereas the comment states it is putting the controller in root complex
mode and indicating Vaux is present.

> +
> +	val = dw_pcie_readl_dbi(pci, GEN3_EQ_CONTROL_OFF);

[ ... ]

> +static int k3_pcie_msi_host_init(struct dw_pcie_rp *pp)
> +{
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> +	u32 val;
> +
> +	dw_pcie_dbi_ro_wr_en(pci);
> +
> +	val = dw_pcie_readl_dbi(pci, COHERENCY_CONTROL_3_OFF);
> +	val = u32_replace_bits(val, K3_CACHE_MSTR_AWCACHE_BEHAVIOR,
> +			       K3_CACHE_MSTR_AWCACHE_MODE);
> +	dw_pcie_writel_dbi(pci, COHERENCY_CONTROL_3_OFF, val);

[Severity: High]
Does configuring general AXI DMA coherency inside an MSI-specific hook break
DMA coherency if the system is booted with 'pci=nomsi'?

dw_pcie_host_init() only calls the .msi_init callback if pci_msi_enabled() is
true. If MSI is disabled, this initialization is skipped and standard DMA
coherency attributes might not be applied.

> +
> +	dw_pcie_dbi_ro_wr_dis(pci);
> +
> +	return 0;
> +}
> +
> +static const struct dw_pcie_host_ops k3_pcie_host_ops = {
> +	.init		= k3_pcie_init,
> +	.deinit		= k1_pcie_deinit,

[Severity: Medium]
Will this properly hard-reset the K3 PCIe endpoint during driver unbind or
probe failure?

The K3 controller reuses k1_pcie_deinit() here, which asserts PCIE_RC_PERST
in PCIE_CLK_RESET_CONTROL. However, k3_pcie_init() shows that K3 requires
PERST# to be asserted via PCIE_PERSTN_OE and PCIE_PERSTN_OUT in
PCIE_CONTROL_LOGIC.

> +	.msi_init	= k3_pcie_msi_host_init,
> +};

[ ... ]

> +static void k3_pcie_clear_irq_status(struct k1_pcie *k1,
> +				     u32 *status0, u32 *status1, u32 *status2)
> +{
> +	*status0 = readl_relaxed(k1->link + K3_PHY_AHB_IRQSTATUS_INTX);
> +	*status1 = readl_relaxed(k1->link + INTR_STATUS);
> +	*status2 = readl_relaxed(k1->link + K3_ADDR_INTR_STATUS1);
> +
> +	writel_relaxed(*status0, k1->link + K3_PHY_AHB_IRQSTATUS_INTX);
> +	writel_relaxed(*status1, k1->link + INTR_STATUS);
> +	writel_relaxed(*status2, k1->link + K3_ADDR_INTR_STATUS1);
> +}
> +
> +static int k3_pcie_parse_port(struct k1_pcie *k1)
> +{
> +	u32 status0, status1, status2;
> +
> +	k3_pcie_clear_irq_status(k1, &status0, &status1, &status2);

[Severity: High]
Can accessing these memory-mapped registers here cause a synchronous
external abort?

During probe, k1_pcie_probe() calls data->parse_port() before calling
dw_pcie_host_init(). However, the hardware clocks are enabled and resets are
deasserted later, inside dw_pcie_host_init(), when it invokes the .init
callback (k3_pcie_init()). Accessing the k1->link registers before they are
clocked may crash the system.

> +
> +	return k1_pcie_parse_port(k1);
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260709040027.958400-1-inochiama@gmail.com?part=6

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

* Re: [PATCH v4 1/6] PCI: spacemit-k1: Add device data support
  2026-07-09  4:00 ` [PATCH v4 1/6] PCI: spacemit-k1: Add device data support Inochi Amaoto
  2026-07-09  4:05   ` sashiko-bot
@ 2026-07-09  7:09   ` Andy Shevchenko
  2026-07-10 16:01   ` Alex Elder
  2 siblings, 0 replies; 30+ messages in thread
From: Andy Shevchenko @ 2026-07-09  7:09 UTC (permalink / raw)
  To: Inochi Amaoto
  Cc: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Alex Elder, Siddharth Vadapalli, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel, linux-pci, devicetree,
	linux-kernel, linux-riscv, spacemit, Yixun Lan, Longbin Li

On Thu, Jul 09, 2026 at 12:00:21PM +0800, Inochi Amaoto wrote:
> To reuse the K1 PCIe driver logic for K3 PCIe controller, add device
> data to handle the K1 specific logic and make room for the incoming
> logic for K3.

...

>  static const struct of_device_id k1_pcie_of_match_table[] = {
> -	{ .compatible = "spacemit,k1-pcie", },
> +	{ .compatible = "spacemit,k1-pcie", .data = &k1_pcie_device_data},

Missing space before }.

>  	{ }
>  };

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-09  4:00 ` [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support Inochi Amaoto
  2026-07-09  4:09   ` sashiko-bot
@ 2026-07-09  7:16   ` Andy Shevchenko
  2026-07-10  1:57     ` Inochi Amaoto
  2026-07-10 12:51     ` Alex Elder
  2026-07-10 16:01   ` Alex Elder
  2 siblings, 2 replies; 30+ messages in thread
From: Andy Shevchenko @ 2026-07-09  7:16 UTC (permalink / raw)
  To: Inochi Amaoto
  Cc: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Alex Elder, Siddharth Vadapalli, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel, linux-pci, devicetree,
	linux-kernel, linux-riscv, spacemit, Yixun Lan, Longbin Li

On Thu, Jul 09, 2026 at 12:00:22PM +0800, Inochi Amaoto wrote:
> The PCIe controller on Spacemit K3 may use multiple PHYs at the
> same time. The feature is not support by the current driver.
> So extend the PHY definition to support multiple PHY handles.

...

>  struct k1_pcie {
>  	struct dw_pcie pci;
>  	const struct k1_pcie_device_data *data;
> -	struct phy *phy;
> +	struct phy **phy;

Should it be annotated by __counted_by_ptr() ?

> +	unsigned int phy_count;

Ah, you allocate much more memory than possible PHYs... Can you redesign and
use the above annotation?

>  	void __iomem *link;
>  	struct regmap *pmu;	/* Errors ignored; MMIO-backed regmap */
>  	u32 pmu_off;

>  }

...

> +static int k1_pcie_get_phy_handle(struct k1_pcie *k1, struct device_node *node)
> +{
> +	const struct k1_pcie_device_data *data = k1->data;
> +	struct device *dev = k1->pci.dev;
> +	unsigned int i;
> +
> +	k1->phy = devm_kmalloc_array(dev, data->max_phy_count,
> +				     sizeof(*k1->phy), GFP_KERNEL);
> +	if (!k1->phy)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < data->max_phy_count; i++) {
> +		k1->phy[i] = devm_of_phy_get_by_index(dev, node, i);

> +		if (IS_ERR(k1->phy[i])) {
> +			if (PTR_ERR(k1->phy[i]) == -ENODEV)
> +				break;
> +
> +			return PTR_ERR(k1->phy[i]);
> +		}

		if (PTR_ERR(k1->phy[i]) == -ENODEV)
			break;
		if (IS_ERR(k1->phy[i]))
			return PTR_ERR(k1->phy[i]);


> +	}

> +	k1->phy_count = i;
> +	if (k1->phy_count == 0)
> +		return -EINVAL;
> +
> +	return 0;

This doesn't seem correct to me, I would expect phy_count to be assigned only
when it's valid. (Yes, perhaps 0 is the same as it was, but semantically it's
different 0 in this case.)

See also above. Do we have some PHY API that just counts provided PHYs?
If not, that what you should probably add first, before this patch.

> +}
> +
> +static int k1_pcie_enable_phy(struct k1_pcie *k1)
> +{
> +	unsigned int i;
> +	int ret;
> +
> +	for (i = 0; i < k1->phy_count; i++) {
> +		ret = phy_init(k1->phy[i]);
> +		if (ret)
> +			goto err_phy;
> +	}
> +
> +	return 0;
> +
> +err_phy:
> +	while (i--)
> +		phy_exit(k1->phy[i]);
> +
> +	return ret;
> +}

...

> static void k1_pcie_deinit(struct dw_pcie_rp *pp)
>  {
>  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
>  	struct k1_pcie *k1 = to_k1_pcie(pci);

> +	int i;
>  
>  	/* Assert fundamental reset (drive PERST# low) */
>  	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CLK_RESET_CONTROL,
>  			PCIE_RC_PERST);
>  
> -	phy_exit(k1->phy);

> +	for (i = 0; i < k1->phy_count; i++)

	for (unsigned int i = 0; i < k1->phy_count; i++)

> +		phy_exit(k1->phy[i]);
>  
>  	k1_pcie_disable_resources(k1);
>  }

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support
  2026-07-09  4:00 ` [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support Inochi Amaoto
  2026-07-09  4:12   ` sashiko-bot
@ 2026-07-09  7:21   ` Andy Shevchenko
  2026-07-10 16:01   ` Alex Elder
  2 siblings, 0 replies; 30+ messages in thread
From: Andy Shevchenko @ 2026-07-09  7:21 UTC (permalink / raw)
  To: Inochi Amaoto
  Cc: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Alex Elder, Siddharth Vadapalli, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel, linux-pci, devicetree,
	linux-kernel, linux-riscv, spacemit, Yixun Lan, Longbin Li

On Thu, Jul 09, 2026 at 12:00:26PM +0800, Inochi Amaoto wrote:
> The PCIe controller on Spacemit K3 is almost a standard Synopsys
> DesignWare PCIe IP with extra link and reset control. Unlike
> the PCIe controller on K1, this controller supports external MSI
> interrupt controller and can use multiple PHYs at the same time.
> 
> Add driver to support PCIe controller on Spacemit K3 PCIe.

...

> +	/* K3: Set IGNORE_PERSTN and drive PERSTN_OE high (assert reset) */
> +	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CONTROL_LOGIC,
> +			PCIE_IGNORE_PERSTN | PCIE_PERSTN_OE | PCIE_PERSTN_OUT);
> +	usleep_range(1000, 2000);

fsleep(1 * USEC_PER_MSEC)

> +	regmap_clear_bits(k1->pmu, k1->pmu_off + PCIE_CONTROL_LOGIC, PCIE_PERSTN_OUT);
> +
> +	msleep(PCIE_T_PVPERL_MS);

If PCIE_T_PVPERL_MS is too small, msleep() maybe not a good choice,
perhaps

fsleep(PCIE_T_PVPERL_MS * USEC_PER_MSEC)

...

> +	val = u32_replace_bits(val, BIT(7),
> +			       GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC);

It's perfectly a single line.

...

>  static const struct of_device_id k1_pcie_of_match_table[] = {
>  	{ .compatible = "spacemit,k1-pcie", .data = &k1_pcie_device_data},
> +	{ .compatible = "spacemit,k3-pcie", .data = &k3_pcie_device_data},

Missed space.

>  	{ }
>  };

I don't see (and haven't checked) the context, do you have
MODULE_DEVICE_TABLE() for this?

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-09  7:16   ` Andy Shevchenko
@ 2026-07-10  1:57     ` Inochi Amaoto
  2026-07-10  8:07       ` Andy Shevchenko
  2026-07-10 12:51     ` Alex Elder
  1 sibling, 1 reply; 30+ messages in thread
From: Inochi Amaoto @ 2026-07-10  1:57 UTC (permalink / raw)
  To: Andy Shevchenko, Inochi Amaoto
  Cc: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Alex Elder, Siddharth Vadapalli, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel, linux-pci, devicetree,
	linux-kernel, linux-riscv, spacemit, Yixun Lan, Longbin Li

On Thu, Jul 09, 2026 at 10:16:28AM +0300, Andy Shevchenko wrote:
> On Thu, Jul 09, 2026 at 12:00:22PM +0800, Inochi Amaoto wrote:
> > The PCIe controller on Spacemit K3 may use multiple PHYs at the
> > same time. The feature is not support by the current driver.
> > So extend the PHY definition to support multiple PHY handles.
> 
> ...
> 
> >  struct k1_pcie {
> >  	struct dw_pcie pci;
> >  	const struct k1_pcie_device_data *data;
> > -	struct phy *phy;
> > +	struct phy **phy;
> 
> Should it be annotated by __counted_by_ptr() ?
> 

Yes, I think it can, this is something I have missed.

> > +	unsigned int phy_count;
> 
> Ah, you allocate much more memory than possible PHYs... Can you redesign and
> use the above annotation?
> 

IIRC use the annotation does not reduce this memory usage...


> >  	void __iomem *link;
> >  	struct regmap *pmu;	/* Errors ignored; MMIO-backed regmap */
> >  	u32 pmu_off;
> 
> >  }
> 
> ...
> 
> > +static int k1_pcie_get_phy_handle(struct k1_pcie *k1, struct device_node *node)
> > +{
> > +	const struct k1_pcie_device_data *data = k1->data;
> > +	struct device *dev = k1->pci.dev;
> > +	unsigned int i;
> > +
> > +	k1->phy = devm_kmalloc_array(dev, data->max_phy_count,
> > +				     sizeof(*k1->phy), GFP_KERNEL);
> > +	if (!k1->phy)
> > +		return -ENOMEM;
> > +
> > +	for (i = 0; i < data->max_phy_count; i++) {
> > +		k1->phy[i] = devm_of_phy_get_by_index(dev, node, i);
> 
> > +		if (IS_ERR(k1->phy[i])) {
> > +			if (PTR_ERR(k1->phy[i]) == -ENODEV)
> > +				break;
> > +
> > +			return PTR_ERR(k1->phy[i]);
> > +		}
> 
> 		if (PTR_ERR(k1->phy[i]) == -ENODEV)
> 			break;
> 		if (IS_ERR(k1->phy[i]))
> 			return PTR_ERR(k1->phy[i]);
> 

Yeah, this is more clear. Thanks.

> 
> > +	}
> 
> > +	k1->phy_count = i;
> > +	if (k1->phy_count == 0)
> > +		return -EINVAL;
> > +
> > +	return 0;
> 
> This doesn't seem correct to me, I would expect phy_count to be assigned only
> when it's valid. (Yes, perhaps 0 is the same as it was, but semantically it's
> different 0 in this case.)
> 

I guess you think 0 is a valid number? I can not understand what you thing
Assign this to 0 if there is no phy is fine to me, which shows there is 0
vaild phy found.

> See also above. Do we have some PHY API that just counts provided PHYs?
> If not, that what you should probably add first, before this patch.
> 

I have not found any api for this. But the actual problem is, how the api
is designed. I have checked both the array bulk api for reset and clock,
it seems like it is much more than this patch...

> > +}
> > +
> > +static int k1_pcie_enable_phy(struct k1_pcie *k1)
> > +{
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	for (i = 0; i < k1->phy_count; i++) {
> > +		ret = phy_init(k1->phy[i]);
> > +		if (ret)
> > +			goto err_phy;
> > +	}
> > +
> > +	return 0;
> > +
> > +err_phy:
> > +	while (i--)
> > +		phy_exit(k1->phy[i]);
> > +
> > +	return ret;
> > +}
> 
> ...
> 
> > static void k1_pcie_deinit(struct dw_pcie_rp *pp)
> >  {
> >  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> >  	struct k1_pcie *k1 = to_k1_pcie(pci);
> 
> > +	int i;
> >  
> >  	/* Assert fundamental reset (drive PERST# low) */
> >  	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CLK_RESET_CONTROL,
> >  			PCIE_RC_PERST);
> >  
> > -	phy_exit(k1->phy);
> 
> > +	for (i = 0; i < k1->phy_count; i++)
> 
> 	for (unsigned int i = 0; i < k1->phy_count; i++)
> 

I agree with the unsigned int, but I guess this definition is not
allowed in linux.

> > +		phy_exit(k1->phy[i]);
> >  
> >  	k1_pcie_disable_resources(k1);
> >  }
> 
> -- 
> With Best Regards,
> Andy Shevchenko
> 
> 

Regards,
Inochi

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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-10  1:57     ` Inochi Amaoto
@ 2026-07-10  8:07       ` Andy Shevchenko
  2026-07-10 10:55         ` Inochi Amaoto
  0 siblings, 1 reply; 30+ messages in thread
From: Andy Shevchenko @ 2026-07-10  8:07 UTC (permalink / raw)
  To: Inochi Amaoto
  Cc: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Alex Elder, Siddharth Vadapalli, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel, linux-pci, devicetree,
	linux-kernel, linux-riscv, spacemit, Yixun Lan, Longbin Li

On Fri, Jul 10, 2026 at 09:57:05AM +0800, Inochi Amaoto wrote:
> On Thu, Jul 09, 2026 at 10:16:28AM +0300, Andy Shevchenko wrote:
> > On Thu, Jul 09, 2026 at 12:00:22PM +0800, Inochi Amaoto wrote:

...

> > >  struct k1_pcie {
> > >  	struct dw_pcie pci;
> > >  	const struct k1_pcie_device_data *data;
> > > -	struct phy *phy;
> > > +	struct phy **phy;
> > 
> > Should it be annotated by __counted_by_ptr() ?
> 
> Yes, I think it can, this is something I have missed.
> 
> > > +	unsigned int phy_count;
> > 
> > Ah, you allocate much more memory than possible PHYs... Can you redesign and
> > use the above annotation?
> 
> IIRC use the annotation does not reduce this memory usage...

It's about how you allocate it, the code uses max_phy_count instead of
phy_count.

> > >  	void __iomem *link;
> > >  	struct regmap *pmu;	/* Errors ignored; MMIO-backed regmap */
> > >  	u32 pmu_off;
> > 
> > >  }

...

> > > +	k1->phy_count = i;
> > > +	if (k1->phy_count == 0)
> > > +		return -EINVAL;
> > > +
> > > +	return 0;
> > 
> > This doesn't seem correct to me, I would expect phy_count to be assigned only
> > when it's valid. (Yes, perhaps 0 is the same as it was, but semantically it's
> > different 0 in this case.)
> 
> I guess you think 0 is a valid number? I can not understand what you thing
> Assign this to 0 if there is no phy is fine to me, which shows there is 0
> vaild phy found.

Isn't it already 0? Semantically code is wrong in a flow (not in the result).

> > See also above. Do we have some PHY API that just counts provided PHYs?
> > If not, that what you should probably add first, before this patch.
> 
> I have not found any api for this. But the actual problem is, how the api
> is designed. I have checked both the array bulk api for reset and clock,
> it seems like it is much more than this patch...

Yeah, I looked at the phy-core and I think it will be hard to implement.
So, the idea is then is to reallocate the pointer each time you get a new PHY.
In this case the phy_count will reflect the actual memory consumption by phy.

...

> > > +	for (i = 0; i < k1->phy_count; i++)
> > 
> > 	for (unsigned int i = 0; i < k1->phy_count; i++)
> > 
> 
> I agree with the unsigned int, but I guess this definition is not
> allowed in linux.

It's allowed and it's encouraged even by Linus. As long as iterator is local,
use this syntax sugar and reduce its scope. It hardens the code.

> > > +		phy_exit(k1->phy[i]);

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-10  8:07       ` Andy Shevchenko
@ 2026-07-10 10:55         ` Inochi Amaoto
  2026-07-10 12:42           ` Alex Elder
  2026-07-11 12:44           ` Andy Shevchenko
  0 siblings, 2 replies; 30+ messages in thread
From: Inochi Amaoto @ 2026-07-10 10:55 UTC (permalink / raw)
  To: Andy Shevchenko, Inochi Amaoto
  Cc: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Alex Elder, Siddharth Vadapalli, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel, linux-pci, devicetree,
	linux-kernel, linux-riscv, spacemit, Yixun Lan, Longbin Li

On Fri, Jul 10, 2026 at 11:07:40AM +0300, Andy Shevchenko wrote:
> On Fri, Jul 10, 2026 at 09:57:05AM +0800, Inochi Amaoto wrote:
> > On Thu, Jul 09, 2026 at 10:16:28AM +0300, Andy Shevchenko wrote:
> > > On Thu, Jul 09, 2026 at 12:00:22PM +0800, Inochi Amaoto wrote:
> 
> ...
> 
> > > >  struct k1_pcie {
> > > >  	struct dw_pcie pci;
> > > >  	const struct k1_pcie_device_data *data;
> > > > -	struct phy *phy;
> > > > +	struct phy **phy;
> > > 
> > > Should it be annotated by __counted_by_ptr() ?
> > 
> > Yes, I think it can, this is something I have missed.
> > 
> > > > +	unsigned int phy_count;
> > > 
> > > Ah, you allocate much more memory than possible PHYs... Can you redesign and
> > > use the above annotation?
> > 
> > IIRC use the annotation does not reduce this memory usage...
> 
> It's about how you allocate it, the code uses max_phy_count instead of
> phy_count.
> 
> > > >  	void __iomem *link;
> > > >  	struct regmap *pmu;	/* Errors ignored; MMIO-backed regmap */
> > > >  	u32 pmu_off;
> > > 
> > > >  }
> 
> ...
> 
> > > > +	k1->phy_count = i;
> > > > +	if (k1->phy_count == 0)
> > > > +		return -EINVAL;
> > > > +
> > > > +	return 0;
> > > 
> > > This doesn't seem correct to me, I would expect phy_count to be assigned only
> > > when it's valid. (Yes, perhaps 0 is the same as it was, but semantically it's
> > > different 0 in this case.)
> > 
> > I guess you think 0 is a valid number? I can not understand what you thing
> > Assign this to 0 if there is no phy is fine to me, which shows there is 0
> > vaild phy found.
> 
> Isn't it already 0? Semantically code is wrong in a flow (not in the result).
> 

In fact it is already 0 here. But I am not understand why you thing is wrong.
Could you explain it in detail? (Maybe you think it is not good to return 
-EINVAL?)

> > > See also above. Do we have some PHY API that just counts provided PHYs?
> > > If not, that what you should probably add first, before this patch.
> > 
> > I have not found any api for this. But the actual problem is, how the api
> > is designed. I have checked both the array bulk api for reset and clock,
> > it seems like it is much more than this patch...
> 
> Yeah, I looked at the phy-core and I think it will be hard to implement.
> So, the idea is then is to reallocate the pointer each time you get a new PHY.
> In this case the phy_count will reflect the actual memory consumption by phy.
> 

Emmm, I think it is kind of buggy and not necessary. In most case
this array is not long actually, so allocate some pointer should be
fine and be an acceptable cost.

> ...
> 
> > > > +	for (i = 0; i < k1->phy_count; i++)
> > > 
> > > 	for (unsigned int i = 0; i < k1->phy_count; i++)
> > > 
> > 
> > I agree with the unsigned int, but I guess this definition is not
> > allowed in linux.
> 
> It's allowed and it's encouraged even by Linus. As long as iterator is local,
> use this syntax sugar and reduce its scope. It hardens the code.
> 

Could you give me a reference url to check, I have not found this
on the coding-style.
https://www.kernel.org/doc/html/latest/process/coding-style.html

> > > > +		phy_exit(k1->phy[i]);
> 
> -- 
> With Best Regards,
> Andy Shevchenko
> 
> 

Regards,
Inochi

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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-10 10:55         ` Inochi Amaoto
@ 2026-07-10 12:42           ` Alex Elder
  2026-07-11 13:01             ` Andy Shevchenko
  2026-07-11 12:44           ` Andy Shevchenko
  1 sibling, 1 reply; 30+ messages in thread
From: Alex Elder @ 2026-07-10 12:42 UTC (permalink / raw)
  To: Inochi Amaoto, Andy Shevchenko
  Cc: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Siddharth Vadapalli, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel, linux-pci, devicetree, linux-kernel,
	linux-riscv, spacemit, Yixun Lan, Longbin Li

On 7/10/26 5:55 AM, Inochi Amaoto wrote:
>>>>> +	k1->phy_count = i;
>>>>> +	if (k1->phy_count == 0)
>>>>> +		return -EINVAL;
>>>>> +
>>>>> +	return 0;
>>>> This doesn't seem correct to me, I would expect phy_count to be assigned only
>>>> when it's valid. (Yes, perhaps 0 is the same as it was, but semantically it's
>>>> different 0 in this case.)
>>> I guess you think 0 is a valid number? I can not understand what you thing
>>> Assign this to 0 if there is no phy is fine to me, which shows there is 0
>>> vaild phy found.
>> Isn't it already 0? Semantically code is wrong in a flow (not in the result).
>>
> In fact it is already 0 here. But I am not understand why you thing is wrong.
> Could you explain it in detail? (Maybe you think it is not good to return
> -EINVAL?)

What Andy is saying is that assigning the value of phy_count
before checking that it is valid is not the expected order of
things.

The point is about best practice, not about the end result.

Best practice would be "don't touch anything if the return
value will indicate an error."

And therefore, better coding practice would be to check for
a bad value, and only after that has been done should you
assign the k1->phy_count value.

					-Alex

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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-09  7:16   ` Andy Shevchenko
  2026-07-10  1:57     ` Inochi Amaoto
@ 2026-07-10 12:51     ` Alex Elder
  2026-07-11 13:04       ` Andy Shevchenko
  1 sibling, 1 reply; 30+ messages in thread
From: Alex Elder @ 2026-07-10 12:51 UTC (permalink / raw)
  To: Andy Shevchenko, Inochi Amaoto
  Cc: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Siddharth Vadapalli, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel, linux-pci, devicetree, linux-kernel,
	linux-riscv, spacemit, Yixun Lan, Longbin Li

On 7/9/26 2:16 AM, Andy Shevchenko wrote:
>> +		if (IS_ERR(k1->phy[i])) {
>> +			if (PTR_ERR(k1->phy[i]) == -ENODEV)
>> +				break;
>> +
>> +			return PTR_ERR(k1->phy[i]);
>> +		}
> 		if (PTR_ERR(k1->phy[i]) == -ENODEV)
> 			break;
> 		if (IS_ERR(k1->phy[i]))
> 			return PTR_ERR(k1->phy[i]);

I'm not sure this is a huge improvement.  Checking IS_ERR()
before using PTR_ERR() is comforting (a little along the
lines of the other issue you mentioned--assigning a result
before checking for an error).  Anyway, it's a little bit
of an ugly construct no matter how you do it.  Here's another
possible way to do it.

	k1->phy[i] = devm_of_phy_get_by_index(dev, node, i);
	if (!IS_ERR(k1->phy[i]))
		continue;

	ret = PTR_ERR(k1->phy[i]);
	if (ret == -ENODEV)
		break;

	return ret;

					-Alex

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

* Re: [PATCH v4 1/6] PCI: spacemit-k1: Add device data support
  2026-07-09  4:00 ` [PATCH v4 1/6] PCI: spacemit-k1: Add device data support Inochi Amaoto
  2026-07-09  4:05   ` sashiko-bot
  2026-07-09  7:09   ` Andy Shevchenko
@ 2026-07-10 16:01   ` Alex Elder
  2 siblings, 0 replies; 30+ messages in thread
From: Alex Elder @ 2026-07-10 16:01 UTC (permalink / raw)
  To: Inochi Amaoto, Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

On 7/8/26 11:00 PM, Inochi Amaoto wrote:
> To reuse the K1 PCIe driver logic for K3 PCIe controller, add device
> data to handle the K1 specific logic and make room for the incoming
> logic for K3.
> 
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>

I have two suggestions/questions, but I think this looks
good overall (please add the space that Andy suggested).

If you drop the data field in the k1_pcie structure you
can keep this tag:

Reviewed-by: Alex Elder <elder@riscstar.com>

> ---
>   drivers/pci/controller/dwc/pcie-spacemit-k1.c | 30 ++++++++++++++++---
>   1 file changed, 26 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> index be20a520255b..f6ae8ff3589a 100644
> --- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> +++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> @@ -49,8 +49,17 @@
>   #define PCIE_CONTROL_LOGIC			0x0004
>   #define PCIE_SOFT_RESET			BIT(0)
>   
> +struct k1_pcie;
> +
> +struct k1_pcie_device_data {
> +	const struct dw_pcie_host_ops *host_ops;
> +	const struct dw_pcie_ops *ops;
> +	int (*parse_port)(struct k1_pcie *k1);
> +};
> +
>   struct k1_pcie {
>   	struct dw_pcie pci;
> +	const struct k1_pcie_device_data *data;

Is it strictly necessary to keep a copy of the data
pointer in the k1_pcie structure?

It can be convenient to do so if you reuse the fields
in that structure rather than duplicating them, but
often the constant platform data is meant only for
initialization, and never needed after that.

>   	struct phy *phy;
>   	void __iomem *link;
>   	struct regmap *pmu;	/* Errors ignored; MMIO-backed regmap */
> @@ -278,14 +287,21 @@ static int k1_pcie_parse_port(struct k1_pcie *k1)
>   
>   static int k1_pcie_probe(struct platform_device *pdev)
>   {
> +	const struct k1_pcie_device_data *data;
>   	struct device *dev = &pdev->dev;
>   	struct k1_pcie *k1;
>   	int ret;
>   
> +	data = device_get_match_data(dev);
> +	if (!data)
> +		return -ENODEV;
> +
>   	k1 = devm_kzalloc(dev, sizeof(*k1), GFP_KERNEL);
>   	if (!k1)
>   		return -ENOMEM;
>   
> +	k1->data = data;
> +
>   	k1->pmu = syscon_regmap_lookup_by_phandle_args(dev_of_node(dev),
>   						       SYSCON_APMU, 1,
>   						       &k1->pmu_off);
> @@ -299,11 +315,11 @@ static int k1_pcie_probe(struct platform_device *pdev)
>   				     "failed to map \"link\" registers\n");
>   
>   	k1->pci.dev = dev;
> -	k1->pci.ops = &k1_pcie_ops;
> +	k1->pci.ops = data->ops;
>   	k1->pci.pp.num_vectors = MAX_MSI_IRQS;
>   	dw_pcie_cap_set(&k1->pci, REQ_RES);
>   
> -	k1->pci.pp.ops = &k1_pcie_host_ops;
> +	k1->pci.pp.ops = data->host_ops;
>   
>   	/* Hold the PHY in reset until we start the link */
>   	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CLK_RESET_CONTROL,
> @@ -320,7 +336,7 @@ static int k1_pcie_probe(struct platform_device *pdev)
>   
>   	platform_set_drvdata(pdev, k1);
>   
> -	ret = k1_pcie_parse_port(k1);
> +	ret = data->parse_port(k1);
>   	if (ret)
>   		return dev_err_probe(dev, ret, "failed to parse root port\n");
>   
> @@ -338,8 +354,14 @@ static void k1_pcie_remove(struct platform_device *pdev)
>   	dw_pcie_host_deinit(&k1->pci.pp);
>   }
>   
> +static const struct k1_pcie_device_data k1_pcie_device_data = {
> +	.host_ops	= &k1_pcie_host_ops,
> +	.ops		= &k1_pcie_ops,
> +	.parse_port	= k1_pcie_parse_port,
> +};
> +
>   static const struct of_device_id k1_pcie_of_match_table[] = {
> -	{ .compatible = "spacemit,k1-pcie", },
> +	{ .compatible = "spacemit,k1-pcie", .data = &k1_pcie_device_data},

In addition to the missing space that Andy mentioned,
adding a comma means the line won't need to change
when you add another entry to the array.

>   	{ }
>   };
>   


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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-09  4:00 ` [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support Inochi Amaoto
  2026-07-09  4:09   ` sashiko-bot
  2026-07-09  7:16   ` Andy Shevchenko
@ 2026-07-10 16:01   ` Alex Elder
  2 siblings, 0 replies; 30+ messages in thread
From: Alex Elder @ 2026-07-10 16:01 UTC (permalink / raw)
  To: Inochi Amaoto, Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

On 7/8/26 11:00 PM, Inochi Amaoto wrote:
> The PCIe controller on Spacemit K3 may use multiple PHYs at the

s/use/uses/

> same time. The feature is not support by the current driver.

s/support/supported/

> So extend the PHY definition to support multiple PHY handles.
> 
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> ---
>   drivers/pci/controller/dwc/pcie-spacemit-k1.c | 70 ++++++++++++++++---
>   1 file changed, 59 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> index f6ae8ff3589a..e22ecbd09579 100644
> --- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> +++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> @@ -55,12 +55,14 @@ struct k1_pcie_device_data {
>   	const struct dw_pcie_host_ops *host_ops;
>   	const struct dw_pcie_ops *ops;
>   	int (*parse_port)(struct k1_pcie *k1);
> +	unsigned int max_phy_count;

Is the name "max_phy_count" meant to suggest that there
could be fewer "actual" PHYs than the number provided in
this field?  If not--if it is simply "the number of PHYs
this platform uses"--then just call this phy_count.

>   };
>   
>   struct k1_pcie {
>   	struct dw_pcie pci;
>   	const struct k1_pcie_device_data *data;
> -	struct phy *phy;
> +	struct phy **phy;
> +	unsigned int phy_count;

If this is always the same as what's in data->max_phy_count,
you don't need to replicate the value here (since you're
also keeping the data pointer in this structure).  (But it
looks like it might be less than max_phy_count.)

I believe I suggested making this structure use a flexible
array member for the PHYs.  If that's possible, it should
go at the end of the structure, and the way you allocate
it needs to change.

>   	void __iomem *link;
>   	struct regmap *pmu;	/* Errors ignored; MMIO-backed regmap */
>   	u32 pmu_off;
> @@ -119,6 +121,54 @@ static void k1_pcie_disable_resources(struct k1_pcie *k1)
>   	clk_bulk_disable_unprepare(ARRAY_SIZE(pci->app_clks), pci->app_clks);
>   }
>   
> +static int k1_pcie_get_phy_handle(struct k1_pcie *k1, struct device_node *node)

I would call this k1_pci_get_phy_handles() (or perhaps
just k1_pci_get_phys()).  Or even k1_pci_phy_get_all().
The name you have seems like you're just getting one handle.

> +{
> +	const struct k1_pcie_device_data *data = k1->data;
> +	struct device *dev = k1->pci.dev;
> +	unsigned int i;
> +
> +	k1->phy = devm_kmalloc_array(dev, data->max_phy_count,
> +				     sizeof(*k1->phy), GFP_KERNEL);

Use kzalloc not kmalloc.  Even if you're initializing all fields
now, a future change might not (and in that case having it zeroed
is safest).

Also, if you find fewer than max_phy_count PHYs, I think it
would be better to only allocate as many needed.  If you
used a flexible array size, you would need to count the
number of entries before allocating it.  It would require
changing the structure a bit--providing a single function
that would allocate the k1_pcie structure after doing that,
and most likely initializing the phy array within the same
function.

> +	if (!k1->phy)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < data->max_phy_count; i++) {
> +		k1->phy[i] = devm_of_phy_get_by_index(dev, node, i);
> +		if (IS_ERR(k1->phy[i])) {

If this returns -ENODEV, you are done getting PHYs.  So
max_phy_count could be more than the "actual" number.

Is that reasonable?  You indicate that at least one PHY
must be found below, but is it OK for a platform to
define fewer than some expected number of PHYs?

(Maybe it is.)

> +			if (PTR_ERR(k1->phy[i]) == -ENODEV)
> +				break;
> +
> +			return PTR_ERR(k1->phy[i]);
> +		}
> +	}
> +
> +	k1->phy_count = i;
> +	if (k1->phy_count == 0)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int k1_pcie_enable_phy(struct k1_pcie *k1)

I would call this k1_pcie_enable_phys().  But actually,
because what you're calling within this is phy_init(),
I'd probably call it k1_pcie_init_phys(), or possibly
k1_pcie_phy_init_all().

> +{
> +	unsigned int i;
> +	int ret;
> +
> +	for (i = 0; i < k1->phy_count; i++) {
> +		ret = phy_init(k1->phy[i]);
> +		if (ret)
> +			goto err_phy;
> +	}
> +
> +	return 0;
> +
> +err_phy:
> +	while (i--)
> +		phy_exit(k1->phy[i]);
> +
> +	return ret;
> +}
> +
>   /* FIXME: Disable ASPM L1 to avoid errors reported on some NVMe drives */
>   static void k1_pcie_disable_aspm_l1(struct k1_pcie *k1)
>   {
> @@ -174,7 +224,7 @@ static int k1_pcie_init(struct dw_pcie_rp *pp)
>   	 */
>   	regmap_set_bits(k1->pmu, reset_ctrl, DEVICE_TYPE_RC | PCIE_AUX_PWR_DET);
>   
> -	ret = phy_init(k1->phy);
> +	ret = k1_pcie_enable_phy(k1);
>   	if (ret) {
>   		k1_pcie_disable_resources(k1);
>   
> @@ -194,12 +244,14 @@ static void k1_pcie_deinit(struct dw_pcie_rp *pp)
>   {
>   	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
>   	struct k1_pcie *k1 = to_k1_pcie(pci);
> +	int i;
>   
>   	/* Assert fundamental reset (drive PERST# low) */
>   	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CLK_RESET_CONTROL,
>   			PCIE_RC_PERST);
>   
> -	phy_exit(k1->phy);
> +	for (i = 0; i < k1->phy_count; i++)
> +		phy_exit(k1->phy[i]);

Please create an inverse of k1_pcie_enable_phy(), like
k1_pcie_disable_phy(), to encapsulate this code.

>   
>   	k1_pcie_disable_resources(k1);
>   }
> @@ -266,23 +318,18 @@ static int k1_pcie_parse_port(struct k1_pcie *k1)
>   {
>   	struct device *dev = k1->pci.dev;
>   	struct device_node *root_port;
> -	struct phy *phy;
> +	int ret;
>   
>   	/* We assume only one root port */

Maybe you could get and put the root_port within
k1_pcie_get_phy_handle(), since that's the only
place it's needed.

					-Alex

>   	root_port = of_get_next_available_child(dev_of_node(dev), NULL);
>   	if (!root_port)
>   		return -EINVAL;
>   
> -	phy = devm_of_phy_get(dev, root_port, NULL);
> +	ret = k1_pcie_get_phy_handle(k1, root_port);
>   
>   	of_node_put(root_port);
>   
> -	if (IS_ERR(phy))
> -		return PTR_ERR(phy);
> -
> -	k1->phy = phy;
> -
> -	return 0;
> +	return ret;
>   }
>   
>   static int k1_pcie_probe(struct platform_device *pdev)
> @@ -358,6 +405,7 @@ static const struct k1_pcie_device_data k1_pcie_device_data = {
>   	.host_ops	= &k1_pcie_host_ops,
>   	.ops		= &k1_pcie_ops,
>   	.parse_port	= k1_pcie_parse_port,
> +	.max_phy_count	= 1,
>   };
>   
>   static const struct of_device_id k1_pcie_of_match_table[] = {


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

* Re: [PATCH v4 3/6] PCI: spacemit-k1: Add device id update helper
  2026-07-09  4:00 ` [PATCH v4 3/6] PCI: spacemit-k1: Add device id update helper Inochi Amaoto
  2026-07-09  4:06   ` sashiko-bot
@ 2026-07-10 16:01   ` Alex Elder
  1 sibling, 0 replies; 30+ messages in thread
From: Alex Elder @ 2026-07-10 16:01 UTC (permalink / raw)
  To: Inochi Amaoto, Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

On 7/8/26 11:00 PM, Inochi Amaoto wrote:
> Both K1 and K3 needs to set vendor id and device id, add a helper function

s/needs/need/

> to simplify this.

I think someone might have commented on this, but I expected to find
that the next patch would fill in the code that's needed to support
K3, but that patch is at the end of your series.

The reason I say it here is that I wondered while looking at this
one why it was needed to create this helper function.  I now know
that k3_pcie_init() will call it (but I had to find that in the
last patch, which was later than I expected).

Your series should start with DT binding changes, then code changes,
and (often) end with DTS changes.

Anyway, this looks good.

Reviewed-by: Alex Elder <elder@riscstar.com>

> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> ---
>   drivers/pci/controller/dwc/pcie-spacemit-k1.c | 17 +++++++++++++----
>   1 file changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> index e22ecbd09579..31aac056b68e 100644
> --- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> +++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> @@ -56,6 +56,7 @@ struct k1_pcie_device_data {
>   	const struct dw_pcie_ops *ops;
>   	int (*parse_port)(struct k1_pcie *k1);
>   	unsigned int max_phy_count;
> +	unsigned int device_id;
>   };
>   
>   struct k1_pcie {
> @@ -186,6 +187,16 @@ static void k1_pcie_disable_aspm_l1(struct k1_pcie *k1)
>   	dw_pcie_dbi_ro_wr_dis(pci);
>   }
>   
> +static void k1_pcie_set_device_id(struct k1_pcie *k1)
> +{
> +	struct dw_pcie *pci = &k1->pci;
> +
> +	dw_pcie_dbi_ro_wr_en(pci);
> +	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, PCI_VENDOR_ID_SPACEMIT);
> +	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, k1->data->device_id);
> +	dw_pcie_dbi_ro_wr_dis(pci);
> +}
> +
>   static int k1_pcie_init(struct dw_pcie_rp *pp)
>   {
>   	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> @@ -201,10 +212,7 @@ static int k1_pcie_init(struct dw_pcie_rp *pp)
>   		return ret;
>   
>   	/* Set the PCI vendor and device ID */
> -	dw_pcie_dbi_ro_wr_en(pci);
> -	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, PCI_VENDOR_ID_SPACEMIT);
> -	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, PCI_DEVICE_ID_SPACEMIT_K1);
> -	dw_pcie_dbi_ro_wr_dis(pci);
> +	k1_pcie_set_device_id(k1);
>   
>   	/*
>   	 * Start by asserting fundamental reset (drive PERST# low).  The
> @@ -406,6 +414,7 @@ static const struct k1_pcie_device_data k1_pcie_device_data = {
>   	.ops		= &k1_pcie_ops,
>   	.parse_port	= k1_pcie_parse_port,
>   	.max_phy_count	= 1,
> +	.device_id	= PCI_DEVICE_ID_SPACEMIT_K1,
>   };
>   
>   static const struct of_device_id k1_pcie_of_match_table[] = {


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

* Re: [PATCH v4 4/6] dt-bindings: PCI: snps,dw-pcie: Add msi-parent for MSI handle check
  2026-07-09  4:00 ` [PATCH v4 4/6] dt-bindings: PCI: snps,dw-pcie: Add msi-parent for MSI handle check Inochi Amaoto
  2026-07-09  4:06   ` sashiko-bot
@ 2026-07-10 16:01   ` Alex Elder
  1 sibling, 0 replies; 30+ messages in thread
From: Alex Elder @ 2026-07-10 16:01 UTC (permalink / raw)
  To: Inochi Amaoto, Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

On 7/8/26 11:00 PM, Inochi Amaoto wrote:
> The IMSIC device on RISC-V based system does not require ID
> remapping for MSI. So this device only needs "msi-parent"
> property for IMSIC-based SoC, and the "msi-map" is not a
> necessary property.
> 
> Add new condition for MSI handling on IMSIC based SoC.
> 
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> Acked-by: Rob Herring (Arm) <robh@kernel.org>

I have nothing to add here.	-Alex

> ---
>   Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml | 7 +++++--
>   1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
> index b3216141881c..91bbbc8924f6 100644
> --- a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
> +++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
> @@ -27,8 +27,11 @@ allOf:
>     - $ref: /schemas/pci/snps,dw-pcie-common.yaml#
>     - if:
>         not:
> -        required:
> -          - msi-map
> +        anyOf:
> +          - required:
> +              - msi-map
> +          - required:
> +              - msi-parent
>       then:
>         properties:
>           interrupt-names:


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

* Re: [PATCH v4 5/6] dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller
  2026-07-09  4:00 ` [PATCH v4 5/6] dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller Inochi Amaoto
  2026-07-09  4:09   ` sashiko-bot
@ 2026-07-10 16:01   ` Alex Elder
  1 sibling, 0 replies; 30+ messages in thread
From: Alex Elder @ 2026-07-10 16:01 UTC (permalink / raw)
  To: Inochi Amaoto, Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

On 7/8/26 11:00 PM, Inochi Amaoto wrote:
> Add binding support for the PCIe controller on the SpacemiT K3 SoC.
> This controller is almost a standard Synopsys DesignWare PCIe IP,
> with some extra link and reset state control.
> 
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>

This looks OK to me.  What I see is that K3 does not require
the interrupts and interrupt-names properties, allows up to
six PHYs (not just one), and adds a dbi2 register that is not
used by K1.

I might have missed it, but I don't see where the dbi2 register
is used by the K3 code you have added.  In pcie-designware.c,
I see that if no "dbi2" resource is found, memory at offset
4096 from the "dbi" base is used.  Does that apply for K3?
If so, maybe there's no need to define dbi2.

					-Alex

> ---
>   .../bindings/pci/spacemit,k1-pcie-host.yaml   | 50 ++++++++++++++++---
>   1 file changed, 43 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml b/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml
> index c4c00b5fcdc0..54817d6fd9af 100644
> --- a/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml
> +++ b/Documentation/devicetree/bindings/pci/spacemit,k1-pcie-host.yaml
> @@ -14,26 +14,29 @@ description: >
>     PCIe IP.  The controller uses the DesignWare built-in MSI interrupt
>     controller, and supports 256 MSIs.
>   
> -allOf:
> -  - $ref: /schemas/pci/snps,dw-pcie.yaml#
> -
>   properties:
>     compatible:
> -    const: spacemit,k1-pcie
> +    enum:
> +      - spacemit,k1-pcie
> +      - spacemit,k3-pcie
>   
>     reg:
> +    minItems: 4
>       items:
>         - description: DesignWare PCIe registers
>         - description: ATU address space
>         - description: PCIe configuration space
>         - description: Link control registers
> +      - description: Data Bus Interface (DBI) shadow registers.
>   
>     reg-names:
> +    minItems: 4
>       items:
>         - const: dbi
>         - const: atu
>         - const: config
>         - const: link
> +      - const: dbi2
>   
>     clocks:
>       items:
> @@ -66,6 +69,8 @@ properties:
>     interrupt-names:
>       const: msi
>   
> +  msi-parent: true
> +
>     spacemit,apmu:
>       $ref: /schemas/types.yaml#/definitions/phandle-array
>       description:
> @@ -84,7 +89,8 @@ patternProperties:
>   
>       properties:
>         phys:
> -        maxItems: 1
> +        minItems: 1
> +        maxItems: 6
>   
>         vpcie3v3-supply:
>           description:
> @@ -96,13 +102,43 @@ patternProperties:
>   
>       unevaluatedProperties: false
>   
> +allOf:
> +  - $ref: /schemas/pci/snps,dw-pcie.yaml#
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: spacemit,k1-pcie
> +    then:
> +      properties:
> +        reg:
> +          maxItems: 4
> +
> +        reg-names:
> +          maxItems: 4
> +
> +      patternProperties:
> +        '^pcie@':
> +          properties:
> +            phys:
> +              maxItems: 1
> +
> +      required:
> +        - interrupts
> +        - interrupt-names
> +    else:
> +      properties:
> +        reg:
> +          minItems: 5
> +
> +        reg-names:
> +          minItems: 5
> +
>   required:
>     - clocks
>     - clock-names
>     - resets
>     - reset-names
> -  - interrupts
> -  - interrupt-names
>     - spacemit,apmu
>   
>   unevaluatedProperties: false


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

* Re: [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support
  2026-07-09  4:00 ` [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support Inochi Amaoto
  2026-07-09  4:12   ` sashiko-bot
  2026-07-09  7:21   ` Andy Shevchenko
@ 2026-07-10 16:01   ` Alex Elder
  2 siblings, 0 replies; 30+ messages in thread
From: Alex Elder @ 2026-07-10 16:01 UTC (permalink / raw)
  To: Inochi Amaoto, Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Siddharth Vadapalli, Andy Shevchenko, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel
  Cc: linux-pci, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan, Longbin Li

On 7/8/26 11:00 PM, Inochi Amaoto wrote:
> The PCIe controller on Spacemit K3 is almost a standard Synopsys
> DesignWare PCIe IP with extra link and reset control. Unlike
> the PCIe controller on K1, this controller supports external MSI
> interrupt controller and can use multiple PHYs at the same time.
> 
> Add driver to support PCIe controller on Spacemit K3 PCIe.

I think it would be good to summarize how the K3 differs from
the K1 here as well, since they're sharing code.  It looks
like it supports up to 6 PHYs, not just 1 (as the K1 does).

> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> ---
>   drivers/pci/controller/dwc/Kconfig            |   4 +-
>   drivers/pci/controller/dwc/pcie-spacemit-k1.c | 126 ++++++++++++++++++
>   2 files changed, 128 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
> index aa0b784c85b4..dacbac5cc35c 100644
> --- a/drivers/pci/controller/dwc/Kconfig
> +++ b/drivers/pci/controller/dwc/Kconfig
> @@ -440,7 +440,7 @@ config PCIE_SOPHGO_DW
>   	  Sophgo SoCs.
>   
>   config PCIE_SPACEMIT_K1
> -	tristate "SpacemiT K1 PCIe controller (host mode)"
> +	tristate "SpacemiT PCIe controller (host mode)"
>   	depends on ARCH_SPACEMIT || COMPILE_TEST
>   	depends on HAS_IOMEM
>   	select PCIE_DW_HOST
> @@ -448,7 +448,7 @@ config PCIE_SPACEMIT_K1
>   	default ARCH_SPACEMIT
>   	help
>   	  Enables support for the DesignWare based PCIe controller in
> -	  the SpacemiT K1 SoC operating in host mode.  Three controllers
> +	  the SpacemiT SoC operating in host mode. Three controllers
>   	  are available on the K1 SoC; the first of these shares a PHY
>   	  with a USB 3.0 host controller (one or the other can be used).
>   
> diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> index 31aac056b68e..680acc93f539 100644
> --- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> +++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> @@ -23,6 +23,7 @@
>   
>   #define PCI_VENDOR_ID_SPACEMIT		0x201f
>   #define PCI_DEVICE_ID_SPACEMIT_K1	0x0001
> +#define PCI_DEVICE_ID_SPACEMIT_K3	0x0002
>   
>   /* Offsets and field definitions for link management registers */
>   #define K1_PHY_AHB_IRQ_EN			0x0000
> @@ -32,8 +33,18 @@
>   #define SMLH_LINK_UP			BIT(1)
>   #define RDLH_LINK_UP			BIT(12)
>   
> +#define INTR_STATUS				0x0010

This register offset should probably be named K3_PHY_INTR_STATUS
(or maybe it's just K3_INTR_STATUS?).  I see that INTR_ENABLE
doesn't have a prefix, and I don't know why--that should have
a similar name.  (Please fix that in your next version as well;
I think it's OK to included it with this patch with a simple
mention in the patch description.)

> +
>   #define INTR_ENABLE				0x0014
>   #define MSI_CTRL_INT			BIT(11)
> +#define RDLH_LINK_UP_INT		BIT(20)
> +
> +#define K3_PHY_AHB_IRQSTATUS_INTX		0x0008

So is this enabling INTX support?  If so, you should do that
first in a separate patch that only applies to K1 (and that
should be verified to work correctly).  If all you're doing
is ensuring the status is cleared, that's OK here, but if
you don't enable it I'm not sure it matters.

> +
> +#define K3_ADDR_INTR_STATUS1			0x0018
> +
> +#define K3_CACHE_MSTR_AWCACHE_MODE	GENMASK(14, 11)
> +#define K3_CACHE_MSTR_AWCACHE_BEHAVIOR	0xf
>   
>   /* Some controls require APMU regmap access */
>   #define SYSCON_APMU			"spacemit,apmu"
> @@ -48,6 +59,9 @@
>   
>   #define PCIE_CONTROL_LOGIC			0x0004
>   #define PCIE_SOFT_RESET			BIT(0)
> +#define PCIE_PERSTN_OE			BIT(24)
> +#define PCIE_PERSTN_OUT			BIT(25)
> +#define PCIE_IGNORE_PERSTN		BIT(31)
>   
>   struct k1_pcie;
>   
> @@ -340,6 +354,109 @@ static int k1_pcie_parse_port(struct k1_pcie *k1)
>   	return ret;
>   }
>   

I ask a few questions in this function; I'm basically
asking "are you *sure* this must be different for K3
than K1?"  Because for the most part this function looks
very similar to k1_pcie_init().

> +static int k3_pcie_init(struct dw_pcie_rp *pp)
> +{
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> +	struct k1_pcie *k1 = to_k1_pcie(pci);
> +	u32 reset_ctrl = k1->pmu_off + PCIE_CLK_RESET_CONTROL;
> +	u32 val;
> +	int ret;
> +
> +	regmap_clear_bits(k1->pmu, reset_ctrl, LTSSM_EN);

Would it be OK to clear this bit in the reset control
register for K1 as well?

> +
> +	k1_pcie_toggle_soft_reset(k1);
> +
> +	ret = k1_pcie_enable_resources(k1);
> +	if (ret)
> +		return ret;
> +
> +	regmap_set_bits(k1->pmu, reset_ctrl, PCIE_AUX_PWR_DET);
> +	regmap_clear_bits(k1->pmu, reset_ctrl, APP_HOLD_PHY_RST);
> +
> +	ret = k1_pcie_enable_phy(k1);
> +	if (ret) {
> +		k1_pcie_disable_resources(k1);
> +		return ret;
> +	}
> +

The handling of PERSTN looks different for K3 than K1.  Could you
implement a helper function that abstracts the differences?

I don't really understand what's happening here, but if it's
comparable to this for K1:

         /* Deassert fundamental reset (drive PERST# high) */
         regmap_clear_bits(k1->pmu, reset_ctrl, PCIE_RC_PERST);

...then a callback function (similar to parse_port) in the device
data might be able to be called for both platforms, allowing
the init function to be common for both.

> +	/* K3: Set IGNORE_PERSTN and drive PERSTN_OE high (assert reset) */
> +	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CONTROL_LOGIC,
> +			PCIE_IGNORE_PERSTN | PCIE_PERSTN_OE | PCIE_PERSTN_OUT);
> +	usleep_range(1000, 2000);
> +	regmap_clear_bits(k1->pmu, k1->pmu_off + PCIE_CONTROL_LOGIC, PCIE_PERSTN_OUT);
> +
> +	msleep(PCIE_T_PVPERL_MS);
> +
> +	/*
> +	 * Put the controller in root complex mode, and indicate that
> +	 * Vaux (3.3v) is present.

Here too, you could abstract what's happening and that might
allow the init function to be common for both (all) platforms.

> +	 */
> +	regmap_set_bits(k1->pmu, k1->pmu_off + PCIE_CONTROL_LOGIC,
> +			PCIE_PERSTN_OUT | PCIE_PERSTN_OE);
> +
> +	val = dw_pcie_readl_dbi(pci, GEN3_EQ_CONTROL_OFF);
> +	val = u32_replace_bits(val, BIT(7),
> +			       GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC);
> +	dw_pcie_writel_dbi(pci, GEN3_EQ_CONTROL_OFF, val);
> +
> +	k1_pcie_set_device_id(k1);

This is done earlier in k1_pcie_init().  Could it be done at the
same time for both platforms?

> +
> +	/* Finally, as a workaround, disable ASPM L1 */
> +	k1_pcie_disable_aspm_l1(k1);
> +
> +	return 0;
> +}
> +
> +static int k3_pcie_msi_host_init(struct dw_pcie_rp *pp)

Why is this needed for K3, but not for K1?  Does this
enable any functionality that K1 could use and benefit
from?

> +{
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> +	u32 val;
> +
> +	dw_pcie_dbi_ro_wr_en(pci);
> +
> +	val = dw_pcie_readl_dbi(pci, COHERENCY_CONTROL_3_OFF);
> +	val = u32_replace_bits(val, K3_CACHE_MSTR_AWCACHE_BEHAVIOR,
> +			       K3_CACHE_MSTR_AWCACHE_MODE);
> +	dw_pcie_writel_dbi(pci, COHERENCY_CONTROL_3_OFF, val);
> +
> +	dw_pcie_dbi_ro_wr_dis(pci);
> +
> +	return 0;
> +}
> +
> +static const struct dw_pcie_host_ops k3_pcie_host_ops = {
> +	.init		= k3_pcie_init,
> +	.deinit		= k1_pcie_deinit,
> +	.msi_init	= k3_pcie_msi_host_init,
> +};
> +
> +static const struct dw_pcie_ops k3_pcie_ops = {

This is identical to k1_pcie_ops, so isn't needed.

> +	.link_up	= k1_pcie_link_up,
> +	.start_link	= k1_pcie_start_link,
> +	.stop_link	= k1_pcie_stop_link,
> +};
> +
> +static void k3_pcie_clear_irq_status(struct k1_pcie *k1,
> +				     u32 *status0, u32 *status1, u32 *status2)

I don't see any value in this helper function, at
least not based on how it's used now.  It is used
exactly once, to clear (by writing) three interrupt
status registers.  Just do that inline.

Even if you want to use this helper function in a
second place (when handling the itnerrupt), don't
pass in these status arguments, they're not needed
in the caller.  Just define them here.

Also you could read/write each register, and use
a single local variable (status) to hold the value
read and written.

> +{
> +	*status0 = readl_relaxed(k1->link + K3_PHY_AHB_IRQSTATUS_INTX);
> +	*status1 = readl_relaxed(k1->link + INTR_STATUS);
> +	*status2 = readl_relaxed(k1->link + K3_ADDR_INTR_STATUS1);
> +
> +	writel_relaxed(*status0, k1->link + K3_PHY_AHB_IRQSTATUS_INTX);
> +	writel_relaxed(*status1, k1->link + INTR_STATUS);
> +	writel_relaxed(*status2, k1->link + K3_ADDR_INTR_STATUS1);
> +}
> +
> +static int k3_pcie_parse_port(struct k1_pcie *k1)
> +{
> +	u32 status0, status1, status2;
> +
> +	k3_pcie_clear_irq_status(k1, &status0, &status1, &status2);

Is it really necessary to clear the IRQ status *only* for K3?
It seems like it would be a good idea (or at least harmless)
to do it for K1 as well.  And in that case, it should just be
added to the existing k1_pcie_parse_port() function.

> +
> +	return k1_pcie_parse_port(k1);
> +}
> +
>   static int k1_pcie_probe(struct platform_device *pdev)
>   {
>   	const struct k1_pcie_device_data *data;
> @@ -417,8 +534,17 @@ static const struct k1_pcie_device_data k1_pcie_device_data = {
>   	.device_id	= PCI_DEVICE_ID_SPACEMIT_K1,
>   };
>   
> +static const struct k1_pcie_device_data k3_pcie_device_data = {
> +	.host_ops	= &k3_pcie_host_ops,
> +	.ops		= &k3_pcie_ops,

I think ops could just point to k1_pcie_ops here.

					-Alex

> +	.parse_port	= k3_pcie_parse_port,
> +	.max_phy_count	= 6,
> +	.device_id	= PCI_DEVICE_ID_SPACEMIT_K3,
> +};
> +
>   static const struct of_device_id k1_pcie_of_match_table[] = {
>   	{ .compatible = "spacemit,k1-pcie", .data = &k1_pcie_device_data},
> +	{ .compatible = "spacemit,k3-pcie", .data = &k3_pcie_device_data},
>   	{ }
>   };
>   


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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-10 10:55         ` Inochi Amaoto
  2026-07-10 12:42           ` Alex Elder
@ 2026-07-11 12:44           ` Andy Shevchenko
  1 sibling, 0 replies; 30+ messages in thread
From: Andy Shevchenko @ 2026-07-11 12:44 UTC (permalink / raw)
  To: Inochi Amaoto
  Cc: Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Alex Elder, Siddharth Vadapalli, Vidya Sagar,
	Neil Armstrong, Gustavo Pimentel, linux-pci, devicetree,
	linux-kernel, linux-riscv, spacemit, Yixun Lan, Longbin Li

On Fri, Jul 10, 2026 at 06:55:10PM +0800, Inochi Amaoto wrote:
> On Fri, Jul 10, 2026 at 11:07:40AM +0300, Andy Shevchenko wrote:
> > On Fri, Jul 10, 2026 at 09:57:05AM +0800, Inochi Amaoto wrote:
> > > On Thu, Jul 09, 2026 at 10:16:28AM +0300, Andy Shevchenko wrote:
> > > > On Thu, Jul 09, 2026 at 12:00:22PM +0800, Inochi Amaoto wrote:

...

> > > > > +	k1->phy_count = i;
> > > > > +	if (k1->phy_count == 0)
> > > > > +		return -EINVAL;
> > > > > +
> > > > > +	return 0;
> > > > 
> > > > This doesn't seem correct to me, I would expect phy_count to be assigned only
> > > > when it's valid. (Yes, perhaps 0 is the same as it was, but semantically it's
> > > > different 0 in this case.)
> > > 
> > > I guess you think 0 is a valid number? I can not understand what you thing
> > > Assign this to 0 if there is no phy is fine to me, which shows there is 0
> > > vaild phy found.
> > 
> > Isn't it already 0? Semantically code is wrong in a flow (not in the result).
> 
> In fact it is already 0 here. But I am not understand why you thing is wrong.
> Could you explain it in detail? (Maybe you think it is not good to return 
> -EINVAL?)

You rewrite 0 by 0, but the fact of the rewriting is inaccuracy.
We should not rewrite the default (whatever it is) with 0 count
as semantically they are different cases. The rule of thumb, we
don't assign values in case of errors, we leave them as is and
it's user / caller responsibility to assign the default and handle
errors properly. This is simple layering violation.

Your code should be

	if (i == 0)
		return -EINVAL;

	k1->phy_count = i;
	return 0;

> > > > See also above. Do we have some PHY API that just counts provided PHYs?
> > > > If not, that what you should probably add first, before this patch.
> > > 
> > > I have not found any api for this. But the actual problem is, how the api
> > > is designed. I have checked both the array bulk api for reset and clock,
> > > it seems like it is much more than this patch...
> > 
> > Yeah, I looked at the phy-core and I think it will be hard to implement.
> > So, the idea is then is to reallocate the pointer each time you get a new PHY.
> > In this case the phy_count will reflect the actual memory consumption by phy.
> 
> Emmm, I think it is kind of buggy and not necessary. In most case
> this array is not long actually, so allocate some pointer should be
> fine and be an acceptable cost.

Then the counted_by will be incorrect as it may access valid memory, but
unused by the driver.

...

> > > > > +	for (i = 0; i < k1->phy_count; i++)
> > > > 
> > > > 	for (unsigned int i = 0; i < k1->phy_count; i++)
> > > > 
> > > 
> > > I agree with the unsigned int, but I guess this definition is not
> > > allowed in linux.
> > 
> > It's allowed and it's encouraged even by Linus. As long as iterator is local,
> > use this syntax sugar and reduce its scope. It hardens the code.
> 
> Could you give me a reference url to check,

Sure, there are two (one for integers and one for pointers)
https://lore.kernel.org/lkml/CAHk-=wiCOTW5UftUrAnvJkr6769D29tF7Of79gUjdQHS_TkF5A@mail.gmail.com/
https://lore.kernel.org/lkml/CAHk-=wgy8p4is8ApEQCT5NS7XFb+NXeo-TKz7jRRZVksLLBSrQ@mail.gmail.com/

> I have not found this on the coding-style.
> https://www.kernel.org/doc/html/latest/process/coding-style.html

Feel free to update the documentation.

> > > > > +		phy_exit(k1->phy[i]);

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-10 12:42           ` Alex Elder
@ 2026-07-11 13:01             ` Andy Shevchenko
  0 siblings, 0 replies; 30+ messages in thread
From: Andy Shevchenko @ 2026-07-11 13:01 UTC (permalink / raw)
  To: Alex Elder
  Cc: Inochi Amaoto, Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Siddharth Vadapalli, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel, linux-pci, devicetree, linux-kernel,
	linux-riscv, spacemit, Yixun Lan, Longbin Li

On Fri, Jul 10, 2026 at 07:42:18AM -0500, Alex Elder wrote:
> On 7/10/26 5:55 AM, Inochi Amaoto wrote:
> > > > > > +	k1->phy_count = i;
> > > > > > +	if (k1->phy_count == 0)
> > > > > > +		return -EINVAL;
> > > > > > +
> > > > > > +	return 0;
> > > > > This doesn't seem correct to me, I would expect phy_count to be assigned only
> > > > > when it's valid. (Yes, perhaps 0 is the same as it was, but semantically it's
> > > > > different 0 in this case.)
> > > > I guess you think 0 is a valid number? I can not understand what you thing
> > > > Assign this to 0 if there is no phy is fine to me, which shows there is 0
> > > > vaild phy found.
> > > Isn't it already 0? Semantically code is wrong in a flow (not in the result).
> > > 
> > In fact it is already 0 here. But I am not understand why you thing is wrong.
> > Could you explain it in detail? (Maybe you think it is not good to return
> > -EINVAL?)
> 
> What Andy is saying is that assigning the value of phy_count
> before checking that it is valid is not the expected order of
> things.
> 
> The point is about best practice, not about the end result.
> 
> Best practice would be "don't touch anything if the return
> value will indicate an error."

Yes, precisely.

> And therefore, better coding practice would be to check for
> a bad value, and only after that has been done should you
> assign the k1->phy_count value.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support
  2026-07-10 12:51     ` Alex Elder
@ 2026-07-11 13:04       ` Andy Shevchenko
  0 siblings, 0 replies; 30+ messages in thread
From: Andy Shevchenko @ 2026-07-11 13:04 UTC (permalink / raw)
  To: Alex Elder
  Cc: Inochi Amaoto, Jingoo Han, Manivannan Sadhasivam, Bjorn Helgaas,
	Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Christian Bruel,
	Frank Li, Nam Cao, Qiang Yu, Krishna Chaitanya Chundru,
	Xincheng Zhang, Siddharth Vadapalli, Vidya Sagar, Neil Armstrong,
	Gustavo Pimentel, linux-pci, devicetree, linux-kernel,
	linux-riscv, spacemit, Yixun Lan, Longbin Li

On Fri, Jul 10, 2026 at 07:51:05AM -0500, Alex Elder wrote:
> On 7/9/26 2:16 AM, Andy Shevchenko wrote:

...

> > > +		if (IS_ERR(k1->phy[i])) {
> > > +			if (PTR_ERR(k1->phy[i]) == -ENODEV)
> > > +				break;
> > > +
> > > +			return PTR_ERR(k1->phy[i]);
> > > +		}
> > 		if (PTR_ERR(k1->phy[i]) == -ENODEV)
> > 			break;
> > 		if (IS_ERR(k1->phy[i]))
> > 			return PTR_ERR(k1->phy[i]);
> 
> I'm not sure this is a huge improvement.  Checking IS_ERR()
> before using PTR_ERR() is comforting (a little along the
> lines of the other issue you mentioned--assigning a result
> before checking for an error).  Anyway, it's a little bit
> of an ugly construct no matter how you do it.

Yeah...

> Here's another possible way to do it.
> 
> 	k1->phy[i] = devm_of_phy_get_by_index(dev, node, i);
> 	if (!IS_ERR(k1->phy[i]))
> 		continue;
> 
> 	ret = PTR_ERR(k1->phy[i]);
> 	if (ret == -ENODEV)
> 		break;

In this case one can simplify to

	k1->phy[i] = devm_of_phy_get_by_index(dev, node, i);
	ret = PTR_ERR_OR_ZERO(k1->phy[i]);
	if (ret == -ENODEV)
		break;
	else if (ret)
		return ret;

-- 
With Best Regards,
Andy Shevchenko



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

end of thread, other threads:[~2026-07-11 13:04 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-09  4:00 [PATCH v4 0/6] riscv: spacemit: Add PCIe RC controller support for K3 Inochi Amaoto
2026-07-09  4:00 ` [PATCH v4 1/6] PCI: spacemit-k1: Add device data support Inochi Amaoto
2026-07-09  4:05   ` sashiko-bot
2026-07-09  7:09   ` Andy Shevchenko
2026-07-10 16:01   ` Alex Elder
2026-07-09  4:00 ` [PATCH v4 2/6] PCI: spacemit-k1: Add multiple PHY handles support Inochi Amaoto
2026-07-09  4:09   ` sashiko-bot
2026-07-09  7:16   ` Andy Shevchenko
2026-07-10  1:57     ` Inochi Amaoto
2026-07-10  8:07       ` Andy Shevchenko
2026-07-10 10:55         ` Inochi Amaoto
2026-07-10 12:42           ` Alex Elder
2026-07-11 13:01             ` Andy Shevchenko
2026-07-11 12:44           ` Andy Shevchenko
2026-07-10 12:51     ` Alex Elder
2026-07-11 13:04       ` Andy Shevchenko
2026-07-10 16:01   ` Alex Elder
2026-07-09  4:00 ` [PATCH v4 3/6] PCI: spacemit-k1: Add device id update helper Inochi Amaoto
2026-07-09  4:06   ` sashiko-bot
2026-07-10 16:01   ` Alex Elder
2026-07-09  4:00 ` [PATCH v4 4/6] dt-bindings: PCI: snps,dw-pcie: Add msi-parent for MSI handle check Inochi Amaoto
2026-07-09  4:06   ` sashiko-bot
2026-07-10 16:01   ` Alex Elder
2026-07-09  4:00 ` [PATCH v4 5/6] dt-bindings: PCI: spacemit: Introduce Spacemit K3 PCIe host controller Inochi Amaoto
2026-07-09  4:09   ` sashiko-bot
2026-07-10 16:01   ` Alex Elder
2026-07-09  4:00 ` [PATCH v4 6/6] PCI: spacemit-k1: Add Spacemit K3 PCIe host controller support Inochi Amaoto
2026-07-09  4:12   ` sashiko-bot
2026-07-09  7:21   ` Andy Shevchenko
2026-07-10 16:01   ` Alex Elder

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox