All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC
@ 2026-09-13  4:23 Eric Chung
  2026-09-13  4:23 ` [PATCH v2 1/4] phy: spacemit: add K1 PCIe/USB3 combo PHY driver Eric Chung
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Eric Chung @ 2026-09-13  4:23 UTC (permalink / raw)
  To: u-boot-spacemit, u-boot, u-boot
  Cc: Tom Rini, Tim Ouyang, Leo Liang, Scott Bambrough, Eric Chung,
	Neil Armstrong, David Lechner, Julien Stephan, Johan Jonker,
	Siu Ming Tong, Lucien.Jheng, Huan Zhou, Michal Simek,
	Pranav Sanwal, Raymond Mao, Yixun Lan

Signed-off-by: Eric Chung <eric.chung@riscstar.com>
---
Changes in v2:
- dts: Rebase on upstream DTS. So drop the changes in overlay DTS.
- pci: Find the phy by index instead.
- maintainer: Add the driver in the Spacemit MAINTAINER entry.
- Link to v1: https://patch.msgid.link/20260705-pci-v1-0-beca83440a27@riscstar.com

To: u-boot@lists.u-boot-project.org
To: u-boot-spacemit@groups.io
Cc: Tom Rini <trini@konsulko.com>
Cc: Neil Armstrong <neil.armstrong@linaro.org>
Cc: David Lechner <dlechner@baylibre.com>
Cc: Julien Stephan <jstephan@baylibre.com>
Cc: Johan Jonker <jbx6244@gmail.com>
Cc: Siu Ming Tong <smtong@axiado.com>
Cc: "Lucien.Jheng" <lucienzx159@gmail.com>
Cc: Eric Chung <eric.chung@riscstar.com>
Cc: Huan Zhou <pericycle.cc@gmail.com>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Pranav Sanwal <pranav.sanwal@amd.com>
Cc: Raymond Mao <raymond.mao@riscstar.com>
Cc: Yixun Lan <dlan@gentoo.org>

---
Eric Chung (4):
      phy: spacemit: add K1 PCIe/USB3 combo PHY driver
      pci: spacemit: add DesignWare PCIe host controller driver
      configs: k1: enable PCIe and NVMe support
      MAINTAINER: add K1 PCIe driver to Spacemit entry

 board/spacemit/k1/MAINTAINERS      |   1 +
 configs/spacemit_k1_defconfig      |  10 +
 drivers/pci/Kconfig                |   7 +
 drivers/pci/Makefile               |   1 +
 drivers/pci/pcie_dw_spacemit.c     | 391 +++++++++++++++++++++++++++++
 drivers/pci/pcie_dw_spacemit.h     |  78 ++++++
 drivers/phy/Kconfig                |   1 +
 drivers/phy/Makefile               |   1 +
 drivers/phy/spacemit/Kconfig       |  11 +
 drivers/phy/spacemit/Makefile      |   1 +
 drivers/phy/spacemit/phy-k1-pcie.c | 492 +++++++++++++++++++++++++++++++++++++
 11 files changed, 994 insertions(+)
---
base-commit: b739fb09a011558396287e077108d2e5379069c1
change-id: 20260705-pci-38358b570d03

Best regards,
--  
Eric Chung <eric.chung@riscstar.com>


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

* [PATCH v2 1/4] phy: spacemit: add K1 PCIe/USB3 combo PHY driver
  2026-09-13  4:23 [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC Eric Chung
@ 2026-09-13  4:23 ` Eric Chung
  2026-09-13  4:23 ` [PATCH v2 2/4] pci: spacemit: add DesignWare PCIe host controller driver Eric Chung
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Eric Chung @ 2026-09-13  4:23 UTC (permalink / raw)
  To: u-boot-spacemit, u-boot, u-boot
  Cc: Tom Rini, Tim Ouyang, Leo Liang, Scott Bambrough, Eric Chung,
	Neil Armstrong, David Lechner, Julien Stephan, Johan Jonker,
	Siu Ming Tong, Lucien.Jheng, Huan Zhou, Michal Simek,
	Pranav Sanwal, Raymond Mao, Yixun Lan

Add PHY driver for Spacemit K1 SoC supporting:
- Combo PHY (PCIe/USB3) with auto-calibration of RX/TX termination
- PCIe-only PHY (2 lanes) using combo PHY calibration values

The combo PHY calibrates at probe time, and the result is shared
globally so PCIe-only PHYs can apply the same termination settings.

Signed-off-by: Eric Chung <eric.chung@riscstar.com>
---
 drivers/phy/Kconfig                |   1 +
 drivers/phy/Makefile               |   1 +
 drivers/phy/spacemit/Kconfig       |  11 +
 drivers/phy/spacemit/Makefile      |   1 +
 drivers/phy/spacemit/phy-k1-pcie.c | 492 +++++++++++++++++++++++++++++++++++++
 5 files changed, 506 insertions(+)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 6262380a60a0..6c5816e67a78 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -369,6 +369,7 @@ source "drivers/phy/ti/Kconfig"
 source "drivers/phy/qcom/Kconfig"
 source "drivers/phy/renesas/Kconfig"
 source "drivers/phy/starfive/Kconfig"
+source "drivers/phy/spacemit/Kconfig"
 
 config PHY_COMMON_PROPS
 	bool "Common PHY properties support"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 19cf95759e57..3256e8bad8d6 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -51,3 +51,4 @@ obj-y += ti/
 obj-y += qcom/
 obj-y += renesas/
 obj-y += starfive/
+obj-y += spacemit/
diff --git a/drivers/phy/spacemit/Kconfig b/drivers/phy/spacemit/Kconfig
new file mode 100644
index 000000000000..3c47601c1fd4
--- /dev/null
+++ b/drivers/phy/spacemit/Kconfig
@@ -0,0 +1,11 @@
+config PHY_SPACEMIT_K1_PCIE
+	bool "Spacemit K1 PCIe PHY driver"
+	depends on PHY
+	help
+	  Support for the Spacemit K1 SoC PCIe and Combo (PCIe/USB3) PHYs.
+
+	  This driver handles both the combo PHY used for port A (which
+	  calibrates RX/TX termination values) and the PCIe-only PHYs for
+	  ports B and C.  The combo PHY must be enabled even if port A
+	  is not used for PCIe, because it provides calibration values
+	  required by the other ports.
diff --git a/drivers/phy/spacemit/Makefile b/drivers/phy/spacemit/Makefile
new file mode 100644
index 000000000000..3496c099cdf3
--- /dev/null
+++ b/drivers/phy/spacemit/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_PHY_SPACEMIT_K1_PCIE) += phy-k1-pcie.o
diff --git a/drivers/phy/spacemit/phy-k1-pcie.c b/drivers/phy/spacemit/phy-k1-pcie.c
new file mode 100644
index 000000000000..e54742a2a9c2
--- /dev/null
+++ b/drivers/phy/spacemit/phy-k1-pcie.c
@@ -0,0 +1,492 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Spacemit K1 PCIe and PCIe/USB 3 combo PHY driver
+ *
+ * Copyright (C) 2026 RISCstar Ltd.  All rights reserved.
+ */
+
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/ofnode.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <reset.h>
+
+#include <dt-bindings/phy/phy.h>
+
+/*
+ * Three PCIe ports are supported in the SpacemiT K1 SoC.
+ *
+ * Port A (combo PHY): 1 lane, can switch between PCIe and USB 3.
+ *                     The only PHY that can auto-calibrate RX/TX termination.
+ * Port B (pcie-phy):  2 lanes, PCIe only.
+ * Port C (pcie-phy):  2 lanes, PCIe only.
+ *
+ * Calibration values from port A are used to configure ports B and C.
+ * Port B/C must not probe until port A has completed calibration.
+ */
+
+/* Offset between lane 0 and lane 1 registers */
+#define PHY_LANE_OFFSET			0x0400
+
+/* PHY PLL configuration */
+#define PCIE_PU_ADDR_CLK_CFG		0x0008
+#define PLL_READY			BIT(0)
+#define CFG_INTERNAL_TIMER_ADJ		GENMASK(10, 7)
+#define TIMER_ADJ_PCIE			0x6
+#define CFG_SW_PHY_INIT_DONE		BIT(11)
+
+#define PCIE_RC_DONE_STATUS		0x0018
+#define CFG_FORCE_RCV_RETRY		BIT(10)
+
+/* PCIe PHY lane calibration */
+#define PCIE_RC_CAL_REG2		0x0020
+#define RC_CAL_TOGGLE			BIT(22)
+#define CLKSEL				GENMASK(31, 29)
+#define CLKSEL_24M			0x3
+
+/* Additional PHY PLL configuration */
+#define PCIE_PU_PLL_1			0x0048
+#define REF_100_WSSC			BIT(12)
+#define FREF_SEL			GENMASK(15, 13)
+#define FREF_24M			0x1
+#define SSC_DEP_SEL			GENMASK(19, 16)
+#define SSC_DEP_NONE			0x0
+
+/* PCIe PHY configuration */
+#define PCIE_PU_PLL_2			0x004c
+#define GEN_REF100			BIT(4)
+
+#define PCIE_RX_REG1			0x0050
+#define EN_RTERM			BIT(3)
+#define AFE_RTERM_REG			GENMASK(11, 8)
+
+#define PCIE_RX_REG2			0x0054
+#define RX_RTERM_SEL			BIT(5)
+
+#define PCIE_LTSSM_DIS_ENTRY		0x005c
+#define CFG_REFCLK_MODE			GENMASK(9, 8)
+#define RFCLK_MODE_DRIVER		0x1
+#define RFCLK_MODE_RECEIVER		0x2
+#define OVRD_REFCLK_MODE		BIT(10)
+
+#define PCIE_TX_REG1			0x0064
+#define TX_RTERM_REG			GENMASK(15, 12)
+#define TX_RTERM_SEL			BIT(25)
+
+/* PHY calibration values */
+#define PCIE_RCAL_RESULT		0x0084
+#define RTERM_VALUE_RX			GENMASK(3, 0)
+#define RTERM_VALUE_TX			GENMASK(7, 4)
+#define R_TUNE_DONE			BIT(10)
+
+/* PMU register offsets (shared APMU space) */
+#define PMUA_USB_PHY_CTRL0		0x0110
+#define COMBO_PHY_SEL			BIT(3)	/* 0: PCIe; 1: USB 3 */
+#define PCIE_CLK_RES_CTRL		0x03cc
+#define PCIE_APP_HOLD_PHY_RST		BIT(30)
+#define DEVICE_TYPE_RC			BIT(31)
+#define GLOBAL_PHY_RST			BIT(8)
+
+#define APMU_CLK_GATE_MASK		0x3f
+
+#define CALIBRATION_TIMEOUT_US		500000
+#define PLL_TIMEOUT_US			500000
+
+/* Global calibration value shared across PHY ports */
+static u32 k1_phy_rterm = ~0;
+
+struct k1_pcie_phy {
+	void __iomem *regs;
+	void __iomem *apmu_base;	/* only for combo PHY */
+	u32 pcie_lanes;
+	bool is_combo;
+	struct clk_bulk clks;
+	struct reset_ctl_bulk rst;
+};
+
+static bool k1_phy_rterm_valid(void)
+{
+	return !(k1_phy_rterm & ~(RTERM_VALUE_RX | RTERM_VALUE_TX));
+}
+
+u32 k1_phy_rterm_rx(void)
+{
+	return FIELD_GET(RTERM_VALUE_RX, k1_phy_rterm);
+}
+
+u32 k1_phy_rterm_tx(void)
+{
+	return FIELD_GET(RTERM_VALUE_TX, k1_phy_rterm);
+}
+
+static void k1_phy_rterm_set(u32 val)
+{
+	k1_phy_rterm = val & (RTERM_VALUE_RX | RTERM_VALUE_TX);
+}
+
+static void k1_combo_phy_sel(struct k1_pcie_phy *k1_phy, bool usb)
+{
+	void __iomem *pmu = k1_phy->apmu_base;
+	u32 val;
+
+	val = readl(pmu + PMUA_USB_PHY_CTRL0);
+	if (usb)
+		val |= COMBO_PHY_SEL;
+	else
+		val &= ~COMBO_PHY_SEL;
+	writel(val, pmu + PMUA_USB_PHY_CTRL0);
+}
+
+int k1_pcie_combo_phy_calibrate(struct udevice *dev, struct k1_pcie_phy *k1_phy)
+{
+	void __iomem *regs = k1_phy->regs;
+	int ret = 0;
+	u32 val;
+
+	if (k1_phy_rterm_valid())
+		return 0;
+
+	/*
+	 * Initialize the APMU control register: set RC mode, enable
+	 * clock gates (bits 0-5), deassert PHY global reset, then
+	 * release the PHY hold.  Without this the PHY registers are
+	 * not accessible and reads will hang.
+	 */
+	val = readl(k1_phy->apmu_base + PCIE_CLK_RES_CTRL);
+	val |= DEVICE_TYPE_RC | PCIE_APP_HOLD_PHY_RST | APMU_CLK_GATE_MASK;
+	val &= ~GLOBAL_PHY_RST;
+	writel(val, k1_phy->apmu_base + PCIE_CLK_RES_CTRL);
+	val &= ~PCIE_APP_HOLD_PHY_RST;
+	writel(val, k1_phy->apmu_base + PCIE_CLK_RES_CTRL);
+
+	/* Put the combo PHY into PCIe mode for calibration */
+	k1_combo_phy_sel(k1_phy, false);
+
+	/* Set refclk override + clear CFG_REFCLK_MODE */
+	val = readl(regs + PCIE_LTSSM_DIS_ENTRY);
+	val |= OVRD_REFCLK_MODE;
+	writel(val, regs + PCIE_LTSSM_DIS_ENTRY);
+
+	val = readl(regs + PCIE_LTSSM_DIS_ENTRY);
+	val &= ~CFG_REFCLK_MODE;
+	writel(val, regs + PCIE_LTSSM_DIS_ENTRY);
+
+	val = readl(regs + PCIE_LTSSM_DIS_ENTRY);
+	val |= FIELD_PREP(CFG_REFCLK_MODE, RFCLK_MODE_DRIVER);
+	writel(val, regs + PCIE_LTSSM_DIS_ENTRY);
+
+	/* Configure PLL: select 24MHz reference, enable 100MHz output */
+	val = readl(regs + PCIE_PU_PLL_1);
+	val &= ~(FREF_SEL | REF_100_WSSC);
+	writel(val, regs + PCIE_PU_PLL_1);
+
+	val = readl(regs + PCIE_PU_PLL_1);
+	val |= FIELD_PREP(FREF_SEL, FREF_24M);
+	writel(val, regs + PCIE_PU_PLL_1);
+
+	val = readl(regs + PCIE_PU_PLL_2);
+	val |= GEN_REF100;
+	writel(val, regs + PCIE_PU_PLL_2);
+
+	val = readl(regs + PCIE_PU_PLL_1);
+	val &= ~SSC_DEP_SEL;
+	writel(val, regs + PCIE_PU_PLL_1);
+
+	/* Start PHY init + force receiver */
+	writel(0x00000B78, regs + PCIE_PU_ADDR_CLK_CFG);
+	writel(CFG_FORCE_RCV_RETRY, regs + PCIE_RC_DONE_STATUS);
+
+	/* Wait for calibration to complete */
+	ret = readl_poll_sleep_timeout(regs + PCIE_RCAL_RESULT,
+				       val, val & R_TUNE_DONE,
+				       500, CALIBRATION_TIMEOUT_US);
+	if (ret)
+		dev_err(dev, "PHY calib timeout, RCAL=0x%08x\n", val);
+
+	if (!ret)
+		k1_phy_rterm_set(val);
+
+	return ret;
+}
+
+static int k1_pcie_phy_init(struct phy *phy)
+{
+	struct k1_pcie_phy *k1_phy = dev_get_priv(phy->dev);
+	void __iomem *regs = k1_phy->regs;
+	int ret;
+	u32 val;
+	int i, lane;
+
+	/* If combo PHY is configured for USB 3 mode */
+	if (k1_phy->is_combo && phy->id == PHY_TYPE_USB3) {
+		k1_combo_phy_sel(k1_phy, true);
+		return 0;
+	}
+
+	/* For combo PHY, ensure it's in PCIe mode */
+	if (k1_phy->is_combo)
+		k1_combo_phy_sel(k1_phy, false);
+
+	dev_dbg(phy->dev, "init: combo=%d lanes=%u rterm=0x%02x\n",
+		k1_phy->is_combo, k1_phy->pcie_lanes, k1_phy_rterm);
+
+	lane = (k1_phy->pcie_lanes == 1) ? 1 : 2;
+
+	/* Apply rterm calibration value: LSB to RX_REG1 */
+	for (i = 0; i < lane; i++) {
+		val = readl(regs + PCIE_RX_REG1 + PHY_LANE_OFFSET * i);
+		val |= FIELD_PREP(AFE_RTERM_REG, k1_phy_rterm_rx());
+		writel(val, regs + PCIE_RX_REG1 + PHY_LANE_OFFSET * i);
+	}
+
+	/* Disable RX_RTERM_SEL for all lanes */
+	for (i = 0; i < lane; i++) {
+		val = readl(regs + PCIE_RX_REG2 + PHY_LANE_OFFSET * i);
+		val &= ~RX_RTERM_SEL;
+		writel(val, regs + PCIE_RX_REG2 + PHY_LANE_OFFSET * i);
+	}
+
+	/* Apply rterm MSB to TX_REG1 */
+	for (i = 0; i < lane; i++) {
+		val = readl(regs + PCIE_TX_REG1 + PHY_LANE_OFFSET * i);
+		val |= FIELD_PREP(TX_RTERM_REG, k1_phy_rterm_tx());
+		writel(val, regs + PCIE_TX_REG1 + PHY_LANE_OFFSET * i);
+	}
+
+	/* Enable TX_RTERM_SEL for all lanes */
+	for (i = 0; i < lane; i++) {
+		val = readl(regs + PCIE_TX_REG1 + PHY_LANE_OFFSET * i);
+		val |= TX_RTERM_SEL;
+		writel(val, regs + PCIE_TX_REG1 + PHY_LANE_OFFSET * i);
+	}
+
+	/* Set CLKSEL_24M on lane0 */
+	val = readl(regs + PCIE_RC_CAL_REG2);
+	val |= FIELD_PREP(CLKSEL, CLKSEL_24M);
+	writel(val, regs + PCIE_RC_CAL_REG2);
+
+	/* Toggle RC_CAL_TOGGLE for all lanes */
+	for (i = 0; i < lane; i++) {
+		val = readl(regs + PCIE_RC_CAL_REG2 + PHY_LANE_OFFSET * i);
+		val &= ~RC_CAL_TOGGLE;
+		writel(val, regs + PCIE_RC_CAL_REG2 + PHY_LANE_OFFSET * i);
+	}
+	for (i = 0; i < lane; i++) {
+		val = readl(regs + PCIE_RC_CAL_REG2 + PHY_LANE_OFFSET * i);
+		val |= RC_CAL_TOGGLE;
+		writel(val, regs + PCIE_RC_CAL_REG2 + PHY_LANE_OFFSET * i);
+	}
+
+	/* Configure refclk as driver mode, override */
+	val = readl(regs + PCIE_LTSSM_DIS_ENTRY);
+	val |= OVRD_REFCLK_MODE;
+	writel(val, regs + PCIE_LTSSM_DIS_ENTRY);
+
+	val = readl(regs + PCIE_LTSSM_DIS_ENTRY);
+	val &= ~CFG_REFCLK_MODE;
+	writel(val, regs + PCIE_LTSSM_DIS_ENTRY);
+
+	val = readl(regs + PHY_LANE_OFFSET + PCIE_LTSSM_DIS_ENTRY);
+	val |= OVRD_REFCLK_MODE;
+	writel(val, regs + PHY_LANE_OFFSET + PCIE_LTSSM_DIS_ENTRY);
+
+	val = readl(regs + PHY_LANE_OFFSET + PCIE_LTSSM_DIS_ENTRY);
+	val &= ~CFG_REFCLK_MODE;
+	writel(val, regs + PHY_LANE_OFFSET + PCIE_LTSSM_DIS_ENTRY);
+
+	/* Set driver mode for both lanes */
+	val = readl(regs + PCIE_LTSSM_DIS_ENTRY);
+	val |= FIELD_PREP(CFG_REFCLK_MODE, RFCLK_MODE_DRIVER);
+	writel(val, regs + PCIE_LTSSM_DIS_ENTRY);
+
+	val = readl(regs + PHY_LANE_OFFSET + PCIE_LTSSM_DIS_ENTRY);
+	val |= FIELD_PREP(CFG_REFCLK_MODE, RFCLK_MODE_DRIVER);
+	writel(val, regs + PHY_LANE_OFFSET + PCIE_LTSSM_DIS_ENTRY);
+
+	/* Configure PLL: select 24MHz reference */
+	val = readl(regs + PCIE_PU_PLL_1);
+	val &= ~FREF_SEL;
+	writel(val, regs + PCIE_PU_PLL_1);
+
+	val = readl(regs + PCIE_PU_PLL_1);
+	val |= FIELD_PREP(FREF_SEL, FREF_24M);
+	writel(val, regs + PCIE_PU_PLL_1);
+
+	/* Enable 100MHz reference output */
+	val = readl(regs + PCIE_PU_PLL_2);
+	val |= GEN_REF100;
+	writel(val, regs + PCIE_PU_PLL_2);
+
+	/* Disable SSC */
+	val = readl(regs + PCIE_PU_PLL_1);
+	val &= ~SSC_DEP_SEL;
+	writel(val, regs + PCIE_PU_PLL_1);
+
+	/* Set PU_ADDR_CLK_CFG for both lanes */
+	val = 0x00000B78;
+	writel(val, regs + PCIE_PU_ADDR_CLK_CFG);
+	writel(val, regs + PHY_LANE_OFFSET + PCIE_PU_ADDR_CLK_CFG);
+
+	/* Force receiver done */
+	val = CFG_FORCE_RCV_RETRY;
+	writel(val, regs + PCIE_RC_DONE_STATUS);
+
+	/* Wait for PLL lock */
+	ret = readl_poll_timeout(regs + PCIE_PU_ADDR_CLK_CFG, val,
+				 val & PLL_READY, PLL_TIMEOUT_US);
+	if (ret) {
+		dev_err(phy->dev, "PLL lock timeout! reg[0x08]=0x%08x\n", val);
+		return ret;
+	}
+
+	dev_dbg(phy->dev, "PLL locked (combo=%d, lanes=%d)\n",
+		k1_phy->is_combo, k1_phy->pcie_lanes);
+
+	return 0;
+}
+
+static int k1_pcie_phy_exit(struct phy *phy)
+{
+	return 0;
+}
+
+static int k1_pcie_phy_of_xlate(struct phy *phy,
+				struct ofnode_phandle_args *args)
+{
+	struct k1_pcie_phy *k1_phy = dev_get_priv(phy->dev);
+
+	if (k1_phy->is_combo) {
+		if (args->args_count != 1)
+			return -EINVAL;
+		if (args->args[0] != PHY_TYPE_PCIE &&
+		    args->args[0] != PHY_TYPE_USB3)
+			return -EINVAL;
+	}
+
+	if (args->args_count > 0)
+		phy->id = args->args[0];
+	else
+		phy->id = 0;
+
+	return 0;
+}
+
+static const struct phy_ops k1_pcie_phy_ops = {
+	.of_xlate	= k1_pcie_phy_of_xlate,
+	.init		= k1_pcie_phy_init,
+	.exit		= k1_pcie_phy_exit,
+};
+
+static int k1_pcie_phy_probe(struct udevice *dev)
+{
+	struct k1_pcie_phy *k1_phy = dev_get_priv(dev);
+	struct ofnode_phandle_args apmu_args;
+	bool is_combo;
+	int ret;
+	u32 lanes;
+
+	is_combo = (bool)dev_get_driver_data(dev);
+	k1_phy->is_combo = is_combo;
+
+	k1_phy->regs = dev_read_addr_ptr(dev);
+	if (!k1_phy->regs)
+		return -EINVAL;
+
+	/* Determine number of lanes */
+	if (is_combo) {
+		lanes = 1;
+	} else {
+		u32 count = 0;
+
+		ret = dev_read_u32(dev, "num-lanes", &count);
+		if (ret == 0 && count == 1)
+			lanes = 1;
+		else
+			lanes = 2;
+	}
+	k1_phy->pcie_lanes = lanes;
+
+	/* Get APMU base for combo PHY (for mode select + calibration) */
+	if (is_combo) {
+		ret = dev_read_phandle_with_args(dev, "spacemit,apmu",
+						 NULL, 0, 0,
+						 &apmu_args);
+		if (ret)
+			return ret;
+
+		k1_phy->apmu_base = (void __iomem *)ofnode_get_addr(apmu_args.node);
+		if (!k1_phy->apmu_base)
+			return -EINVAL;
+
+		ret = clk_get_bulk(dev, &k1_phy->clks);
+		if (ret)
+			dev_warn(dev, "failed to get clocks: %d\n", ret);
+
+		ret = reset_get_bulk(dev, &k1_phy->rst);
+		if (ret)
+			dev_warn(dev, "failed to get resets: %d\n", ret);
+
+		ret = k1_pcie_combo_phy_calibrate(dev, k1_phy);
+		if (ret)
+			dev_warn(dev, "calibration failed: %d\n", ret);
+	} else {
+		/*
+		 * PCIe-only PHYs need the calibration value from the
+		 * combo PHY.  In device-tree order the combo PHY probes
+		 * first, but handle the case where it hasn't yet by
+		 * explicitly looking it up.
+		 */
+		if (!k1_phy_rterm_valid()) {
+			struct udevice *combo_dev;
+
+			ret = uclass_first_device_drvdata(UCLASS_PHY, 1UL,
+							  &combo_dev);
+			if (ret)
+				dev_warn(dev,
+					 "failed to probe combo PHY: %d\n",
+					 ret);
+		}
+
+		if (!k1_phy_rterm_valid()) {
+			dev_err(dev,
+				"calibration value not available; "
+				"is the combo PHY enabled?\n");
+			return -ENOENT;
+		}
+
+		ret = clk_get_bulk(dev, &k1_phy->clks);
+		if (ret)
+			dev_warn(dev, "failed to get clocks: %d\n", ret);
+
+		ret = reset_get_bulk(dev, &k1_phy->rst);
+		if (ret)
+			dev_warn(dev, "failed to get resets: %d\n", ret);
+	}
+
+	dev_dbg(dev, "probed (combo=%d lanes=%u rterm=0x%02x)\n",
+		is_combo, lanes, k1_phy_rterm);
+
+	return 0;
+}
+
+static const struct udevice_id k1_pcie_phy_ids[] = {
+	{ .compatible = "spacemit,k1-combo-phy", .data = 1UL },
+	{ .compatible = "spacemit,k1-pcie-phy", .data = 0UL },
+	{ }
+};
+
+U_BOOT_DRIVER(k1_pcie_phy) = {
+	.name		= "k1_pcie_phy",
+	.id		= UCLASS_PHY,
+	.of_match	= k1_pcie_phy_ids,
+	.ops		= &k1_pcie_phy_ops,
+	.probe		= k1_pcie_phy_probe,
+	.priv_auto	= sizeof(struct k1_pcie_phy),
+};

-- 
2.51.0


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

* [PATCH v2 2/4] pci: spacemit: add DesignWare PCIe host controller driver
  2026-09-13  4:23 [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC Eric Chung
  2026-09-13  4:23 ` [PATCH v2 1/4] phy: spacemit: add K1 PCIe/USB3 combo PHY driver Eric Chung
@ 2026-09-13  4:23 ` Eric Chung
  2026-09-23 13:30   ` Yixun Lan
  2026-09-13  4:23 ` [PATCH v2 3/4] configs: k1: enable PCIe and NVMe support Eric Chung
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Eric Chung @ 2026-09-13  4:23 UTC (permalink / raw)
  To: u-boot-spacemit, u-boot, u-boot
  Cc: Tom Rini, Tim Ouyang, Leo Liang, Scott Bambrough, Eric Chung,
	Neil Armstrong, David Lechner, Julien Stephan, Johan Jonker,
	Siu Ming Tong, Lucien.Jheng, Huan Zhou, Michal Simek,
	Pranav Sanwal, Raymond Mao, Yixun Lan

Add PCIe host controller driver for Spacemit K1 SoC using the
Synopsys DesignWare PCIe core. Supports up to 3 ports.

Signed-off-by: Eric Chung <eric.chung@riscstar.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

---
v2:
- Locate the phy by index instead.
---
 drivers/pci/Kconfig            |   7 +
 drivers/pci/Makefile           |   1 +
 drivers/pci/pcie_dw_spacemit.c | 391 +++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pcie_dw_spacemit.h |  78 ++++++++
 4 files changed, 477 insertions(+)

diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 42edc73bcdaa..86fafc5a3c73 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -498,4 +498,11 @@ config PCIE_DW_IMX
 	  Say Y here if you want to enable DW PCIe controller support on
 	  iMX SoCs.
 
+config PCIE_DW_SPACEMIT
+	bool "Enable Spacemit K1 PCIe"
+	select PCIE_DW_COMMON
+	help
+	  Say Y here if you want to enable PCIe controller support on
+	  K1 SoC.
+
 endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 3873f357a45f..f839ea1d396f 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_PCIE_PLDA_COMMON) += pcie_plda_common.o
 obj-$(CONFIG_PCIE_STARFIVE_JH7110) += pcie_starfive_jh7110.o
 obj-$(CONFIG_PCIE_DW_AMD) += pcie_dw_amd.o
 obj-$(CONFIG_PCIE_DW_IMX) += pcie_dw_imx.o
+obj-$(CONFIG_PCIE_DW_SPACEMIT) += pcie_dw_spacemit.o
diff --git a/drivers/pci/pcie_dw_spacemit.c b/drivers/pci/pcie_dw_spacemit.c
new file mode 100644
index 000000000000..09c56d8a4c4a
--- /dev/null
+++ b/drivers/pci/pcie_dw_spacemit.c
@@ -0,0 +1,391 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Spacemit K1 PCIe host controller driver
+ *
+ * Copyright (c) 2023, Spacemit Corporation.
+ * Copyright (c) 2026, RISCstar Ltd.
+ *
+ */
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm-generic/gpio.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/ofnode.h>
+#include <dm/read.h>
+#include <generic-phy.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <log.h>
+#include <pci.h>
+#include <power-domain.h>
+#include <reset.h>
+
+#include "pcie_dw_common.h"
+#include "pcie_dw_spacemit.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct pcie_dw_spacemit {
+	/* Must be first member of the struct */
+	struct pcie_dw dw;
+	void __iomem		*apmu_base;
+	u32			apmu_offset;
+	void __iomem		*phy_ahb;	/* DT "link" */
+	int			port_id;
+
+	/* reset, clock resources */
+	struct clk_bulk		clks;
+	struct reset_ctl_bulk	rsts;
+	struct gpio_desc		pwr_on_gpio;
+	int			power_on_status;
+};
+
+static inline u32 spacemit_pcie_readl(struct pcie_dw_spacemit *pcie, u32 offset)
+{
+	return readl(pcie->apmu_base + pcie->apmu_offset + offset);
+}
+
+static inline void spacemit_pcie_writel(struct pcie_dw_spacemit *pcie,
+					u32 offset, u32 value)
+{
+	writel(value, pcie->apmu_base + pcie->apmu_offset + offset);
+}
+
+static inline u32 spacemit_pcie_phy_ahb_readl(struct pcie_dw_spacemit *pcie, u32 offset)
+{
+	return readl(pcie->phy_ahb + offset);
+}
+
+static void pcie_dw_configure(struct pcie_dw_spacemit *pci, u32 cap_speed)
+{
+	u32 val;
+
+	dw_pcie_dbi_write_enable(&pci->dw, true);
+
+	val = readl(pci->dw.dbi_base + PCIE_LINK_CAPABILITY);
+	val &= ~TARGET_LINK_SPEED_MASK;
+	val |= cap_speed;
+	writel(val, pci->dw.dbi_base + PCIE_LINK_CAPABILITY);
+
+	val = readl(pci->dw.dbi_base + PCIE_LINK_CTL_2);
+	val &= ~TARGET_LINK_SPEED_MASK;
+	val |= cap_speed;
+	writel(val, pci->dw.dbi_base + PCIE_LINK_CTL_2);
+
+	dw_pcie_dbi_write_enable(&pci->dw, false);
+}
+
+static int is_link_up(struct pcie_dw_spacemit *pci)
+{
+	u32 val;
+
+	val = readl(pci->dw.dbi_base + PCIE_PORT_DEBUG0);
+	val &= PORT_LOGIC_LTSSM_STATE_MASK;
+
+	return (val == PORT_LOGIC_LTSSM_STATE_L0);
+}
+
+static int wait_link_up(struct pcie_dw_spacemit *pci)
+{
+	unsigned long timeout;
+
+	timeout = get_timer(0) + PCIE_LINK_UP_TIMEOUT_MS;
+	while (!is_link_up(pci)) {
+		if (get_timer(0) > timeout) {
+			dev_dbg(pci->dw.dev, "LTSSM link training timeout\n");
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int pcie_dw_spacemit_pcie_link_up(struct pcie_dw_spacemit *pci, u32 cap_speed)
+{
+	u32 reg;
+
+	if (is_link_up(pci)) {
+		printf("PCI Link already up before configuration!\n");
+		return 1;
+	}
+
+	/* DW pre link configurations */
+	pcie_dw_configure(pci, cap_speed);
+
+	/* Initiate link training */
+	reg = spacemit_pcie_readl(pci, PCIECTRL_K1X_CONF_DEVICE_CMD);
+	reg |= LTSSM_EN;
+	reg &= ~APP_HOLD_PHY_RST;
+	spacemit_pcie_writel(pci, PCIECTRL_K1X_CONF_DEVICE_CMD, reg);
+
+	/* Check that link was established */
+	if (!wait_link_up(pci))
+		return 0;
+
+	/*
+	 * Link can be established in Gen 1, still need to wait
+	 * until MAC negotiation is completed
+	 */
+	udelay(100);
+
+	return 1;
+}
+
+static int pcie_set_mode(struct pcie_dw_spacemit *pci,
+			 enum dw_pcie_device_mode mode)
+{
+	u32 reg;
+
+	switch (mode) {
+	case DW_PCIE_RC_TYPE:
+		reg = spacemit_pcie_readl(pci, PCIECTRL_K1X_CONF_DEVICE_CMD);
+		reg |= DEVICE_TYPE_RC | PCIE_AUX_PWR_DET;
+		spacemit_pcie_writel(pci, PCIECTRL_K1X_CONF_DEVICE_CMD, reg);
+
+		reg = spacemit_pcie_readl(pci, PCIE_CTRL_LOGIC);
+		reg |= PCIE_IGNORE_PERSTN;
+		spacemit_pcie_writel(pci, PCIE_CTRL_LOGIC, reg);
+		break;
+	case DW_PCIE_EP_TYPE:
+		reg = spacemit_pcie_readl(pci, PCIECTRL_K1X_CONF_DEVICE_CMD);
+		reg &= ~DEVICE_TYPE_RC;
+		spacemit_pcie_writel(pci, PCIECTRL_K1X_CONF_DEVICE_CMD, reg);
+		break;
+	default:
+		dev_err(pci->dw.dev, "INVALID device type %d\n", mode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int spacemit_pcie_host_init(struct pcie_dw_spacemit *pci)
+{
+	u32 reg;
+
+	mdelay(100);
+	/* set Perst# gpio high state*/
+	reg = spacemit_pcie_readl(pci, PCIECTRL_K1X_CONF_DEVICE_CMD);
+	reg &= ~PCIE_RC_PERST;
+	spacemit_pcie_writel(pci, PCIECTRL_K1X_CONF_DEVICE_CMD, reg);
+
+	return 0;
+}
+
+static int pcie_dw_init_id(struct pcie_dw_spacemit *pci)
+{
+	dw_pcie_dbi_write_enable(&pci->dw, true);
+	writew(SPACEMIT_PCIE_VENDOR_ID, pci->dw.dbi_base + PCI_VENDOR_ID);
+	writew(SPACEMIT_PCIE_DEVICE_ID, pci->dw.dbi_base + PCI_DEVICE_ID);
+	dw_pcie_dbi_write_enable(&pci->dw, false);
+
+	return 0;
+}
+
+static int k1x_power_on(struct pcie_dw_spacemit *pci, int on)
+{
+	struct pcie_dw *dwp = &pci->dw;
+	int gpio_val = 0;
+
+	if (on) {
+		if (pci->power_on_status)
+			gpio_val = 1;
+		else
+			gpio_val = 0;
+	} else {
+		if (pci->power_on_status)
+			gpio_val = 0;
+		else
+			gpio_val = 1;
+	}
+
+	if (dm_gpio_is_valid(&pci->pwr_on_gpio)) {
+		dev_info(dwp->dev, "PCIe interface power %s, set gpio %d to %d\n",
+			 on ? "on" : "off", pci->pwr_on_gpio.offset, gpio_val);
+		dm_gpio_set_value(&pci->pwr_on_gpio, gpio_val);
+	}
+
+	return 0;
+}
+
+static int pcie_dw_spacemit_probe(struct udevice *dev)
+{
+	struct pcie_dw_spacemit *pci = dev_get_priv(dev);
+	struct udevice *ctlr = pci_get_controller(dev);
+	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
+	struct phy phy0 = {0};
+	ofnode port;
+	int ret;
+	u32 reg;
+
+	/* enable pcie clk and deassert resets */
+	clk_enable_bulk(&pci->clks);
+	reset_deassert_bulk(&pci->rsts);
+
+	reg = spacemit_pcie_readl(pci, PCIECTRL_K1X_CONF_DEVICE_CMD);
+	reg &= ~LTSSM_EN;
+	spacemit_pcie_writel(pci, PCIECTRL_K1X_CONF_DEVICE_CMD, reg);
+
+	/* set Perst# (fundamental reset) gpio low state*/
+	reg = spacemit_pcie_readl(pci, PCIECTRL_K1X_CONF_DEVICE_CMD);
+	reg |= PCIE_RC_PERST;
+	spacemit_pcie_writel(pci, PCIECTRL_K1X_CONF_DEVICE_CMD, reg);
+
+	/* The PHY is described on the root port child node */
+	port = ofnode_first_subnode(dev_ofnode(dev));
+	if (!ofnode_valid(port)) {
+		dev_err(dev, "failed to find PCIe port node\n");
+		return -ENODEV;
+	}
+
+	ret = generic_phy_get_by_index_nodev(port, 0, &phy0);
+	if (!ret) {
+		reg = spacemit_pcie_readl(pci, PCIECTRL_K1X_CONF_DEVICE_CMD);
+		reg |= DEVICE_TYPE_RC | APP_HOLD_PHY_RST | PCIE_PHY_LANE_CTRL_MASK;
+		reg &= ~GLOBAL_PHY_RST;
+		spacemit_pcie_writel(pci, PCIECTRL_K1X_CONF_DEVICE_CMD, reg);
+		reg &= ~(u32)APP_HOLD_PHY_RST;
+		spacemit_pcie_writel(pci, PCIECTRL_K1X_CONF_DEVICE_CMD, reg);
+
+		ret = generic_phy_init(&phy0);
+		if (ret) {
+			dev_err(dev, "failed to init PHY: %d\n", ret);
+			return ret;
+		}
+
+		ret = generic_phy_power_on(&phy0);
+		if (ret) {
+			dev_err(dev, "failed to power on PHY: %d\n", ret);
+			return ret;
+		}
+	} else {
+		dev_err(dev, "failed to get pcie-phy: %d\n", ret);
+		return ret;
+	}
+
+	pci->dw.first_busno = dev_seq(dev);
+	pci->dw.dev = dev;
+
+	pcie_set_mode(pci, DW_PCIE_RC_TYPE);
+
+	/* power on the interface */
+	k1x_power_on(pci, 1);
+
+	spacemit_pcie_host_init(pci);
+	pcie_dw_setup_host(&pci->dw);
+	pcie_dw_init_id(pci);
+
+	if (!pcie_dw_spacemit_pcie_link_up(pci, LINK_SPEED_GEN_1)) {
+		printf("PCIE-%d: Link down\n", dev_seq(dev));
+		return -ENODEV;
+	}
+
+	printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", dev_seq(dev),
+	       pcie_dw_get_link_speed(&pci->dw),
+	       pcie_dw_get_link_width(&pci->dw),
+	       hose->first_busno);
+
+	ret = pcie_dw_prog_outbound_atu_unroll(&pci->dw, PCIE_ATU_REGION_INDEX0,
+					       PCIE_ATU_TYPE_MEM,
+					       pci->dw.mem.phys_start,
+					       pci->dw.mem.bus_start,
+					       pci->dw.mem.size);
+
+	return 0;
+}
+
+static int pcie_dw_spacemit_of_to_plat(struct udevice *dev)
+{
+	int ret = 0;
+	struct pcie_dw_spacemit *pcie = dev_get_priv(dev);
+	struct ofnode_phandle_args args;
+	fdt_addr_t dbi_addr;
+
+	/* Get the controller base address */
+	pcie->dw.dbi_base = (void *)dev_read_addr_name(dev, "dbi");
+	if ((fdt_addr_t)pcie->dw.dbi_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	dbi_addr = (fdt_addr_t)pcie->dw.dbi_base;
+
+	/* Get the config space base address and size */
+	pcie->dw.cfg_base = (void *)dev_read_addr_size_name(dev, "config",
+							 &pcie->dw.cfg_size);
+	if ((fdt_addr_t)pcie->dw.cfg_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* Get the iATU base address and size */
+	pcie->dw.atu_base = (void *)dev_read_addr_name(dev, "atu");
+	if ((fdt_addr_t)pcie->dw.atu_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* Get the PHY AHB base address (called "link" in Linux DTS) */
+	pcie->phy_ahb = (void *)dev_read_addr_name(dev, "link");
+	if ((fdt_addr_t)pcie->phy_ahb == FDT_ADDR_T_NONE) {
+		pcie->phy_ahb = (void *)dev_read_addr_name(dev, "phy_ahb");
+		if ((fdt_addr_t)pcie->phy_ahb == FDT_ADDR_T_NONE)
+			return -EINVAL;
+	}
+
+	/* Get APMU regmap from spacemit,apmu property */
+	ret = dev_read_phandle_with_args(dev, "spacemit,apmu", NULL, 1, 0,
+					 &args);
+	if (ret)
+		return ret;
+
+	pcie->apmu_base = (void __iomem *)ofnode_get_addr(args.node);
+	if (!pcie->apmu_base)
+		return -EINVAL;
+	pcie->apmu_offset = args.args[0];
+
+	/* Derive port ID from DBI base address */
+	pcie->port_id = (dbi_addr - SPACEMIT_PCIE_DBI_BASE) / SPACEMIT_PCIE_DBI_STRIDE;
+
+	ret = clk_get_bulk(dev, &pcie->clks);
+	if (ret) {
+		dev_warn(dev, "failed to get clocks: %d\n", ret);
+		return ret;
+	}
+
+	ret = reset_get_bulk(dev, &pcie->rsts);
+	if (ret) {
+		dev_warn(dev, "failed to get resets: %d\n", ret);
+		return ret;
+	}
+
+	gpio_request_by_name(dev, "k1x,pwr_on", 0, &pcie->pwr_on_gpio,
+			     GPIOD_IS_OUT);
+	if (!dm_gpio_is_valid(&pcie->pwr_on_gpio))
+		dev_info(dev, "has no power on gpio.\n");
+
+	ret = dev_read_u32(dev, "power-on-status", &pcie->power_on_status);
+	if (ret) {
+		dev_info(dev, "has no power-on-status flag, use default.\n");
+		pcie->power_on_status = 1;
+	}
+
+	return 0;
+}
+
+static const struct dm_pci_ops pcie_dw_spacemit_ops = {
+	.read_config	= pcie_dw_read_config,
+	.write_config	= pcie_dw_write_config,
+};
+
+static const struct udevice_id pcie_dw_spacemit_ids[] = {
+	{ .compatible = "spacemit,k1-pcie" },
+	{ }
+};
+
+U_BOOT_DRIVER(pcie_dw_spacemit) = {
+	.name			= "pcie_dw_spacemit",
+	.id			= UCLASS_PCI,
+	.of_match		= pcie_dw_spacemit_ids,
+	.ops			= &pcie_dw_spacemit_ops,
+	.of_to_plat	= pcie_dw_spacemit_of_to_plat,
+	.probe			= pcie_dw_spacemit_probe,
+	.priv_auto	= sizeof(struct pcie_dw_spacemit),
+};
diff --git a/drivers/pci/pcie_dw_spacemit.h b/drivers/pci/pcie_dw_spacemit.h
new file mode 100644
index 000000000000..2c17f113b75c
--- /dev/null
+++ b/drivers/pci/pcie_dw_spacemit.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Spacemit K1 DesignWare PCIe host controller driver
+ *
+ * Copyright (c) 2023, Spacemit Corporation.
+ * Copyright (c) 2026, RISCstar Ltd.
+ */
+
+#ifndef _PCIE_DW_SPACEMIT_H_
+#define _PCIE_DW_SPACEMIT_H_
+
+#include <linux/bitops.h>
+
+/* PCIe DW common registers */
+#define PCIE_LINK_CAPABILITY		0x7c
+#define PCIE_LINK_CTL_2			0xa0
+#define TARGET_LINK_SPEED_MASK		0xf
+#define LINK_SPEED_GEN_1		0x1
+#define LINK_SPEED_GEN_2		0x2
+#define LINK_SPEED_GEN_3		0x3
+
+#define PCIE_MISC_CONTROL_1_OFF	0x8bc
+#define PCIE_DBI_RO_WR_EN		BIT(0)
+
+#define PLR_OFFSET			0x700
+#define PCIE_PORT_DEBUG0		(PLR_OFFSET + 0x28)
+#define PORT_LOGIC_LTSSM_STATE_MASK	0x1f
+#define PORT_LOGIC_LTSSM_STATE_L0	0x11
+
+#define PCIE_LINK_UP_TIMEOUT_MS		1000
+
+/* Vendor and device IDs */
+#define PCIE_VENDORID_MASK		GENMASK(15, 0)
+#define PCIE_DEVICEID_SHIFT		16
+#define SPACEMIT_PCIE_VENDOR_ID		0x201F
+#define SPACEMIT_PCIE_DEVICE_ID		0x0001
+
+/* Application register offsets */
+#define PCIE_CMD_STATUS			0x04
+#define LTSSM_EN_VAL			BIT(0)
+
+/* K1X_CONF_DEVICE_CMD register */
+#define PCIECTRL_K1X_CONF_DEVICE_CMD	0x0000
+#define LTSSM_EN			BIT(6)
+#define PCIE_PERST_IN			BIT(7)
+#define GLOBAL_PHY_RST			BIT(8)
+#define PCIE_AUX_PWR_DET		BIT(9)
+#define PCIE_CLKREQ_IN			BIT(10)	/* read-only: CLKREQ# IO input value */
+#define PCIE_REFCLK_EN			BIT(11)
+#define PCIE_RC_PERST			BIT(12)
+#define PCIE_EP_WAKE			BIT(13)
+#define APP_HOLD_PHY_RST		BIT(30)
+#define DEVICE_TYPE_RC			BIT(31)
+
+/* PCIE_CTRL_LOGIC register */
+#define PCIE_CTRL_LOGIC			0x0004
+#define PCIE_SOFT_RESET			BIT(0)
+#define PCIE_IGNORE_PERSTN		BIT(2)
+
+/* PHY AHB link status */
+#define K1X_PHY_AHB_LINK_STS		0x0004
+#define SMLH_LINK_UP			BIT(1)
+#define RDLH_LINK_UP			BIT(12)
+
+/* PHY lane control mask (bits 0-5 in DEVICE_CMD) */
+#define PCIE_PHY_LANE_CTRL_MASK		0x3f
+
+/* PCIe DBI address calculation */
+#define SPACEMIT_PCIE_DBI_BASE		0xca000000
+#define SPACEMIT_PCIE_DBI_STRIDE	0x400000
+
+enum dw_pcie_device_mode {
+	DW_PCIE_UNKNOWN_TYPE,
+	DW_PCIE_EP_TYPE,
+	DW_PCIE_RC_TYPE,
+};
+
+#endif /* _PCIE_DW_SPACEMIT_H_ */

-- 
2.51.0


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

* [PATCH v2 3/4] configs: k1: enable PCIe and NVMe support
  2026-09-13  4:23 [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC Eric Chung
  2026-09-13  4:23 ` [PATCH v2 1/4] phy: spacemit: add K1 PCIe/USB3 combo PHY driver Eric Chung
  2026-09-13  4:23 ` [PATCH v2 2/4] pci: spacemit: add DesignWare PCIe host controller driver Eric Chung
@ 2026-09-13  4:23 ` Eric Chung
  2026-09-13  4:23 ` [PATCH v2 4/4] MAINTAINER: add K1 PCIe driver to Spacemit entry Eric Chung
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Eric Chung @ 2026-09-13  4:23 UTC (permalink / raw)
  To: u-boot-spacemit, u-boot, u-boot
  Cc: Tom Rini, Tim Ouyang, Leo Liang, Scott Bambrough, Eric Chung,
	Neil Armstrong, David Lechner, Julien Stephan, Johan Jonker,
	Siu Ming Tong, Lucien.Jheng, Huan Zhou, Michal Simek,
	Pranav Sanwal, Raymond Mao, Yixun Lan

Enable PCIe and NVMe support on K1 based boards.

Signed-off-by: Eric Chung <eric.chung@riscstar.com>
---
 configs/spacemit_k1_defconfig | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/configs/spacemit_k1_defconfig b/configs/spacemit_k1_defconfig
index 5f9923c7f470..9c15d96eae20 100644
--- a/configs/spacemit_k1_defconfig
+++ b/configs/spacemit_k1_defconfig
@@ -105,6 +105,16 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_MEMINFO=y
 CONFIG_CMD_MEMINFO_MAP=y
 CONFIG_EFI_PARTITION=y
+CONFIG_PCI=y
+CONFIG_CMD_PCI=y
+CONFIG_NVME=y
+CONFIG_NVME_PCI=y
+CONFIG_CMD_NVME=y
+CONFIG_PCIE_DW_SPACEMIT=y
+CONFIG_PHY=y
+CONFIG_PHY_SPACEMIT_K1_PCIE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_EXT4=y
 CONFIG_SPL_SPI=y
 CONFIG_SPL_DM_SPI=y
 CONFIG_SPL_DM_SPI_FLASH=y

-- 
2.51.0


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

* [PATCH v2 4/4] MAINTAINER: add K1 PCIe driver to Spacemit entry
  2026-09-13  4:23 [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC Eric Chung
                   ` (2 preceding siblings ...)
  2026-09-13  4:23 ` [PATCH v2 3/4] configs: k1: enable PCIe and NVMe support Eric Chung
@ 2026-09-13  4:23 ` Eric Chung
  2026-09-23 13:16 ` [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC Yixun Lan
  2026-09-29 10:15 ` Yixun Lan
  5 siblings, 0 replies; 9+ messages in thread
From: Eric Chung @ 2026-09-13  4:23 UTC (permalink / raw)
  To: u-boot-spacemit, u-boot, u-boot
  Cc: Tom Rini, Tim Ouyang, Leo Liang, Scott Bambrough, Eric Chung,
	Neil Armstrong, David Lechner, Julien Stephan, Johan Jonker,
	Siu Ming Tong, Lucien.Jheng, Huan Zhou, Michal Simek,
	Pranav Sanwal, Raymond Mao, Yixun Lan

Add drivers/pci/pcie_dw_spacemit.c to the list of files
maintained for the Spacemit K1 board.

Signed-off-by: Eric Chung <eric.chung@riscstar.com>
---
 board/spacemit/k1/MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/board/spacemit/k1/MAINTAINERS b/board/spacemit/k1/MAINTAINERS
index e12288a206e0..c1d6b8f3a1c0 100644
--- a/board/spacemit/k1/MAINTAINERS
+++ b/board/spacemit/k1/MAINTAINERS
@@ -10,6 +10,7 @@ F:	doc/board/spacemit/
 F:	drivers/gpio/spacemit_gpio.c
 F:	drivers/i2c/k1_i2c.c
 F:	drivers/mmc/spacemit_sdhci.c
+F:	drivers/pci/pcie_dw_spacemit.c
 F:	drivers/pinctrl/spacemit/
 F:	drivers/power/pmic/pmic_spacemit_p1.c
 F:	drivers/power/regulator/spacemit_p1_regulator.c

-- 
2.51.0


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

* Re: [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC
  2026-09-13  4:23 [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC Eric Chung
                   ` (3 preceding siblings ...)
  2026-09-13  4:23 ` [PATCH v2 4/4] MAINTAINER: add K1 PCIe driver to Spacemit entry Eric Chung
@ 2026-09-23 13:16 ` Yixun Lan
  2026-09-29 10:15 ` Yixun Lan
  5 siblings, 0 replies; 9+ messages in thread
From: Yixun Lan @ 2026-09-23 13:16 UTC (permalink / raw)
  To: Eric Chung
  Cc: u-boot-spacemit, u-boot, Tom Rini, Tim Ouyang, Leo Liang,
	Scott Bambrough, Neil Armstrong, David Lechner, Julien Stephan,
	Johan Jonker, Siu Ming Tong, Lucien.Jheng, Huan Zhou,
	Michal Simek, Pranav Sanwal, Raymond Mao, Yixun Lan

On 12:23 Sun 13 Sep     , Eric Chung wrote:
> Signed-off-by: Eric Chung <eric.chung@riscstar.com>
> ---
> Changes in v2:
> - dts: Rebase on upstream DTS. So drop the changes in overlay DTS.
> - pci: Find the phy by index instead.
> - maintainer: Add the driver in the Spacemit MAINTAINER entry.
> - Link to v1: https://patch.msgid.link/20260705-pci-v1-0-beca83440a27@riscstar.com
> 
> To: u-boot@lists.u-boot-project.org
> To: u-boot-spacemit@groups.io
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Neil Armstrong <neil.armstrong@linaro.org>
> Cc: David Lechner <dlechner@baylibre.com>
> Cc: Julien Stephan <jstephan@baylibre.com>
> Cc: Johan Jonker <jbx6244@gmail.com>
> Cc: Siu Ming Tong <smtong@axiado.com>
> Cc: "Lucien.Jheng" <lucienzx159@gmail.com>
> Cc: Eric Chung <eric.chung@riscstar.com>
> Cc: Huan Zhou <pericycle.cc@gmail.com>
> Cc: Michal Simek <michal.simek@amd.com>
> Cc: Pranav Sanwal <pranav.sanwal@amd.com>
> Cc: Raymond Mao <raymond.mao@riscstar.com>
> Cc: Yixun Lan <dlan@gentoo.org>
> 
> ---
> Eric Chung (4):
>       phy: spacemit: add K1 PCIe/USB3 combo PHY driver
>       pci: spacemit: add DesignWare PCIe host controller driver
>       configs: k1: enable PCIe and NVMe support
>       MAINTAINER: add K1 PCIe driver to Spacemit entry
> 
>  board/spacemit/k1/MAINTAINERS      |   1 +
>  configs/spacemit_k1_defconfig      |  10 +
>  drivers/pci/Kconfig                |   7 +
>  drivers/pci/Makefile               |   1 +
>  drivers/pci/pcie_dw_spacemit.c     | 391 +++++++++++++++++++++++++++++
>  drivers/pci/pcie_dw_spacemit.h     |  78 ++++++
>  drivers/phy/Kconfig                |   1 +
>  drivers/phy/Makefile               |   1 +
>  drivers/phy/spacemit/Kconfig       |  11 +
>  drivers/phy/spacemit/Makefile      |   1 +
>  drivers/phy/spacemit/phy-k1-pcie.c | 492 +++++++++++++++++++++++++++++++++++++
>  11 files changed, 994 insertions(+)
> ---
For the series, tested on Bananapi-f3 board

Reviewed-by: Yixun Lan <dlan@kernel.org>
Tested-by: Yixun Lan <dlan@kernel.org>

-- 
Yixun Lan (dlan)

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

* Re: [PATCH v2 2/4] pci: spacemit: add DesignWare PCIe host controller driver
  2026-09-13  4:23 ` [PATCH v2 2/4] pci: spacemit: add DesignWare PCIe host controller driver Eric Chung
@ 2026-09-23 13:30   ` Yixun Lan
  2026-09-24 14:00     ` Neil Armstrong
  0 siblings, 1 reply; 9+ messages in thread
From: Yixun Lan @ 2026-09-23 13:30 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: u-boot-spacemit, u-boot, Tom Rini, Eric Chung, Tim Ouyang,
	Leo Liang, Scott Bambrough, Neil Armstrong, David Lechner,
	Julien Stephan, Johan Jonker, Siu Ming Tong, Lucien.Jheng,
	Huan Zhou, Michal Simek, Pranav Sanwal, Raymond Mao, Yixun Lan

Hi Neil,

On 12:23 Sun 13 Sep     , Eric Chung wrote:
> Add PCIe host controller driver for Spacemit K1 SoC using the
> Synopsys DesignWare PCIe core. Supports up to 3 ports.
> 
> Signed-off-by: Eric Chung <eric.chung@riscstar.com>
> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
> 
> ---
> v2:
> - Locate the phy by index instead.
> ---
>  drivers/pci/Kconfig            |   7 +
>  drivers/pci/Makefile           |   1 +
>  drivers/pci/pcie_dw_spacemit.c | 391 +++++++++++++++++++++++++++++++++++++++++
>  drivers/pci/pcie_dw_spacemit.h |  78 ++++++++
>  4 files changed, 477 insertions(+)
> 

Would you like to merge this patch via pci tree? otherwise, I could take all
of this series via spacemit custodian tree, let me know which way you'd prefer?

Thanks

-- 
Yixun Lan (dlan)

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

* Re: [PATCH v2 2/4] pci: spacemit: add DesignWare PCIe host controller driver
  2026-09-23 13:30   ` Yixun Lan
@ 2026-09-24 14:00     ` Neil Armstrong
  0 siblings, 0 replies; 9+ messages in thread
From: Neil Armstrong @ 2026-09-24 14:00 UTC (permalink / raw)
  To: Yixun Lan
  Cc: u-boot-spacemit, u-boot, Tom Rini, Eric Chung, Tim Ouyang,
	Leo Liang, Scott Bambrough, David Lechner, Julien Stephan,
	Johan Jonker, Siu Ming Tong, Lucien.Jheng, Huan Zhou,
	Michal Simek, Pranav Sanwal, Raymond Mao, Yixun Lan

Hi,

On 9/23/26 15:30, Yixun Lan wrote:
> Hi Neil,
> 
> On 12:23 Sun 13 Sep     , Eric Chung wrote:
>> Add PCIe host controller driver for Spacemit K1 SoC using the
>> Synopsys DesignWare PCIe core. Supports up to 3 ports.
>>
>> Signed-off-by: Eric Chung <eric.chung@riscstar.com>
>> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
>>
>> ---
>> v2:
>> - Locate the phy by index instead.
>> ---
>>   drivers/pci/Kconfig            |   7 +
>>   drivers/pci/Makefile           |   1 +
>>   drivers/pci/pcie_dw_spacemit.c | 391 +++++++++++++++++++++++++++++++++++++++++
>>   drivers/pci/pcie_dw_spacemit.h |  78 ++++++++
>>   4 files changed, 477 insertions(+)
>>
> 
> Would you like to merge this patch via pci tree? otherwise, I could take all
> of this series via spacemit custodian tree, let me know which way you'd prefer?

Feel free to pick it via your tree!

Thanks,
Neil

> 
> Thanks
> 


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

* Re: [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC
  2026-09-13  4:23 [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC Eric Chung
                   ` (4 preceding siblings ...)
  2026-09-23 13:16 ` [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC Yixun Lan
@ 2026-09-29 10:15 ` Yixun Lan
  5 siblings, 0 replies; 9+ messages in thread
From: Yixun Lan @ 2026-09-29 10:15 UTC (permalink / raw)
  To: u-boot-spacemit, u-boot, Eric Chung
  Cc: Yixun Lan, Tom Rini, Tim Ouyang, Leo Liang, Scott Bambrough,
	Neil Armstrong, David Lechner, Julien Stephan, Johan Jonker,
	Siu Ming Tong, Lucien.Jheng, Huan Zhou, Michal Simek,
	Pranav Sanwal, Raymond Mao, Yixun Lan


On Sun, 13 Sep 2026 12:23:09 +0800, Eric Chung wrote:
> 


Applied, thanks!

[1/4] phy: spacemit: add K1 PCIe/USB3 combo PHY driver
      https://git.u-boot-project.org/u-boot/custodians/u-boot-spacemit/-/commit/57eb5723d5feb3226cff9ac1d8379f0b31eb09b1
[2/4] pci: spacemit: add DesignWare PCIe host controller driver
      https://git.u-boot-project.org/u-boot/custodians/u-boot-spacemit/-/commit/c8764b8db670152ff8e3b393c8de52823bef51ec
[3/4] configs: k1: enable PCIe and NVMe support
      https://git.u-boot-project.org/u-boot/custodians/u-boot-spacemit/-/commit/d70d033928044754e9ac6ea103bfaea19b300816
[4/4] MAINTAINER: add K1 PCIe driver to Spacemit entry
      https://git.u-boot-project.org/u-boot/custodians/u-boot-spacemit/-/commit/dfa681ec397aed90bd13aa5e0e887ee533d41988

Best regards,
-- 
Yixun Lan <dlan@kernel.org>

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

end of thread, other threads:[~2026-09-29 10:15 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-13  4:23 [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC Eric Chung
2026-09-13  4:23 ` [PATCH v2 1/4] phy: spacemit: add K1 PCIe/USB3 combo PHY driver Eric Chung
2026-09-13  4:23 ` [PATCH v2 2/4] pci: spacemit: add DesignWare PCIe host controller driver Eric Chung
2026-09-23 13:30   ` Yixun Lan
2026-09-24 14:00     ` Neil Armstrong
2026-09-13  4:23 ` [PATCH v2 3/4] configs: k1: enable PCIe and NVMe support Eric Chung
2026-09-13  4:23 ` [PATCH v2 4/4] MAINTAINER: add K1 PCIe driver to Spacemit entry Eric Chung
2026-09-23 13:16 ` [PATCH v2 0/4] pci: enable designware pci and phy on spacemit k1 SoC Yixun Lan
2026-09-29 10:15 ` Yixun Lan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.