Devicetree
 help / color / mirror / Atom feed
* [PATCH v7 4/9] mmc: sdhci-of-k1: add comprehensive SDR tuning support
From: Iker Pedrosa @ 2026-04-13  7:24 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Yixun Lan
  Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
	Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
	spacemit, linux-kernel, Anand Moon, Trevor Gamblin,
	Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>

Implement software tuning algorithm to enable UHS-I SDR modes for SD
card operation and HS200 mode for eMMC. This adds both TX and RX delay
line tuning based on the SpacemiT K1 controller capabilities.

Algorithm features:
- Add tuning register definitions (RX_CFG, DLINE_CTRL, DLINE_CFG)
- Conditional tuning: only for high-speed modes (≥100MHz)
- TX tuning: configure transmit delay line with optimal values
  (dline_reg=0, delaycode=127) to ensure optimal signal output timing
- RX tuning: single-pass window detection algorithm testing full
  delay range (0-255) to find optimal receive timing window
- Retry mechanism: multiple fallback delays within optimal window
  for improved reliability

Tested-by: Anand Moon <linux.amoon@gmail.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
 drivers/mmc/host/sdhci-of-k1.c | 172 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 172 insertions(+)

diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c
index d9144537032a..37b0911e7cf2 100644
--- a/drivers/mmc/host/sdhci-of-k1.c
+++ b/drivers/mmc/host/sdhci-of-k1.c
@@ -69,6 +69,28 @@
 #define  SDHC_PHY_DRIVE_SEL		GENMASK(2, 0)
 #define  SDHC_RX_BIAS_CTRL		BIT(5)
 
+#define SPACEMIT_SDHC_RX_CFG_REG        0x118
+#define  SDHC_RX_SDCLK_SEL0_MASK        GENMASK(1, 0)
+#define  SDHC_RX_SDCLK_SEL1_MASK        GENMASK(3, 2)
+#define  SDHC_RX_SDCLK_SEL1             FIELD_PREP(SDHC_RX_SDCLK_SEL1_MASK, 1)
+
+#define SPACEMIT_SDHC_DLINE_CTRL_REG    0x130
+#define  SDHC_DLINE_PU                  BIT(0)
+#define  SDHC_RX_DLINE_CODE_MASK        GENMASK(23, 16)
+#define  SDHC_TX_DLINE_CODE_MASK        GENMASK(31, 24)
+
+#define SPACEMIT_SDHC_DLINE_CFG_REG     0x134
+#define  SDHC_RX_DLINE_REG_MASK         GENMASK(7, 0)
+#define  SDHC_RX_DLINE_GAIN             BIT(8)
+#define  SDHC_TX_DLINE_REG_MASK         GENMASK(23, 16)
+
+#define SPACEMIT_RX_DLINE_REG		9
+#define SPACEMIT_RX_TUNE_DELAY_MIN	0x0
+#define SPACEMIT_RX_TUNE_DELAY_MAX	0xFF
+
+#define SPACEMIT_TX_TUNING_DLINE_REG	0x00
+#define SPACEMIT_TX_TUNING_DELAYCODE	127
+
 struct spacemit_sdhci_host {
 	struct clk *clk_core;
 	struct clk *clk_io;
@@ -96,6 +118,50 @@ static inline void spacemit_sdhci_clrsetbits(struct sdhci_host *host, u32 clr, u
 	sdhci_writel(host, val, reg);
 }
 
+static void spacemit_sdhci_set_rx_delay(struct sdhci_host *host, u8 delay)
+{
+	spacemit_sdhci_clrsetbits(host, SDHC_RX_DLINE_CODE_MASK,
+				  FIELD_PREP(SDHC_RX_DLINE_CODE_MASK, delay),
+				  SPACEMIT_SDHC_DLINE_CTRL_REG);
+}
+
+static void spacemit_sdhci_set_tx_delay(struct sdhci_host *host, u8 delay)
+{
+	spacemit_sdhci_clrsetbits(host, SDHC_TX_DLINE_CODE_MASK,
+				  FIELD_PREP(SDHC_TX_DLINE_CODE_MASK, delay),
+				  SPACEMIT_SDHC_DLINE_CTRL_REG);
+}
+
+static void spacemit_sdhci_set_tx_dline_reg(struct sdhci_host *host, u8 dline_reg)
+{
+	spacemit_sdhci_clrsetbits(host, SDHC_TX_DLINE_REG_MASK,
+				  FIELD_PREP(SDHC_TX_DLINE_REG_MASK, dline_reg),
+				  SPACEMIT_SDHC_DLINE_CFG_REG);
+}
+
+static void spacemit_sdhci_tx_tuning_prepare(struct sdhci_host *host)
+{
+	spacemit_sdhci_setbits(host, SDHC_TX_MUX_SEL, SPACEMIT_SDHC_TX_CFG_REG);
+	spacemit_sdhci_setbits(host, SDHC_DLINE_PU, SPACEMIT_SDHC_DLINE_CTRL_REG);
+	udelay(5);
+}
+
+static void spacemit_sdhci_prepare_tuning(struct sdhci_host *host)
+{
+	spacemit_sdhci_clrsetbits(host, SDHC_RX_DLINE_REG_MASK,
+				  FIELD_PREP(SDHC_RX_DLINE_REG_MASK, SPACEMIT_RX_DLINE_REG),
+				  SPACEMIT_SDHC_DLINE_CFG_REG);
+
+	spacemit_sdhci_setbits(host, SDHC_DLINE_PU, SPACEMIT_SDHC_DLINE_CTRL_REG);
+	udelay(5);
+
+	spacemit_sdhci_clrsetbits(host, SDHC_RX_SDCLK_SEL1_MASK, SDHC_RX_SDCLK_SEL1,
+				  SPACEMIT_SDHC_RX_CFG_REG);
+
+	if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200)
+		spacemit_sdhci_setbits(host, SDHC_HS200_USE_RFIFO, SPACEMIT_SDHC_PHY_FUNC_REG);
+}
+
 static void spacemit_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
 	sdhci_reset(host, mask);
@@ -191,6 +257,111 @@ static unsigned int spacemit_sdhci_clk_get_max_clock(struct sdhci_host *host)
 	return clk_get_rate(pltfm_host->clk);
 }
 
+static int spacemit_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+	int current_len = 0, current_start = 0;
+	int max_pass_len = 0, max_pass_start = 0;
+	struct mmc_host *mmc = host->mmc;
+	struct mmc_ios ios = mmc->ios;
+	u8 final_delay;
+	int ret = 0;
+	int i;
+
+	/*
+	 * Tuning is required for SDR50/SDR104, HS200/HS400 cards and
+	 * if clock frequency is greater than 100MHz in these modes.
+	 */
+	if (host->clock < 100 * 1000 * 1000 ||
+	    !(ios.timing == MMC_TIMING_MMC_HS200 ||
+	      ios.timing == MMC_TIMING_UHS_SDR50 ||
+	      ios.timing == MMC_TIMING_UHS_SDR104))
+		return 0;
+
+	if (mmc->caps2 & MMC_CAP2_NO_MMC) {
+		spacemit_sdhci_set_tx_dline_reg(host, SPACEMIT_TX_TUNING_DLINE_REG);
+		spacemit_sdhci_set_tx_delay(host, SPACEMIT_TX_TUNING_DELAYCODE);
+		spacemit_sdhci_tx_tuning_prepare(host);
+
+		dev_dbg(mmc_dev(host->mmc), "TX tuning: dline_reg=%d, delaycode=%d\n",
+			SPACEMIT_TX_TUNING_DLINE_REG, SPACEMIT_TX_TUNING_DELAYCODE);
+	}
+
+	spacemit_sdhci_prepare_tuning(host);
+
+	for (i = SPACEMIT_RX_TUNE_DELAY_MIN; i <= SPACEMIT_RX_TUNE_DELAY_MAX; i++) {
+		spacemit_sdhci_set_rx_delay(host, i);
+		ret = mmc_send_tuning(host->mmc, opcode, NULL);
+
+		dev_dbg(mmc_dev(host->mmc), "RX delay %d: %s\n",
+			i, ret == 0 ? "pass" : "fail");
+
+		if (ret == 0) {
+			/* Test passed - extend current window */
+			if (current_len == 0)
+				current_start = i;
+			current_len++;
+		} else {
+			/* Test failed - check if current window is best so far */
+			if (current_len > max_pass_len) {
+				max_pass_len = current_len;
+				max_pass_start = current_start;
+			}
+			current_len = 0;
+		}
+	}
+
+	if (current_len > max_pass_len) {
+		max_pass_len = current_len;
+		max_pass_start = current_start;
+	}
+
+	if (max_pass_len < 3) {
+		dev_err(mmc_dev(host->mmc), "Tuning failed: no stable window found\n");
+		return -EIO;
+	}
+
+	final_delay = max_pass_start + max_pass_len / 2;
+	spacemit_sdhci_set_rx_delay(host, final_delay);
+	ret = mmc_send_tuning(host->mmc, opcode, NULL);
+	if (ret) {
+		u8 retry_delays[] = {
+			max_pass_start + max_pass_len / 4,
+			max_pass_start + (3 * max_pass_len) / 4,
+			max_pass_start,
+			max_pass_start + max_pass_len - 1
+		};
+		int retry_count = ARRAY_SIZE(retry_delays);
+
+		dev_warn(mmc_dev(mmc), "Primary delay %d failed, trying alternatives\n",
+			 final_delay);
+
+		for (i = 0; i < retry_count; i++) {
+			if (retry_delays[i] >= SPACEMIT_RX_TUNE_DELAY_MIN &&
+			    retry_delays[i] <= SPACEMIT_RX_TUNE_DELAY_MAX) {
+				spacemit_sdhci_set_rx_delay(host, retry_delays[i]);
+				ret = mmc_send_tuning(host->mmc, opcode, NULL);
+				if (!ret) {
+					final_delay = retry_delays[i];
+					dev_info(mmc_dev(mmc), "Retry successful with delay %d\n",
+						 final_delay);
+					break;
+				}
+			}
+		}
+
+		if (ret) {
+			dev_err(mmc_dev(mmc), "All retry attempts failed\n");
+			return -EIO;
+		}
+	}
+
+	dev_dbg(mmc_dev(host->mmc),
+		"Tuning successful: window %d-%d, using delay %d\n",
+		max_pass_start, max_pass_start + max_pass_len - 1, final_delay);
+
+	return 0;
+}
+
 static int spacemit_sdhci_pre_select_hs400(struct mmc_host *mmc)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
@@ -326,6 +497,7 @@ static const struct sdhci_ops spacemit_sdhci_ops = {
 	.set_bus_width		= sdhci_set_bus_width,
 	.set_clock		= spacemit_sdhci_set_clock,
 	.set_uhs_signaling	= spacemit_sdhci_set_uhs_signaling,
+	.platform_execute_tuning = spacemit_sdhci_execute_tuning,
 };
 
 static const struct sdhci_pltfm_data spacemit_sdhci_k1_pdata = {

-- 
2.53.0


^ permalink raw reply related

* [PATCH v7 3/9] mmc: sdhci-of-k1: add regulator and pinctrl voltage switching support
From: Iker Pedrosa @ 2026-04-13  7:24 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Yixun Lan
  Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
	Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
	spacemit, linux-kernel, Anand Moon, Trevor Gamblin,
	Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>

Add voltage switching infrastructure for UHS-I modes by integrating both
regulator framework (for supply voltage control) and pinctrl state
switching (for pin drive strength optimization).

- Add regulator supply parsing and voltage switching callback
- Add optional pinctrl state switching between "default" (3.3V) and
  "state_uhs" (1.8V) configurations
- Enable coordinated voltage and pin configuration changes for UHS modes

This provides complete voltage switching support while maintaining
backward compatibility when pinctrl states are not defined.

Tested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
 drivers/mmc/host/sdhci-of-k1.c | 72 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c
index 0dd06fc19b85..d9144537032a 100644
--- a/drivers/mmc/host/sdhci-of-k1.c
+++ b/drivers/mmc/host/sdhci-of-k1.c
@@ -16,6 +16,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/reset.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 
 #include "sdhci.h"
@@ -71,6 +72,9 @@
 struct spacemit_sdhci_host {
 	struct clk *clk_core;
 	struct clk *clk_io;
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pinctrl_default;
+	struct pinctrl_state *pinctrl_uhs;
 };
 
 /* All helper functions will update clr/set while preserve rest bits */
@@ -219,6 +223,46 @@ static void spacemit_sdhci_pre_hs400_to_hs200(struct mmc_host *mmc)
 			       SPACEMIT_SDHC_PHY_CTRL_REG);
 }
 
+static int spacemit_sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
+						      struct mmc_ios *ios)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct spacemit_sdhci_host *sdhst = sdhci_pltfm_priv(pltfm_host);
+	struct pinctrl_state *state;
+	int ret;
+
+	ret = sdhci_start_signal_voltage_switch(mmc, ios);
+	if (ret)
+		return ret;
+
+	if (!sdhst->pinctrl)
+		return 0;
+
+	/* Select appropriate pinctrl state based on signal voltage */
+	switch (ios->signal_voltage) {
+	case MMC_SIGNAL_VOLTAGE_330:
+		state = sdhst->pinctrl_default;
+		break;
+	case MMC_SIGNAL_VOLTAGE_180:
+		state = sdhst->pinctrl_uhs;
+		break;
+	default:
+		dev_warn(mmc_dev(mmc), "unsupported voltage %d\n", ios->signal_voltage);
+		return 0;
+	}
+
+	ret = pinctrl_select_state(sdhst->pinctrl, state);
+	if (ret) {
+		dev_warn(mmc_dev(mmc), "failed to select pinctrl state: %d\n", ret);
+		return 0;
+	}
+	dev_dbg(mmc_dev(mmc), "switched to %s pinctrl state\n",
+		ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180 ? "UHS" : "default");
+
+	return 0;
+}
+
 static inline int spacemit_sdhci_get_clocks(struct device *dev,
 					    struct sdhci_pltfm_host *pltfm_host)
 {
@@ -252,6 +296,30 @@ static inline int spacemit_sdhci_get_resets(struct device *dev)
 	return 0;
 }
 
+static inline void spacemit_sdhci_get_pins(struct device *dev,
+					   struct sdhci_pltfm_host *pltfm_host)
+{
+	struct spacemit_sdhci_host *sdhst = sdhci_pltfm_priv(pltfm_host);
+
+	sdhst->pinctrl = devm_pinctrl_get(dev);
+	if (IS_ERR(sdhst->pinctrl)) {
+		sdhst->pinctrl = NULL;
+		dev_dbg(dev, "pinctrl not available, voltage switching will work without it\n");
+		return;
+	}
+
+	sdhst->pinctrl_default = pinctrl_lookup_state(sdhst->pinctrl, "default");
+	if (IS_ERR(sdhst->pinctrl_default))
+		sdhst->pinctrl_default = NULL;
+
+	sdhst->pinctrl_uhs = pinctrl_lookup_state(sdhst->pinctrl, "uhs");
+	if (IS_ERR(sdhst->pinctrl_uhs))
+		sdhst->pinctrl_uhs = NULL;
+
+	dev_dbg(dev, "pinctrl setup: default=%p, uhs=%p\n",
+		sdhst->pinctrl_default, sdhst->pinctrl_uhs);
+}
+
 static const struct sdhci_ops spacemit_sdhci_ops = {
 	.get_max_clock		= spacemit_sdhci_clk_get_max_clock,
 	.reset			= spacemit_sdhci_reset,
@@ -324,6 +392,10 @@ static int spacemit_sdhci_probe(struct platform_device *pdev)
 
 	host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
 
+	spacemit_sdhci_get_pins(dev, pltfm_host);
+
+	host->mmc_host_ops.start_signal_voltage_switch = spacemit_sdhci_start_signal_voltage_switch;
+
 	ret = spacemit_sdhci_get_clocks(dev, pltfm_host);
 	if (ret)
 		goto err_pltfm;

-- 
2.53.0


^ permalink raw reply related

* [PATCH v7 2/9] mmc: sdhci-of-k1: enable essential clock infrastructure for SD operation
From: Iker Pedrosa @ 2026-04-13  7:24 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Yixun Lan
  Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
	Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
	spacemit, linux-kernel, Anand Moon, Trevor Gamblin,
	Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>

Ensure SD card pins receive clock signals by enabling pad clock
generation and overriding automatic clock gating. Required for all SD
operation modes.

The SDHC_GEN_PAD_CLK_ON setting in LEGACY_CTRL_REG is safe for both SD
and eMMC operation as both protocols use the same physical MMC interface
pins and require proper clock signal generation at the hardware level
for signal integrity and timing.

Additional SD-specific clock overrides (SDHC_OVRRD_CLK_OEN and
SDHC_FORCE_CLK_ON) are conditionally applied only for SD-only
controllers to handle removable card scenarios.

Tested-by: Anand Moon <linux.amoon@gmail.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
 drivers/mmc/host/sdhci-of-k1.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c
index 455656f9842d..0dd06fc19b85 100644
--- a/drivers/mmc/host/sdhci-of-k1.c
+++ b/drivers/mmc/host/sdhci-of-k1.c
@@ -21,6 +21,13 @@
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 
+#define SPACEMIT_SDHC_OP_EXT_REG	0x108
+#define  SDHC_OVRRD_CLK_OEN		BIT(11)
+#define  SDHC_FORCE_CLK_ON		BIT(12)
+
+#define SPACEMIT_SDHC_LEGACY_CTRL_REG	0x10C
+#define  SDHC_GEN_PAD_CLK_ON		BIT(6)
+
 #define SPACEMIT_SDHC_MMC_CTRL_REG	0x114
 #define  SDHC_MISC_INT_EN		BIT(1)
 #define  SDHC_MISC_INT			BIT(2)
@@ -101,6 +108,12 @@ static void spacemit_sdhci_reset(struct sdhci_host *host, u8 mask)
 
 	if (!(host->mmc->caps2 & MMC_CAP2_NO_MMC))
 		spacemit_sdhci_setbits(host, SDHC_MMC_CARD_MODE, SPACEMIT_SDHC_MMC_CTRL_REG);
+
+	spacemit_sdhci_setbits(host, SDHC_GEN_PAD_CLK_ON, SPACEMIT_SDHC_LEGACY_CTRL_REG);
+
+	if (host->mmc->caps2 & MMC_CAP2_NO_MMC)
+		spacemit_sdhci_setbits(host, SDHC_OVRRD_CLK_OEN | SDHC_FORCE_CLK_ON,
+				       SPACEMIT_SDHC_OP_EXT_REG);
 }
 
 static void spacemit_sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned int timing)

-- 
2.53.0


^ permalink raw reply related

* [PATCH v7 1/9] dt-bindings: mmc: spacemit,sdhci: add pinctrl support for voltage switching
From: Iker Pedrosa @ 2026-04-13  7:24 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Yixun Lan
  Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
	Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
	spacemit, linux-kernel
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>

Document pinctrl properties to support voltage-dependent pin
configuration switching for UHS-I SD card modes.

Add optional pinctrl-names property with two states:
- "default": For 3.3V operation with standard drive strength
- "state_uhs": For 1.8V operation with optimized drive strength

These pinctrl states allow the SDHCI driver to coordinate voltage
switching with pin configuration changes, ensuring proper signal
integrity during UHS-I mode transitions.

Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
 Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml b/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml
index 9a055d963a7f..34d202af909f 100644
--- a/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml
@@ -44,6 +44,18 @@ properties:
       - const: axi
       - const: sdh
 
+  pinctrl-names:
+    minItems: 1
+    items:
+      - const: default
+      - const: uhs
+
+  pinctrl-0:
+    description: Default pinctrl state for 3.3V operation
+
+  pinctrl-1:
+    description: Optional pinctrl state for 1.8V UHS operation with "uhs" name
+
 required:
   - compatible
   - reg
@@ -62,4 +74,7 @@ examples:
       interrupt-parent = <&plic>;
       clocks = <&clk_apmu 10>, <&clk_apmu 13>;
       clock-names = "core", "io";
+      pinctrl-names = "default", "uhs";
+      pinctrl-0 = <&sdhci_default_cfg>;
+      pinctrl-1 = <&sdhci_uhs_cfg>;
     };

-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH 2/2] media: i2c: add os02g10 image sensor driver
From: Tarang Raval @ 2026-04-13  7:20 UTC (permalink / raw)
  To: Elgin Perumbilly, sakari.ailus@linux.intel.com
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Hans Verkuil, Hans de Goede, Vladimir Zapolskiy,
	Laurent Pinchart, Xiaolei Wang, Walter Werner Schneider,
	Kate Hsuan, Sylvain Petinot, Mehdi Djait, Heimir Thor Sverrisson,
	linux-media@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <20260411094723.129738-3-elgin.perumbilly@siliconsignals.io>

Hi Elgin,

Thanks for sending these drivers.

A few minor points are listed below, please take a look.

> Add a v4l2 subdevice driver for the Omnivision os02g10 sensor.
>
> The Omnivision os02g10 is a CMOS image sensor with an active array size of
> 1920 x 1080.
>
> The following features are supported:
> - Manual exposure an gain control support
> - vblank/hblank control support
> - vflip/hflip control support
> - Test pattern control support
> - Supported resolution: 1920 x 1080 @ 30fps (SBGGR10)
>
> Signed-off-by: Elgin Perumbilly <elgin.perumbilly@siliconsignals.io>
> ---
>  MAINTAINERS                 |    1 +
>  drivers/media/i2c/Kconfig   |   10 +
>  drivers/media/i2c/Makefile  |    1 +
>  drivers/media/i2c/os02g10.c | 1010 +++++++++++++++++++++++++++++++++++
>  4 files changed, 1022 insertions(+)
>  create mode 100644 drivers/media/i2c/os02g10.c

...

> +#define OS02G10_REG_SIF_CTRL                   OS02G10_PAGE_REG8(0x02, 0x5e)
> +#define OS02G10_ORIENTATION_BAYER_FIX          0x32

The above two definitions belong to Page 2, Please move them to the Page 2
block below.

> +/* Page 2 */
> +#define OS02G10_REG_V_START                    OS02G10_PAGE_REG16(0x02, 0xa0)
> +#define OS02G10_REG_V_SIZE                     OS02G10_PAGE_REG16(0x02, 0xa2)
> +#define OS02G10_REG_H_START                    OS02G10_PAGE_REG16(0x02, 0xa4)
> +#define OS02G10_REG_H_SIZE                     OS02G10_PAGE_REG16(0x02, 0xa6)
> +
> +#define OS02G10_LINK_FREQ_720MHZ               (720 * HZ_PER_MHZ)

...

> +static int os02g10_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +       struct os02g10 *os02g10 = container_of_const(ctrl->handler,
> +                                                    struct os02g10, handler);
> +       struct v4l2_subdev_state *state;
> +       struct v4l2_mbus_framefmt *fmt;
> +       int ret = 0;
> +
> +       state = v4l2_subdev_get_locked_active_state(&os02g10->sd);
> +       fmt = v4l2_subdev_state_get_format(state, 0);
> +
> +       if (ctrl->id == V4L2_CID_VBLANK) {
> +               /* Honour the VBLANK limits when setting exposure */
> +               s64 max = fmt->height + ctrl->val - OS02G10_EXPOSURE_MARGIN;
> +
> +               ret = __v4l2_ctrl_modify_range(os02g10->exposure,
> +                                              os02g10->exposure->minimum, max,
> +                                              os02g10->exposure->step,
> +                                              os02g10->exposure->default_value);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       if (pm_runtime_get_if_in_use(os02g10->dev) == 0)

Please use pm_runtime_get_if_active.

> +               return 0;
> +
> +       switch (ctrl->id) {
> +       case V4L2_CID_EXPOSURE:
> +               os02g10_write(os02g10, OS02G10_REG_LONG_EXPOSURE, ctrl->val, &ret);
> +               break;
> +       case V4L2_CID_ANALOGUE_GAIN:
> +               os02g10_write(os02g10, OS02G10_REG_ANALOG_GAIN, ctrl->val, &ret);
> +               break;
> +       case V4L2_CID_DIGITAL_GAIN:
> +               os02g10_write(os02g10, OS02G10_REG_DIGITAL_GAIN_L,
> +                             (ctrl->val & 0xff), &ret);
> +               os02g10_write(os02g10, OS02G10_REG_DIGITAL_GAIN_H,
> +                             ((ctrl->val >> 8) & 0x7), &ret);
> +               break;
> +       case V4L2_CID_VBLANK:
> +               u64 vts = ctrl->val + fmt->height;
> +
> +               os02g10_update_bits(os02g10, OS02G10_REG_FRAME_EXP_SEPERATE_EN,
> +                                   OS02G10_FRAME_EXP_SEPERATE_EN,
> +                                   OS02G10_FRAME_EXP_SEPERATE_EN, &ret);
> +               os02g10_write(os02g10, OS02G10_REG_FRAME_LENGTH, vts, &ret);
> +               break;
> +       case V4L2_CID_HFLIP:
> +       case V4L2_CID_VFLIP:
> +               os02g10_write(os02g10, OS02G10_REG_FLIP_MIRROR,
> +                             os02g10->hflip->val | os02g10->vflip->val << 1,
> +                             &ret);
> +               os02g10_write(os02g10, OS02G10_REG_SIF_CTRL,
> +                             OS02G10_ORIENTATION_BAYER_FIX, &ret);
> +               break;
> +       case V4L2_CID_TEST_PATTERN:
> +               os02g10_update_bits(os02g10,
> +                                   OS02G10_REG_TEST_PATTERN,
> +                                   OS02G10_TEST_PATTERN_ENABLE,
> +                                   ctrl->val ? OS02G10_TEST_PATTERN_ENABLE : 0,
> +                                   &ret);
> +               break;
> +       default:
> +               ret = -EINVAL;
> +               break;
> +       }
> +       os02g10_write(os02g10, OS02G10_REG_FRAME_SYNC, 0x01, &ret);
> +
> +       pm_runtime_put(os02g10->dev);
> +
> +       return ret;
> +}

...

> +static int os02g10_init_controls(struct os02g10 *os02g10)
> +{
> +       const struct os02g10_mode *mode = &supported_modes[0];
> +       u64 vblank_def, hblank_def, exp_max, pixel_rate;
> +       struct v4l2_fwnode_device_properties props;
> +       struct v4l2_ctrl_handler *ctrl_hdlr;
> +       int ret;
> +
> +       ctrl_hdlr = &os02g10->handler;
> +       v4l2_ctrl_handler_init(ctrl_hdlr, 12);
> +
> +       /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
> +       pixel_rate = div_u64(OS02G10_LINK_FREQ_720MHZ * 2 * 2, 10);
> +       v4l2_ctrl_new_std(ctrl_hdlr, &os02g10_ctrl_ops, V4L2_CID_PIXEL_RATE, 0,
> +                         pixel_rate, 1, pixel_rate);
> +
> +       os02g10->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &os02g10_ctrl_ops,
> +                                                   V4L2_CID_LINK_FREQ,
> +                                                   os02g10->link_freq_index,
> +                                                   0, link_freq_menu_items);
> +       if (os02g10->link_freq)
> +               os02g10->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> +       hblank_def = mode->hts_def - mode->width;

Please use (mode->hts_def * 2) here, otherwise hblank_def can end up with
negative value.

Also, add a comment mentioning that the datasheet does not provide any
information about the unit of hts.

> +       os02g10->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &os02g10_ctrl_ops,
> +                                           V4L2_CID_HBLANK, hblank_def, hblank_def,
> +                                           1, hblank_def);
> +       if (os02g10->hblank)
> +               os02g10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> +       vblank_def = mode->vts_def - mode->height;
> +       os02g10->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &os02g10_ctrl_ops,
> +                                           V4L2_CID_VBLANK, vblank_def,
> +                                           OS02G10_FRAME_LENGTH_MAX - mode->height,
> +                                           1, vblank_def);
> +

...

> +static int os02g10_disable_streams(struct v4l2_subdev *sd,
> +                                  struct v4l2_subdev_state *state, u32 pad,
> +                                  u64 streams_mask)
> +{
> +       struct os02g10 *os02g10 = to_os02g10(sd);
> +       int ret;
> +
> +       ret = os02g10_write(os02g10, OS02G10_REG_STREAM_CTRL,
> +                           OS02G10_STREAM_CTRL_OFF, NULL);
> +       if (ret)
> +               dev_err(os02g10->dev, "%s failed to set stream\n", __func__);

Remove __func__ from the error message; it is unnecessary.

Also, please use a more meaningful error message

> +
> +       __v4l2_ctrl_grab(os02g10->vflip, false);
> +       __v4l2_ctrl_grab(os02g10->hflip, false);
> +
> +       pm_runtime_put(os02g10->dev);
> +
> +       return ret;
> +}
> +
> +static int os02g10_get_selection(struct v4l2_subdev *sd,
> +                      struct v4l2_subdev_state *sd_state,
> +                      struct v4l2_subdev_selection *sel)
> +{
> +   switch (sel->target)
> +   case V4L2_SEL_TGT_CROP:
> +   case V4L2_SEL_TGT_NATIVE_SIZE:
> +         sel->r = os02g10_native_area;

V4L2_SEL_TGT_CROP should use the active area, and V4L2_SEL_TGT_CROP_BOUNDS
should use the native area. Please update this accordingly.

> +         return 0;
> +   case V4L2_SEL_TGT_CROP_DEFAULT:
> +   case V4L2_SEL_TGT_CROP_BOUNDS:
> +         sel->r = os02g10_active_area;
> +         return 0;
> +   default:
> +         return -EINVAL;
> +   }
> +}

...

> +static struct i2c_driver os02g10_driver = {
> +       .driver = {
> +               .name = "os02g10",
> +               .pm = pm_ptr(&os02g10_pm_ops),
> +               .of_match_table = os02g10_id,
> +       },
> +       .probe = os02g10_probe,
> +       .remove = os02g10_remove,
> +};
> +module_i2c_driver(os02g10_driver);
> +
> +MODULE_DESCRIPTION("OS02G10 Camera Sensor Driver");
> +MODULE_AUTHOR("Tarang Raval <tarang.raval@siliconsignals.io>");

You can add your name here as well.

> +MODULE_LICENSE("GPL");
> --
> 2.34.1

Apart from the above comments, the driver looks good to me.

Reviewed-by: Tarang Raval <tarang.raval@siliconsignals.io>

Best Regards,
Tarang

^ permalink raw reply

* RE: [PATCH v7 2/2] iio: dac: ad5706r: Add support for AD5706R DAC
From: Torreno, Alexis Czezar @ 2026-04-13  7:15 UTC (permalink / raw)
  To: David Lechner, Lars-Peter Clausen, Hennerich, Michael,
	Jonathan Cameron, Sa, Nuno, Andy Shevchenko, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, Andy Shevchenko
In-Reply-To: <cdfb9deb-2439-413b-8c20-3c6ad6a81ce3@baylibre.com>

> > +static int ad5706r_regmap_write(void *context, const void *data,
> > +size_t count) {
> > +	struct ad5706r_state *st = context;
> > +	unsigned int num_bytes, val;
> > +	u16 reg;
> > +
> > +	if (count != 4)
> > +		return -EINVAL;
> > +
> > +	reg = get_unaligned_be16(data);
> > +	num_bytes = ad5706r_reg_len(reg);
> > +
> > +	struct spi_transfer xfer = {
> > +		.tx_buf = st->tx_buf,
> > +		.len = num_bytes + 2,
> > +	};
> > +
> > +	val = get_unaligned_be32(data);
> > +	put_unaligned_be32(val, &st->tx_buf[0]);
> 
> Can't we just do memcpy() instead of swapping the byte order twice?

This was memcpy before, was changed to this for consistency as per Andy's
suggestion. It was during v5.

Removal of this plus the other mem* commands allowed removal of string.h
in the headers.

> 
> > +
> > +	/* For single byte, copy the data to the correct position */
> > +	if (num_bytes == AD5706R_SINGLE_BYTE_LEN)
> > +		st->tx_buf[2] = st->tx_buf[3];
> > +
> > +	return spi_sync_transfer(st->spi, &xfer, 1);
> 
> There isn't any special paramters in the xfer struct, so spi_write() should work
> here and save a bit of code.
> 
> 	return spi_write(st->spi, data, num_bytes);

Back in v3-v4, Joathan suggested this to be spi_write_then_read() as it was much safer,
but I requested to keep it this way since I would be adding more features to this driver
like changing spi_speeds, which cannot be done if using spi_write_then_read
 
> 
> > +}
> > +
> > +static int ad5706r_regmap_read(void *context, const void *reg_buf,
> > +			       size_t reg_size, void *val_buf, size_t val_size) {
> > +	struct ad5706r_state *st = context;
> > +	unsigned int num_bytes;
> > +	u16 reg, cmd, val;
> > +	int ret;
> > +
> > +	if (reg_size != 2 || val_size != 2)
> > +		return -EINVAL;
> > +
> > +	reg = get_unaligned_be16(reg_buf);
> > +	num_bytes = ad5706r_reg_len(reg);
> > +
> > +	/* Full duplex, device responds immediately after command */
> > +	struct spi_transfer xfer = {
> > +		.tx_buf = st->tx_buf,
> > +		.rx_buf = st->rx_buf,
> > +		.len = 2 + num_bytes,
> > +	};
> > +
> > +	cmd = AD5706R_RD_MASK | (reg & AD5706R_ADDR_MASK);
> > +	put_unaligned_be16(cmd, &st->tx_buf[0]);
> > +	put_unaligned_be16(0, &st->tx_buf[2]);
> 
> Do we actually need to write 0s while reading?
> 
> Usually, we would just do a spi_write_then_read for something like this.

Technically it's a don't care data, zero just makes it cleaner signals during debug

Discussed spi_write_then_read in a comment above

> 
> > +
> > +	ret = spi_sync_transfer(st->spi, &xfer, 1);
> > +	if (ret)
> > +		return ret;
> > +
> 
> 
> > +	/* Extract value from response (skip 2-byte command echo) */
> > +	if (num_bytes == AD5706R_SINGLE_BYTE_LEN)
> > +		val = st->rx_buf[2];
> > +	else if (num_bytes == AD5706R_DOUBLE_BYTE_LEN)
> > +		val = get_unaligned_be16(&st->rx_buf[2]);
> > +	else
> > +		return -EINVAL;
> > +
> > +	put_unaligned_be16(val, val_buf);
> 
> Can't this all be simplified to memcpy(val_buf, &st->rx_buf[2], num_bytes); ?
> 
> Or the whole thing simplified to:
> 
> 	return spi_write_then_read(st->spi, reg_buf, 2, val_buf, num_bytes);
> 

as discussed above about mem* and spi_write_then_read

^ permalink raw reply

* Re: [PATCH v2 13/13] arm64: defconfig: Enable I3C and SPD5118 hwmon
From: Krzysztof Kozlowski @ 2026-04-13  7:12 UTC (permalink / raw)
  To: Akhil R
  Cc: Frank.Li, acpica-devel, alexandre.belloni, conor+dt, devicetree,
	ebiggers, krzk+dt, lenb, linux-acpi, linux-hwmon, linux-i3c,
	linux-kernel, linux, miquel.raynal, p.zabel, rafael, robh,
	sakari.ailus, wsa+renesas, smangipudi
In-Reply-To: <20260413065747.31834-1-akhilrajeev@nvidia.com>

On 13/04/2026 08:57, Akhil R wrote:
>>> Isn't I3C needed for SPD5118. Otherwise I understand even less from this
>>> rationale - why I3C is being enabled here?
>>>
>>> And before author asks what do I want to here: no, it is author's job to
>>> convince me to accept I3C in defconfig. Not mine.
>>
>> BTW, all this was asked at v1 and author did not improve the commit msg
>> beside giving quite broad/unspecific "Vera".
> 
> If I am not wrong, the ask in v1 was to specify the product which this is
> getting used - 'Vera' it is. I do not know why you would think it is
> unspecific.

I already said why. Because I Googled it and Google told me it can be
"architecture". And no, you do not use SPD5118 on architecture.

> 
> As Thierry and Guenter mentioned, the lack of policy and 'mix of both' in
> the defconfig makes it quite difficult to understand what could genuinely
> be convincing other than putting down every little detail or do a trial
> and error.

I think the main problem is that people forgot that commits must answer
WHY you are doing this. Now my assumption is that people sending
defconfigs do not understand why they are doing it, therefore they
cannot explain "why" in commit msg.

Look, find me in following nvidia patches any answers to why this change
is needed:

https://lore.kernel.org/all/20260409131340.168556-7-pshete@nvidia.com/
https://lore.kernel.org/all/20240829134252.49661-1-jonathanh@nvidia.com/
https://lore.kernel.org/all/20240509215808.126217-1-bwicaksono@nvidia.com/

I understand that I can clarify what sort of answers to "why?" I expect.
but lack of such clarification is not excuse to not provide ANY
explanation in commit msg.

Basically it is logic like:
"Uh, I don't how to explain this change, why do we need it, why is it
good, why am I doing that...anyway, let's send it!"

Why doing something in the first place if one does not know the reason
behind?

Best regards,
Krzysztof

^ permalink raw reply

* Re: Phandles
From: Kyle Bonnici @ 2026-04-13  7:10 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Herve Codina, devicetree-compiler@vger.kernel.org, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, devicetree@vger.kernel.org
In-Reply-To: <00f0d18e-feba-45cd-af92-f737c9b965ef@kernel.org>



> On 13 Apr 2026, at 08:37, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> 
> On 12/04/2026 18:37, Kyle Bonnici wrote:
>>>>> Case 1:
>>>>> / {
>>>>>    node1 {
>>>>>         pwms = <1 &pwm0 1 20 PWM_POLARITY_NORMAL>;
>>>>> 
>>>>>         Here the first cell '1' is not a phandle.  
>>>> 
>>>> Here the compiler is making an assumption here that all `pwms` properties must be specifier properties and all use `pwm` specifier.
>>> 
>>> I think the purpose of 'select: true' is to have the binding always applied:
>>> https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/pwm/pwm-consumer.yaml#L15
>>> 
>> 
>> 
>> I’m having trouble finding where the Devicetree Specification (v0.4) mandates that all binding systems must extend dt-schema. 
>> Since this requirement isn't explicitly in the spec, it follows that the WARNING_PROPERTY_PHANDLE_CELLS validation belongs in dt-validate rather than within dtc itself.
> 
> 
> So you want to have a property with values not being phandle? The spec
> defines that properties like "pwm" must contain "value of properties
> with a phandle value type". Therefore what does '1' represents in your
> example?

I am just building and maintaining an LSP to assists Zephyr and Linux developers alike and what is technically
allowed in Zephyr is not allowed in Linux. The issue here is that DTC is warning zephyr users about it. 
I also find my self in the wrong to enforce these types for Zephyr dts usage given all documentation I have seen 
so far. 

> 
> Best regards,
> Krzysztof


^ permalink raw reply

* Re: [PATCH RFC 3/4] clk: qcom: tcsrcc-glymur: Migrate tcsr_pcie_N_clkref_en to clk_ref common helper
From: Qiang Yu @ 2026-04-13  7:06 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Taniya Das, Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, johan,
	linux-arm-msm, linux-clk, devicetree, linux-kernel
In-Reply-To: <adem2WKh2B-Leivq@baldur>

On Thu, Apr 09, 2026 at 08:19:41AM -0500, Bjorn Andersson wrote:
> On Wed, Apr 01, 2026 at 09:47:38PM -0700, Qiang Yu wrote:
> > On Wed, Apr 01, 2026 at 10:05:12PM +0530, Taniya Das wrote:
> > > On 4/1/2026 12:05 PM, Qiang Yu wrote:
> > > > diff --git a/drivers/clk/qcom/tcsrcc-glymur.c b/drivers/clk/qcom/tcsrcc-glymur.c
> [..]
> > > > +static const char * const tcsr_pcie_4_regulators[] = {
> > > > +	"vdda-refgen-0p9",
> > > > +	"vdda-refgen-1p2",
> > > > +	"vdda-qreftx1-0p9",
> > > > +	"vdda-qrefrpt0-0p9",
> > > > +	"vdda-qrefrpt1-0p9",
> > > > +	"vdda-qrefrpt2-0p9",
> > > > +	"vdda-qrefrx2-0p9",
> > > > +};
> > > > +
> > > 
> > > TCSR clock refs are just not for PCIe alone, they would have supplies
> > > for all the ref clocks. These supplies can also be shared across other
> > > clock refs. I think it is not the correct way to handle the supplies, as
> > > TCSR does not have the complete supplies map.
> > >
> > We have complete supplies map. You can get it on ipcatlog. Here is example
> > for other instances eg USB and EDP:
> > - Glymur (eDP): CXO PAD -> TX0 -> RPT0 -> RX0 -> eDP
> > - Glymur (USB4_2): CXO PAD -> TX0 -> RPT0 -> RPT1 -> RX1 -> USB4_2
> > - Glymur (USB3): CXO PAD -> TX0 -> RPT3 -> RPT4 -> RX4 -> USB3_SS3
> > 
> > I only add supplies for PCIe in this series because USB and EDP vote these
> > LDO in their PHY driver. They can remove them in PHY dts node and add same
> > regulator list here.
> > 
> 
> The regulators are reference counted. Can't we add the USB and eDP
> handling here as well now, and then after they are voted here we remove
> them from the PHY?
>

For USB, I’m not yet sure which tcsr_*_clkref_en each USB instance in the
QREF diagram is tied to. I need to confirm that mapping first, I'm
checking with Wesley Cheng.

For eDP, there is only one instance, so I can add it.

- Qiang Yu
> Regards,
> Bjorn
> 
> > - Qiang Yu
> > > 
> > > > +static const struct qcom_clk_ref_desc tcsr_cc_glymur_clk_descs[] = {
> > > > +	[TCSR_EDP_CLKREF_EN] = {
> > > > +		.name = "tcsr_edp_clkref_en",
> > > > +		.offset = 0x60,
> > > >  	},
> > > > -};
> > > >
> > > 
> > > 
> > > -- 
> > > Thanks,
> > > Taniya Das
> > > 

^ permalink raw reply

* Re: [PATCH v2 13/13] arm64: defconfig: Enable I3C and SPD5118 hwmon
From: Akhil R @ 2026-04-13  6:57 UTC (permalink / raw)
  To: krzk
  Cc: Frank.Li, acpica-devel, akhilrajeev, alexandre.belloni, conor+dt,
	devicetree, ebiggers, krzk+dt, lenb, linux-acpi, linux-hwmon,
	linux-i3c, linux-kernel, linux, miquel.raynal, p.zabel, rafael,
	robh, sakari.ailus, wsa+renesas, smangipudi
In-Reply-To: <d62130c6-c503-479d-99d8-b4f0f0582a4b@kernel.org>

On Sun, 12 Apr 2026 15:33:42 +0200, Krzysztof Kozlowski
> On 12/04/2026 15:32, Krzysztof Kozlowski wrote:
>> On 11/04/2026 09:20, Guenter Roeck wrote:
>>> On 4/10/26 22:34, Akhil R wrote:
>>> [ ... ]
>>>>>>> And it
>>>>>>> should bring me clear rule what I can or cannot remove from defconfig,
>>>>>>> if in 2 years I come and start pruning it from symbols.
>>>>
>>>> I am still a little confused on what information would likely accept (and
>>>> keep) these configs in the defconfig. Would updating the commit message
>>>> as below work?
>>>>
>>>> "These configs enable the support for SPD5118 within the
>>>> Small-Outline-Compression-Attached Memory Modules (SOCAMM) LPDDR5X found
>>>> in the NVIDIA Vera CPUs. The Vera CPU uses ACPI and is part of platforms
>>>> such as Vera Rubin."
>>>>
>>>
>>> It is quite interesting that we argue about SPD5118 which is mandatory in
>>> DDR5 systems. At the same time, CONFIG_IGB_HWMON, CONFIG_SENSORS_MACSMC_HWMON,
>>> CONFIG_SENSORS_RASPBERRYPI_HWMON, and CONFIG_RTC_DRV_DS3232_HWMON _are_
>>> enabled in arm64:defconfig. CONFIG_IGB_HWMON is even built-in.
>> 
>> Why CONFIG_SENSORS_MACSMC_HWMON is weird? It is part of the soc using
>> the defconfig?
>> 
>> The author here has troubles bringing any arguments why his drivers
>> should be defconfig and keeps asking what do I want to hear. If one
>> cannot make an argument why a change is needed, then maybe the change
>> should not be sent?
>> 
>> It's the job of the author to convince why the community needs this
>> change, unless it is obvious, ofc.
>> 
>>>
>>> It is kind of difficult to understand why those are more important than
>>> the temperature sensor on DDR5 modules (or the temperature sensor on DDR4
>>> modules, for that matter).
>> 
>> No one discussed this. I have no clue what is SPD5118 and commit msg did
>> not explain that. Did not even provide accurate user of that.
>> 
>>>
>>> I don't know what the policy for defconfig is, but just based on that it does
>>> seem to lack consistency.
>> 
>> No wonder... people write poor commits and send that to upstream. And
>> when asked "why do we want this" they got stuck.
>> 
>>>
>>> A separate question is if it is time to enable I3C in default configurations.
>>> I'd think so - more and more chip vendors support it, and presumably they would
>>> not invest in it if there was no demand, but that is just my personal opinion.
>> 
>> Isn't I3C needed for SPD5118. Otherwise I understand even less from this
>> rationale - why I3C is being enabled here?
>> 
>> And before author asks what do I want to here: no, it is author's job to
>> convince me to accept I3C in defconfig. Not mine.
> 
> BTW, all this was asked at v1 and author did not improve the commit msg
> beside giving quite broad/unspecific "Vera".

If I am not wrong, the ask in v1 was to specify the product which this is
getting used - 'Vera' it is. I do not know why you would think it is
unspecific.

As Thierry and Guenter mentioned, the lack of policy and 'mix of both' in
the defconfig makes it quite difficult to understand what could genuinely
be convincing other than putting down every little detail or do a trial
and error.

Anyway, I will describe where each config is getting used in the next
revision - hoping that would help.

Regards,
Akhil

^ permalink raw reply

* Re: [PATCH v2 07/10] dt-bindings: timer: renesas,rz-mtu3: document RZ/{T2H,N2H}
From: Krzysztof Kozlowski @ 2026-04-13  6:54 UTC (permalink / raw)
  To: Cosmin Tanislav
  Cc: Biju Das, Daniel Lezcano, Thomas Gleixner, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
	Magnus Damm, Michael Turquette, Stephen Boyd, Lee Jones,
	Philipp Zabel, linux-iio, linux-renesas-soc, linux-kernel,
	devicetree, linux-clk
In-Reply-To: <20260410163530.383818-8-cosmin-gabriel.tanislav.xa@renesas.com>

On Fri, Apr 10, 2026 at 07:35:27PM +0300, Cosmin Tanislav wrote:
> Compared to the previously supported SoCs, the Renesas RZ/T2H and RZ/N2H
> SoCs do not have a reset line.
> 
> Add support for them by moving the required reset into a conditional
> matching all compatibles for the existing SoCs. Disable the resets for
> RZ/T2H and RZ/N2H.
> 
> Document RZ/T2H and RZ/N2H, and use the generic compatible as a
> fallback, as functionality is the same.
> 
> Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
> ---
> 
> V2:
>  * squash "move required resets to conditional" into this
>  * disable the resets in the else branch of the condition
> 
>  .../bindings/timer/renesas,rz-mtu3.yaml       | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v3 1/2] dt-bindings: display: waveshare,dsp2dpi: describe DSI2LVDS setup
From: Krzysztof Kozlowski @ 2026-04-13  6:51 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Neil Armstrong, Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg,
	Joseph Guo, Marek Vasut, Andrzej Hajda, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec, dri-devel,
	devicetree, linux-kernel
In-Reply-To: <20260412-ws-lcd-v3-1-db22c2631828@oss.qualcomm.com>

On Sun, Apr 12, 2026 at 08:32:24PM +0300, Dmitry Baryshkov wrote:
> Several the Waveshare DSI LCD panel kits use DSI2LVDS ICN6202 bridge
> together with the LVDS panels. Define new compatible for the on-kit
> bridge setup (it is not itmized and it uses Waveshare prefix since the
> rest of the integration details are not known).
> 
> Note: the ICN6202 / ICN6211 bridges are completely handled by the board
> itself, they should not be programmed by the host (which otherwise might
> override correct params), etc. As such, it doesn't make sense to use
> those in the compat strings. I consider those to be an internal detail
> of the setup.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
>  .../devicetree/bindings/display/bridge/waveshare,dsi2dpi.yaml    | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 3/3] ASoC: renesas: fsi: Fix hang by enabling SPU clock
From: Bui Duc Phuc @ 2026-04-13  6:45 UTC (permalink / raw)
  To: Kuninori Morimoto
  Cc: broonie, lgirdwood, robh, krzk+dt, conor+dt, geert+renesas,
	magnus.damm, perex, tiwai, linux-sound, linux-renesas-soc,
	devicetree, linux-kernel
In-Reply-To: <87fr56vu4f.wl-kuninori.morimoto.gx@renesas.com>

Hi Morimoto-san, Geert,

Thanks for the feedback.

To keep things moving, I will send v2 shortly, focusing on the sequence
reordering and SPU Clock control to fix the system hang, which has been
confirmed to work.
Regarding the fsidiv clock provider, I will prepare it as a separate
patch after
confirmation from Geert, and will consider the appropriate approach for its
implementation.

Best regards,
Phuc

On Wed, Apr 8, 2026 at 1:33 PM Kuninori Morimoto
<kuninori.morimoto.gx@renesas.com> wrote:
>
>
> Hi Bui, Geert
>
> > > Hmm... fsi_dai_trigger() seems strange.
> > > It seems (A) stops clock, and (B) sets register after that.
> > > Is this the reason why you get error ? I think (A) and (B) should be
> > > reversed. The balance between SNDRV_PCM_TRIGGER_START, and with
> > > __fsi_suspend() are also not good.
> > > If so, can you use hw_start/stop() ?
> >
> > Thank you for the guidance. After reordering the sequence and moving the
> > SPU power control to fsi_hw_start/shutdown, the system hang is now resolved.
>
> Nice !
>
> > By the way, I’d like to discuss the fsidiv clock handling.
> > In the legacy implementation, it was handled here:
> > https://elixir.bootlin.com/linux/v7.0-rc7/source/drivers/sh/clk/cpg.c.
> > Currently, this has not been ported to the Common Clock Framework (CCF) for
> > R8A7740, and it resides in a different register range from the core CPG.
> > For v2, would you prefer that I implement a small clock provider for
> > fsidiv within
> > the FSI driver, or should it be added under drivers/clk/renesas/?
>
> I think it should be under drivers/clk/renesas, but Geert ?
>
> Thank you for your help !!
>
> Best regards
> ---
> Kuninori Morimoto

^ permalink raw reply

* Re: Phandles
From: Krzysztof Kozlowski @ 2026-04-13  6:37 UTC (permalink / raw)
  To: Kyle Bonnici, Herve Codina
  Cc: devicetree-compiler@vger.kernel.org, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, devicetree@vger.kernel.org
In-Reply-To: <163D807F-0F83-4282-B182-7A18B124D3E6@hotmail.com>

On 12/04/2026 18:37, Kyle Bonnici wrote:
>>>> Case 1:
>>>> / {
>>>>     node1 {
>>>>          pwms = <1 &pwm0 1 20 PWM_POLARITY_NORMAL>;
>>>>
>>>>          Here the first cell '1' is not a phandle.  
>>>
>>> Here the compiler is making an assumption here that all `pwms` properties must be specifier properties and all use `pwm` specifier.
>>
>> I think the purpose of 'select: true' is to have the binding always applied:
>>  https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/pwm/pwm-consumer.yaml#L15
>>
> 
> 
> I’m having trouble finding where the Devicetree Specification (v0.4) mandates that all binding systems must extend dt-schema. 
> Since this requirement isn't explicitly in the spec, it follows that the WARNING_PROPERTY_PHANDLE_CELLS validation belongs in dt-validate rather than within dtc itself.


So you want to have a property with values not being phandle? The spec
defines that properties like "pwm" must contain "value of properties
with a phandle value type". Therefore what does '1' represents in your
example?

Best regards,
Krzysztof

^ permalink raw reply

* Re: Phandles
From: Krzysztof Kozlowski @ 2026-04-13  6:33 UTC (permalink / raw)
  To: Herve Codina, Kyle Bonnici
  Cc: devicetree-compiler@vger.kernel.org, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, devicetree
In-Reply-To: <20260412173916.7a971a45@bootlin.com>

On 12/04/2026 17:40, Herve Codina wrote:
> Hi Kyle,
> 
> +Cc Kernel device-tree maintainers
> 
> On Sun, 12 Apr 2026 13:51:35 +0000
> Kyle Bonnici <kylebonnici@hotmail.com> wrote:
> 
>>> On 12 Apr 2026, at 14:51, Herve Codina <herve.codina@bootlin.com> wrote:
>>>
>>> Hi Kyle,
>>>
>>> On Sat, 11 Apr 2026 18:33:33 +0000
>>> Kyle Bonnici <kylebonnici@hotmail.com> wrote:
>>>   
>>>> Hi
>>>>
>>>> I have been looking at the the code for the compiler and I am wondering which specifications marks the below properties MUST BE Nexus Properties hence the validation.
>>>>
>>>> WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", "#interrupt-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", "#io-channel-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true);
>>>> WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", "#mux-control-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells");  
>>>
>>> All of those properties are defined as phandles.
>>>
>>> For instance, the 'pwms' property available in a node means the the node is
>>> a pwm consumer. It must follow the pwm consumer binding [1] and so a phandle
>>> is involved.
>>>
>>> This phandle can have arguments and the number of argument is defined by the
>>> #pwm-cells property set in the pwm provider node [2], [3].
>>>
>>> [1] https://elixir.bootlin.com/zephyr/v4.4.0-rc3/source/dts/bindings/pwm/pwm-controller.yaml
>>> [2] https://github.com/zephyrproject-rtos/zephyr/blob/main/dts/bindings/pwm/pwm-controller.yaml
>>> [3] https://elixir.bootlin.com/linux/v7.0-rc7/source/Documentation/devicetree/bindings/pwm/pwm.yaml
>>>   
>>>>
>>>>
>>>> These can be found here: https://github.com/dgibson/dtc/blob/main/checks.c#L1498 this is relevant for https://github.com/zephyrproject-rtos/zephyr/issues/107066  
>>>
>>> Examples provided in the zephyrproject issue link are, in my opinion, incorrect.
>>>
>>>  Case 1:
>>>  / {
>>>      node1 {
>>>           pwms = <1 &pwm0 1 20 PWM_POLARITY_NORMAL>;
>>>
>>>           Here the first cell '1' is not a phandle.  
>>
>> Here the compiler is making an assumption here that all `pwms` properties must be specifier properties and all use `pwm` specifier.
> 
> I think the purpose of 'select: true' is to have the binding always applied:
>   https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/pwm/pwm-consumer.yaml#L15
> 
> If this is confirmed, DTC performs correct checks as this binding must always
> be applied and so the 'pwms' property must be a phandle-array property.
> 
> Device-tree maintainers, can you confirm the purpose of 'select: true' set
> in a DT binding ?

The quoted parts were mentioning Zephyr. Here you mentioned DTC, but ask
about "select: true", so dtschema. I don't get the context... dtschema
has nothing to do with DTC and Zephyr.

Best regards,
Krzysztof

^ permalink raw reply

* Re: [PATCH v3 2/2] dt-bindings: leds: Document LTC3208 Multidisplay LED Driver
From: Krzysztof Kozlowski @ 2026-04-13  6:30 UTC (permalink / raw)
  To: Roleda, Jan carlo
  Cc: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-kernel@vger.kernel.org,
	linux-leds@vger.kernel.org, devicetree@vger.kernel.org
In-Reply-To: <BN8PR03MB4977C3A5917167F9B8BE6A3E96272@BN8PR03MB4977.namprd03.prod.outlook.com>

On 13/04/2026 01:37, Roleda, Jan carlo wrote:
> Hello Krzysztof,
> 
> Thank you again for the review. 
> 
> For clarification,
> 
>> -----Original Message-----
>> From: Krzysztof Kozlowski <krzk@kernel.org>
>> Sent: Tuesday, April 7, 2026 2:58 PM
>> To: Roleda, Jan carlo <Jancarlo.Roleda@analog.com>
>> Cc: Lee Jones <lee@kernel.org>; Pavel Machek <pavel@kernel.org>; Rob
>> Herring <robh@kernel.org>; Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor
>> Dooley <conor+dt@kernel.org>; linux-kernel@vger.kernel.org; linux-
>> leds@vger.kernel.org; devicetree@vger.kernel.org
>> Subject: Re: [PATCH v3 2/2] dt-bindings: leds: Document LTC3208 Multidisplay
>> LED Driver
>>
>> [External]
>>
>> On Mon, Apr 06, 2026 at 03:17:06PM +0800, Jan Carlo Roleda wrote:
>>> Add Documentation for LTC3208 Multidisplay LED Driver.
>>>
>>> Signed-off-by: Jan Carlo Roleda <jancarlo.roleda@analog.com>
>>> ---
>>
>> Still incorrect order.

You still did not correct the order of patches. I already asked you at v2.

>>
>> ...
>>
>>> +
>>> +      led-controller@1b {
>>> +        compatible = "adi,ltc3208";
>>> +        reg = <0x1b>;
>>> +        #address-cells = <1>;
>>> +        #size-cells = <0>;
>>> +        adi,disable-camhl-pin;
>>> +        adi,cfg-enrgbs-pin;
>>> +        adi,disable-rgb-aux4-dropout;
>>> +
>>> +        led@0 {
>>> +          reg = <0>;
>>
>> I still expect this to be complete, so at least function and color.
>>
>> Best regards,
>> Krzysztof
> 
> Are you referring here to keep the led@0-6,
> but instead of only the reg I should include other LED properties (i.e. function and color)?
> If so, I will add them as such in the next patch.
> 
> Do let me know if this is correct.

Make the example complete.

Best regards,
Krzysztof

^ permalink raw reply

* [PATCH v3 5/5] arch: arm64: dts: qcom: Add support for PCIe3a
From: Qiang Yu @ 2026-04-13  6:26 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Qiang Yu
In-Reply-To: <20260412-glymur_gen5x8_phy_0413-v3-0-affcebc16b8b@oss.qualcomm.com>

Describe PCIe3a controller and PHY. Also add required system resources
like regulators, clocks, interrupts and registers configuration for PCIe3a.

Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/glymur.dtsi | 316 ++++++++++++++++++++++++++++++++++-
 1 file changed, 315 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi
index f23cf81ddb77a4138deeb4e00dd8b316930a2feb..c15f87c37ecbad72076a6c731f4959a1a8bd8425 100644
--- a/arch/arm64/boot/dts/qcom/glymur.dtsi
+++ b/arch/arm64/boot/dts/qcom/glymur.dtsi
@@ -736,7 +736,7 @@ gcc: clock-controller@100000 {
 				 <0>,				/* USB 2 Phy PCIE PIPEGMUX */
 				 <0>,				/* USB 2 Phy PIPEGMUX */
 				 <0>,				/* USB 2 Phy SYS PCIE PIPEGMUX */
-				 <0>,				/* PCIe 3a */
+				 <&pcie3a_phy>,			/* PCIe 3a */
 				 <&pcie3b_phy>,			/* PCIe 3b */
 				 <&pcie4_phy>,			/* PCIe 4 */
 				 <&pcie5_phy>,			/* PCIe 5 */
@@ -3640,6 +3640,320 @@ pcie3b_port0: pcie@0 {
 			};
 		};
 
+		pcie3a: pci@1c10000 {
+			device_type = "pci";
+			compatible = "qcom,glymur-pcie", "qcom,pcie-x1e80100";
+			reg = <0x0 0x01c10000 0x0 0x3000>,
+			      <0x0 0x70000000 0x0 0xf20>,
+			      <0x0 0x70000f40 0x0 0xa8>,
+			      <0x0 0x70001000 0x0 0x4000>,
+			      <0x0 0x70100000 0x0 0x100000>,
+			      <0x0 0x01c13000 0x0 0x1000>;
+			reg-names = "parf",
+				    "dbi",
+				    "elbi",
+				    "atu",
+				    "config",
+				    "mhi";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges = <0x01000000 0x0 0x00000000 0x0 0x70200000 0x0 0x100000>,
+				 <0x02000000 0x0 0x70000000 0x0 0x70300000 0x0 0x3d00000>,
+				 <0x03000000 0x7 0x00000000 0x7 0x00000000 0x0 0x40000000>,
+				 <0x43000000 0x70 0x00000000 0x70 0x00000000 0x10 0x00000000>;
+
+			bus-range = <0 0xff>;
+
+			dma-coherent;
+
+			linux,pci-domain = <3>;
+			num-lanes = <8>;
+
+			operating-points-v2 = <&pcie3a_opp_table>;
+
+			msi-map = <0x0 &gic_its 0xb0000 0x10000>;
+			iommu-map = <0x0 &pcie_smmu 0x30000 0x10000>;
+
+			interrupts = <GIC_SPI 948 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 949 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 844 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 845 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 846 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 847 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 942 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "msi0",
+					  "msi1",
+					  "msi2",
+					  "msi3",
+					  "msi4",
+					  "msi5",
+					  "msi6",
+					  "msi7",
+					  "global";
+
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 0x7>;
+			interrupt-map = <0 0 0 1 &intc 0 0 0 848 IRQ_TYPE_LEVEL_HIGH>,
+					<0 0 0 2 &intc 0 0 0 849 IRQ_TYPE_LEVEL_HIGH>,
+					<0 0 0 3 &intc 0 0 0 850 IRQ_TYPE_LEVEL_HIGH>,
+					<0 0 0 4 &intc 0 0 0 851 IRQ_TYPE_LEVEL_HIGH>;
+
+			clocks = <&gcc GCC_PCIE_3A_AUX_CLK>,
+				 <&gcc GCC_PCIE_3A_CFG_AHB_CLK>,
+				 <&gcc GCC_PCIE_3A_MSTR_AXI_CLK>,
+				 <&gcc GCC_PCIE_3A_SLV_AXI_CLK>,
+				 <&gcc GCC_PCIE_3A_SLV_Q2A_AXI_CLK>,
+				 <&gcc GCC_AGGRE_NOC_PCIE_3A_WEST_SF_AXI_CLK>;
+			clock-names = "aux",
+				      "cfg",
+				      "bus_master",
+				      "bus_slave",
+				      "slave_q2a",
+				      "noc_aggr";
+
+			assigned-clocks = <&gcc GCC_PCIE_3A_AUX_CLK>;
+			assigned-clock-rates = <19200000>;
+
+			interconnects = <&pcie_west_anoc MASTER_PCIE_3A QCOM_ICC_TAG_ALWAYS
+					&mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
+					<&hsc_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+					&pcie_west_slv_noc SLAVE_PCIE_3A QCOM_ICC_TAG_ALWAYS>;
+			interconnect-names = "pcie-mem",
+					     "cpu-pcie";
+
+			resets = <&gcc GCC_PCIE_3A_BCR>,
+				 <&gcc GCC_PCIE_3A_LINK_DOWN_BCR>;
+			reset-names = "pci",
+				      "link_down";
+
+			power-domains = <&gcc GCC_PCIE_3A_GDSC>;
+
+			eq-presets-8gts = /bits/ 16 <0x5555 0x5555 0x5555 0x5555
+						     0x5555 0x5555 0x5555 0x5555>;
+			eq-presets-16gts = /bits/ 8 <0x55 0x55 0x55 0x55 0x55 0x55 0x55 0x55>;
+			eq-presets-32gts = /bits/ 8 <0x55 0x55 0x55 0x55 0x55 0x55 0x55 0x55>;
+
+			status = "disabled";
+
+			pcie3a_opp_table: opp-table {
+				compatible = "operating-points-v2";
+
+				/* GEN 1 x1 */
+				opp-2500000-1 {
+					opp-hz = /bits/ 64 <2500000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <250000 1>;
+					opp-level = <1>;
+				};
+
+				/* GEN 1 x2 */
+				opp-5000000-1 {
+					opp-hz = /bits/ 64 <5000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <500000 1>;
+					opp-level = <1>;
+				};
+
+				/* GEN 1 x4 */
+				opp-10000000-1 {
+					opp-hz = /bits/ 64 <10000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <1000000 1>;
+					opp-level = <1>;
+				};
+
+				/* GEN 1 x8 */
+				opp-20000000-1 {
+					opp-hz = /bits/ 64 <20000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <2000000 1>;
+					opp-level = <1>;
+				};
+
+				/* GEN 2 x1 */
+				opp-5000000-2 {
+					opp-hz = /bits/ 64 <5000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <500000 1>;
+					opp-level = <2>;
+				};
+
+				/* GEN 2 x2 */
+				opp-10000000-2 {
+					opp-hz = /bits/ 64 <10000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <1000000 1>;
+					opp-level = <2>;
+				};
+
+				/* GEN 2 x4 */
+				opp-20000000-2 {
+					opp-hz = /bits/ 64 <20000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <2000000 1>;
+					opp-level = <2>;
+				};
+
+				/* GEN 2 x8 */
+				opp-40000000-2 {
+					opp-hz = /bits/ 64 <40000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <4000000 1>;
+					opp-level = <2>;
+				};
+
+				/* GEN 3 x1 */
+				opp-8000000-3 {
+					opp-hz = /bits/ 64 <8000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <984500 1>;
+					opp-level = <3>;
+				};
+
+				/* GEN 3 x2 */
+				opp-16000000-3 {
+					opp-hz = /bits/ 64 <16000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <1969000 1>;
+					opp-level = <3>;
+				};
+
+				/* GEN 3 x4 */
+				opp-32000000-3 {
+					opp-hz = /bits/ 64 <32000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <3938000 1>;
+					opp-level = <3>;
+				};
+
+				/* GEN 3 x8 */
+				opp-64000000-3 {
+					opp-hz = /bits/ 64 <64000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+					opp-peak-kBps = <7876000 1>;
+					opp-level = <3>;
+				};
+
+				/* GEN 4 x1 */
+				opp-16000000-4 {
+					opp-hz = /bits/ 64 <16000000>;
+					required-opps = <&rpmhpd_opp_svs>;
+					opp-peak-kBps = <1969000 1>;
+					opp-level = <4>;
+				};
+
+				/* GEN 4 x2 */
+				opp-32000000-4 {
+					opp-hz = /bits/ 64 <32000000>;
+					required-opps = <&rpmhpd_opp_svs>;
+					opp-peak-kBps = <3938000 1>;
+					opp-level = <4>;
+				};
+
+				/* GEN 4 x4 */
+				opp-64000000-4 {
+					opp-hz = /bits/ 64 <64000000>;
+					required-opps = <&rpmhpd_opp_svs>;
+					opp-peak-kBps = <7876000 1>;
+					opp-level = <4>;
+				};
+
+				/* GEN 4 x8 */
+				opp-128000000-4 {
+					opp-hz = /bits/ 64 <128000000>;
+					required-opps = <&rpmhpd_opp_svs>;
+					opp-peak-kBps = <15753000 1>;
+					opp-level = <4>;
+				};
+
+				/* GEN 5 x1 */
+				opp-32000000-5 {
+					opp-hz = /bits/ 64 <32000000>;
+					required-opps = <&rpmhpd_opp_nom>;
+					opp-peak-kBps = <3938000 1>;
+					opp-level = <5>;
+				};
+
+				/* GEN 5 x2 */
+				opp-64000000-5 {
+					opp-hz = /bits/ 64 <64000000>;
+					required-opps = <&rpmhpd_opp_nom>;
+					opp-peak-kBps = <7876000 1>;
+					opp-level = <5>;
+				};
+
+				/* GEN 5 x4 */
+				opp-128000000-5 {
+					opp-hz = /bits/ 64 <128000000>;
+					required-opps = <&rpmhpd_opp_nom>;
+					opp-peak-kBps = <15753000 1>;
+					opp-level = <5>;
+				};
+
+				/* GEN 5 x8 */
+				opp-256000000-5 {
+					opp-hz = /bits/ 64 <256000000>;
+					required-opps = <&rpmhpd_opp_nom>;
+					opp-peak-kBps = <31506000 1>;
+					opp-level = <5>;
+				};
+			};
+
+			pcie3a_port0: pcie@0 {
+				device_type = "pci";
+				reg = <0x0 0x0 0x0 0x0 0x0>;
+				bus-range = <0x01 0xff>;
+
+				phys = <&pcie3a_phy>;
+
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges;
+			};
+		};
+
+		pcie3a_phy: phy@f00000 {
+			compatible = "qcom,glymur-qmp-gen5x8-pcie-phy";
+			reg = <0 0x00f00000 0 0x10000>;
+
+			clocks = <&gcc GCC_PCIE_PHY_3A_AUX_CLK>,
+				 <&gcc GCC_PCIE_3A_CFG_AHB_CLK>,
+				 <&tcsr TCSR_PCIE_3_CLKREF_EN>,
+				 <&gcc GCC_PCIE_3A_PHY_RCHNG_CLK>,
+				 <&gcc GCC_PCIE_3A_PIPE_CLK>,
+				 <&gcc GCC_PCIE_PHY_3B_AUX_CLK>;
+			clock-names = "aux",
+				      "cfg_ahb",
+				      "ref",
+				      "rchng",
+				      "pipe",
+				      "phy_b_aux";
+
+			resets = <&gcc GCC_PCIE_3A_PHY_BCR>,
+				 <&gcc GCC_PCIE_3A_NOCSR_COM_PHY_BCR>,
+				 <&gcc GCC_PCIE_3B_PHY_BCR>,
+				 <&gcc GCC_PCIE_3B_NOCSR_COM_PHY_BCR>;
+			reset-names = "phy",
+				      "phy_nocsr",
+				      "phy_b",
+				      "phy_b_nocsr";
+
+			assigned-clocks = <&gcc GCC_PCIE_3A_PHY_RCHNG_CLK>;
+			assigned-clock-rates = <100000000>;
+
+			power-domains = <&gcc GCC_PCIE_3A_PHY_GDSC>,
+					<&gcc GCC_PCIE_3B_PHY_GDSC>;
+
+			#clock-cells = <0>;
+			clock-output-names = "pcie3a_pipe_clk";
+
+			#phy-cells = <0>;
+
+			status = "disabled";
+		};
+
 		pcie3b_phy: phy@f10000 {
 			compatible = "qcom,glymur-qmp-gen5x4-pcie-phy";
 			reg = <0x0 0x00f10000 0x0 0x10000>;

-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 4/5] phy: qcom: qmp-pcie: Add Gen5 8-lanes mode for Glymur
From: Qiang Yu @ 2026-04-13  6:25 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Qiang Yu,
	Abel Vesa, Dmitry Baryshkov
In-Reply-To: <20260412-glymur_gen5x8_phy_0413-v3-0-affcebc16b8b@oss.qualcomm.com>

The third PCIe controller on Glymur SoC supports 8-lane operation via
bifurcation of two PHYs (each requires separate power domian, resets and
aux clk).

Add dedicated reset/no_csr reset list ("phy_b", "phy_b_nocsr") and
clock ("phy_b_aux") required for 8-lane operation. Introduce new
glymur_qmp_gen5x8_pciephy_cfg configuration to enable PCIe Gen5 x8 mode.

Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
---
 drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
index 51db9eea41255bad0034bbcfbfdc36894c2bc95f..e872b50b11da50e6317ce7e1acf6385925f92cdb 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
@@ -3376,7 +3376,7 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
 
 /* list of clocks required by phy */
 static const char * const qmp_pciephy_clk_l[] = {
-	"aux", "cfg_ahb", "ref", "refgen", "rchng", "phy_aux",
+	"aux", "cfg_ahb", "ref", "refgen", "rchng", "phy_aux", "phy_b_aux",
 };
 
 /* list of regulators */
@@ -3401,6 +3401,14 @@ static const char * const sm8550_pciephy_nocsr_reset_l[] = {
 	"phy_nocsr",
 };
 
+static const char * const glymur_pciephy_reset_l[] = {
+	"phy", "phy_b"
+};
+
+static const char * const glymur_pciephy_nocsr_reset_l[] = {
+	"phy_nocsr", "phy_b_nocsr",
+};
+
 static const struct qmp_pcie_offsets qmp_pcie_offsets_qhp = {
 	.serdes		= 0,
 	.pcs		= 0x1800,
@@ -4705,6 +4713,23 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = {
 	.phy_status		= PHYSTATUS_4_20,
 };
 
+static const struct qmp_phy_cfg glymur_qmp_gen5x8_pciephy_cfg = {
+	.lanes = 8,
+
+	.offsets		= &qmp_pcie_offsets_v8_50,
+
+	.reset_list		= glymur_pciephy_reset_l,
+	.num_resets		= ARRAY_SIZE(glymur_pciephy_reset_l),
+	.nocsr_reset_list	= glymur_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(glymur_pciephy_nocsr_reset_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
+
+	.regs			= pciephy_v8_50_regs_layout,
+
+	.phy_status		= PHYSTATUS_4_20,
+};
+
 static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls)
 {
 	const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -5483,6 +5508,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
 	}, {
 		.compatible = "qcom,glymur-qmp-gen5x4-pcie-phy",
 		.data = &glymur_qmp_gen5x4_pciephy_cfg,
+	}, {
+		.compatible = "qcom,glymur-qmp-gen5x8-pcie-phy",
+		.data = &glymur_qmp_gen5x8_pciephy_cfg,
 	}, {
 		.compatible = "qcom,ipq6018-qmp-pcie-phy",
 		.data = &ipq6018_pciephy_cfg,

-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 3/5] phy: qcom: qmp-pcie: Support multiple nocsr resets
From: Qiang Yu @ 2026-04-13  6:25 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Qiang Yu
In-Reply-To: <20260412-glymur_gen5x8_phy_0413-v3-0-affcebc16b8b@oss.qualcomm.com>

Refactor nocsr reset handling to support multiple nocsr resets required
for PHY configurations with bifurcated operation modes.

The Glymur SoC's 3rd PCIe instance supports 8-lane mode using two PHYs
in bifurcation, where each PHY requires its own nocsr reset to be
controlled simultaneously. The current implementation only supports a
single nocsr reset per PHY configuration.

Add num_nocsr and nocsr_list fields to struct qmp_phy_cfg to represent the
number and names of a group of nocsr reset names. Initialize these fields
for all PHYs that have nocsr resets, allowing the driver to correctly
acquire multiple nocsr resets during probe and control them as an array
by using reset_control_bulk APIs.

The refactoring maintains backward compatibility for existing single
nocsr reset configurations while enabling support for multi-PHY
scenarios like Glymur's 8-lane bifurcation mode.

Additionally, introduces x1e80100_qmp_gen3x2_pciephy_cfg as a separate
configuration from sm8550_qmp_gen3x2_pciephy_cfg since the x1e80100 Gen3x2
PHY requires nocsr reset support while the sm8550 Gen3x2 PHY does not.

Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
---
 drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 87 ++++++++++++++++++++++++++++----
 1 file changed, 77 insertions(+), 10 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
index 424c935e27a8766e1e26762bd3d7df527c1520e3..51db9eea41255bad0034bbcfbfdc36894c2bc95f 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
@@ -3281,6 +3281,11 @@ struct qmp_phy_cfg {
 	/* resets to be requested */
 	const char * const *reset_list;
 	int num_resets;
+
+	/* nocsr resets to be requested */
+	const char * const *nocsr_reset_list;
+	int num_nocsr_resets;
+
 	/* regulators to be requested */
 	const char * const *vreg_list;
 	int num_vregs;
@@ -3327,7 +3332,7 @@ struct qmp_pcie {
 	int num_pipe_clks;
 
 	struct reset_control_bulk_data *resets;
-	struct reset_control *nocsr_reset;
+	struct reset_control_bulk_data *nocsr_reset;
 	struct regulator_bulk_data *vregs;
 
 	struct phy *phy;
@@ -3392,6 +3397,10 @@ static const char * const sdm845_pciephy_reset_l[] = {
 	"phy",
 };
 
+static const char * const sm8550_pciephy_nocsr_reset_l[] = {
+	"phy_nocsr",
+};
+
 static const struct qmp_pcie_offsets qmp_pcie_offsets_qhp = {
 	.serdes		= 0,
 	.pcs		= 0x1800,
@@ -4348,6 +4357,8 @@ static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = {
 	},
 	.reset_list		= sdm845_pciephy_reset_l,
 	.num_resets		= ARRAY_SIZE(sdm845_pciephy_reset_l),
+	.nocsr_reset_list	= sm8550_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
 	.vreg_list		= sm8550_qmp_phy_vreg_l,
 	.num_vregs		= ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
 	.regs			= pciephy_v6_regs_layout,
@@ -4380,6 +4391,8 @@ static const struct qmp_phy_cfg sm8650_qmp_gen4x2_pciephy_cfg = {
 	},
 	.reset_list		= sdm845_pciephy_reset_l,
 	.num_resets		= ARRAY_SIZE(sdm845_pciephy_reset_l),
+	.nocsr_reset_list	= sm8550_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
 	.vreg_list		= sm8550_qmp_phy_vreg_l,
 	.num_vregs		= ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
 	.regs			= pciephy_v6_regs_layout,
@@ -4480,6 +4493,35 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = {
 	.phy_status		= PHYSTATUS_4_20,
 };
 
+static const struct qmp_phy_cfg x1e80100_qmp_gen3x2_pciephy_cfg = {
+	.lanes = 2,
+
+	.offsets		= &qmp_pcie_offsets_v5,
+
+	.tbls = {
+		.serdes		= sm8550_qmp_gen3x2_pcie_serdes_tbl,
+		.serdes_num	= ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_serdes_tbl),
+		.tx		= sm8550_qmp_gen3x2_pcie_tx_tbl,
+		.tx_num		= ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl),
+		.rx		= sm8550_qmp_gen3x2_pcie_rx_tbl,
+		.rx_num		= ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_rx_tbl),
+		.pcs		= sm8550_qmp_gen3x2_pcie_pcs_tbl,
+		.pcs_num	= ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl),
+		.pcs_misc	= sm8550_qmp_gen3x2_pcie_pcs_misc_tbl,
+		.pcs_misc_num	= ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_misc_tbl),
+	},
+	.reset_list		= sdm845_pciephy_reset_l,
+	.num_resets		= ARRAY_SIZE(sdm845_pciephy_reset_l),
+	.nocsr_reset_list	= sm8550_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
+	.regs			= pciephy_v5_regs_layout,
+
+	.pwrdn_ctrl		= SW_PWRDN | REFCLK_DRV_DSBL,
+	.phy_status		= PHYSTATUS,
+};
+
 static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = {
 	.lanes = 2,
 
@@ -4502,6 +4544,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = {
 
 	.reset_list		= sdm845_pciephy_reset_l,
 	.num_resets		= ARRAY_SIZE(sdm845_pciephy_reset_l),
+	.nocsr_reset_list	= sm8550_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
 	.vreg_list		= qmp_phy_vreg_l,
 	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 	.regs			= pciephy_v6_regs_layout,
@@ -4535,6 +4579,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x4_pciephy_cfg = {
 
 	.reset_list		= sdm845_pciephy_reset_l,
 	.num_resets		= ARRAY_SIZE(sdm845_pciephy_reset_l),
+	.nocsr_reset_list	= sm8550_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
 	.vreg_list		= qmp_phy_vreg_l,
 	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 	.regs			= pciephy_v6_regs_layout,
@@ -4566,6 +4612,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x8_pciephy_cfg = {
 
 	.reset_list		= sdm845_pciephy_reset_l,
 	.num_resets		= ARRAY_SIZE(sdm845_pciephy_reset_l),
+	.nocsr_reset_list	= sm8550_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
 	.vreg_list		= qmp_phy_vreg_l,
 	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 	.regs			= pciephy_v6_regs_layout,
@@ -4581,6 +4629,8 @@ static const struct qmp_phy_cfg qmp_v6_gen4x4_pciephy_cfg = {
 
 	.reset_list             = sdm845_pciephy_reset_l,
 	.num_resets             = ARRAY_SIZE(sdm845_pciephy_reset_l),
+	.nocsr_reset_list	= sm8550_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
 	.vreg_list              = qmp_phy_vreg_l,
 	.num_vregs              = ARRAY_SIZE(qmp_phy_vreg_l),
 	.regs                   = pciephy_v6_regs_layout,
@@ -4609,6 +4659,8 @@ static const struct qmp_phy_cfg qmp_v8_gen3x2_pciephy_cfg = {
 
 	.reset_list		= sdm845_pciephy_reset_l,
 	.num_resets		= ARRAY_SIZE(sdm845_pciephy_reset_l),
+	.nocsr_reset_list	= sm8550_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
 	.vreg_list		= qmp_phy_vreg_l,
 	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 	.regs			= pciephy_v8_regs_layout,
@@ -4624,6 +4676,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_cfg = {
 
 	.reset_list		= sdm845_pciephy_reset_l,
 	.num_resets		= ARRAY_SIZE(sdm845_pciephy_reset_l),
+	.nocsr_reset_list	= sm8550_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
 	.vreg_list		= qmp_phy_vreg_l,
 	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 
@@ -4640,6 +4694,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = {
 
 	.reset_list		= sdm845_pciephy_reset_l,
 	.num_resets		= ARRAY_SIZE(sdm845_pciephy_reset_l),
+	.nocsr_reset_list	= sm8550_pciephy_nocsr_reset_l,
+	.num_nocsr_resets	= ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
 	.vreg_list		= qmp_phy_vreg_l,
 	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 
@@ -4768,7 +4824,7 @@ static int qmp_pcie_init(struct phy *phy)
 		}
 	}
 
-	ret = reset_control_assert(qmp->nocsr_reset);
+	ret = reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_reset);
 	if (ret) {
 		dev_err(qmp->dev, "no-csr reset assert failed\n");
 		goto err_assert_reset;
@@ -4805,7 +4861,7 @@ static int qmp_pcie_exit(struct phy *phy)
 	const struct qmp_phy_cfg *cfg = qmp->cfg;
 
 	if (qmp->nocsr_reset)
-		reset_control_assert(qmp->nocsr_reset);
+		reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_reset);
 	else
 		reset_control_bulk_assert(cfg->num_resets, qmp->resets);
 
@@ -4849,7 +4905,7 @@ static int qmp_pcie_power_on(struct phy *phy)
 	if (ret)
 		return ret;
 
-	ret = reset_control_deassert(qmp->nocsr_reset);
+	ret = reset_control_bulk_deassert(cfg->num_nocsr_resets, qmp->nocsr_reset);
 	if (ret) {
 		dev_err(qmp->dev, "no-csr reset deassert failed\n");
 		goto err_disable_pipe_clk;
@@ -4998,14 +5054,25 @@ static int qmp_pcie_reset_init(struct qmp_pcie *qmp)
 	for (i = 0; i < cfg->num_resets; i++)
 		qmp->resets[i].id = cfg->reset_list[i];
 
-	ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, qmp->resets);
+	ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets,
+						    qmp->resets);
 	if (ret)
 		return dev_err_probe(dev, ret, "failed to get resets\n");
 
-	qmp->nocsr_reset = devm_reset_control_get_optional_exclusive(dev, "phy_nocsr");
-	if (IS_ERR(qmp->nocsr_reset))
-		return dev_err_probe(dev, PTR_ERR(qmp->nocsr_reset),
-							"failed to get no-csr reset\n");
+	if (!cfg->num_nocsr_resets)
+		return 0;
+	qmp->nocsr_reset = devm_kcalloc(dev, cfg->num_nocsr_resets,
+				   sizeof(*qmp->nocsr_reset), GFP_KERNEL);
+	if (!qmp->nocsr_reset)
+		return -ENOMEM;
+
+	for (i = 0; i < cfg->num_nocsr_resets; i++)
+		qmp->nocsr_reset[i].id = cfg->nocsr_reset_list[i];
+
+	ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_nocsr_resets,
+						    qmp->nocsr_reset);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to get no-csr reset\n");
 
 	return 0;
 }
@@ -5520,7 +5587,7 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
 		.data = &sm8750_qmp_gen3x2_pciephy_cfg,
 	}, {
 		.compatible = "qcom,x1e80100-qmp-gen3x2-pcie-phy",
-		.data = &sm8550_qmp_gen3x2_pciephy_cfg,
+		.data = &x1e80100_qmp_gen3x2_pciephy_cfg,
 	}, {
 		.compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy",
 		.data = &x1e80100_qmp_gen4x2_pciephy_cfg,

-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 2/5] phy: qcom: qmp-pcie: Add multiple power-domains support
From: Qiang Yu @ 2026-04-13  6:25 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Qiang Yu,
	Dmitry Baryshkov
In-Reply-To: <20260412-glymur_gen5x8_phy_0413-v3-0-affcebc16b8b@oss.qualcomm.com>

The Glymur SoC's 3rd PCIe instance supports 8-lane mode using two PHYs in
a bifurcated configuration. Each PHY has its own power domain (phy_gdsc)
that must be powered on before initialization per hardware requirements.

Current PHY power management assumes a single power domain per PHY,
preventing proper setup for this dual-PHY scenario. Add support for
multiple power domains by using devm_pm_domain_attach_list() to attach
power domains manually, while maintaining compatibility with single
power domain PHYs.

Enable runtime PM to allow power domain control when the PCIe driver
calls phy_power_on/phy_power_off:

- Single power domain: QMP PHY platform device directly attaches to
  power domain and controls it during runtime resume/suspend
- Multiple power domains: devm_pm_domain_attach_list() creates virtual
  devices as power domain suppliers, linked to the QMP PHY platform
  device as consumer

This ensures power domains are properly attached and turned on/off
for both single and multiple power domain configurations.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
---
 drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
index fed2fc9bb31108d51f88d34f3379c7744681f485..424c935e27a8766e1e26762bd3d7df527c1520e3 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
@@ -17,6 +17,7 @@
 #include <linux/phy/pcie.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
+#include <linux/pm_domain.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
@@ -5329,6 +5330,7 @@ static int qmp_pcie_parse_dt(struct qmp_pcie *qmp)
 
 static int qmp_pcie_probe(struct platform_device *pdev)
 {
+	struct dev_pm_domain_list *pd_list;
 	struct device *dev = &pdev->dev;
 	struct phy_provider *phy_provider;
 	struct device_node *np;
@@ -5348,6 +5350,16 @@ static int qmp_pcie_probe(struct platform_device *pdev)
 	WARN_ON_ONCE(!qmp->cfg->pwrdn_ctrl);
 	WARN_ON_ONCE(!qmp->cfg->phy_status);
 
+	ret = devm_pm_domain_attach_list(dev, NULL, &pd_list);
+	if (ret < 0 && ret != -EEXIST) {
+		dev_err(dev, "Failed to attach power domain\n");
+		return ret;
+	}
+
+	ret = devm_pm_runtime_enable(dev);
+	if (ret)
+		return ret;
+
 	ret = qmp_pcie_clk_init(qmp);
 	if (ret)
 		return ret;

-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 1/5] dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add support for glymur Gen5 x8 bifurcation mode
From: Qiang Yu @ 2026-04-13  6:25 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Qiang Yu
In-Reply-To: <20260412-glymur_gen5x8_phy_0413-v3-0-affcebc16b8b@oss.qualcomm.com>

The Glymur SoC has pcie3a and pcie3b PHYs that can operate in two modes:

1. Independent 4-lane mode: Each PHY operates as a separate PCIe Gen5
   4-lane interface, compatible with qcom,glymur-qmp-gen5x4-pcie-phy
2. Bifurcation mode (8-lane): pcie3a phy acts as leader and pcie3b phy as
   follower to form a single 8-lane PCIe Gen5 interface

In bifurcation mode, the hardware design requires controlling additional
resources beyond the standard pcie3a PHY configuration:

- pcie3b's aux_clk (phy_b_aux)
- pcie3b's phy_gdsc power domain
- pcie3b's bcr/nocsr reset

Add qcom,glymur-qmp-gen5x8-pcie-phy compatible string to document this
8-lane bifurcation configuration.

The phy_b_aux clock is used as the 6th clock instead of pipediv2,
requiring the clock-names enum to be extended to support both
[phy_b_aux, pipediv2] options at index 5. This follows the existing
pattern used for [rchng, refgen] clocks at index 3.

Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
---
 .../bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml   | 53 ++++++++++++++++++----
 1 file changed, 45 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
index 3a35120a77ec0ceb814a1cdcacff32fef32b4f7b..14eba5d705b1956c1bb00cc8c95171ed6488299b 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
@@ -18,6 +18,7 @@ properties:
     enum:
       - qcom,glymur-qmp-gen4x2-pcie-phy
       - qcom,glymur-qmp-gen5x4-pcie-phy
+      - qcom,glymur-qmp-gen5x8-pcie-phy
       - qcom,kaanapali-qmp-gen3x2-pcie-phy
       - qcom,qcs615-qmp-gen3x1-pcie-phy
       - qcom,qcs8300-qmp-gen4x2-pcie-phy
@@ -68,20 +69,27 @@ properties:
       - const: ref
       - enum: [rchng, refgen]
       - const: pipe
-      - const: pipediv2
+      - enum: [phy_b_aux, pipediv2]
 
   power-domains:
-    maxItems: 1
+    minItems: 1
+    items:
+      - description: PCIe PHY power domain. For PHYs supporting
+          bifurcation mode, this is the leader PHY power domain.
+      - description: Additional PCIe PHY power domain for PHYs supporting
+          bifurcation mode, used by the follower PHY.
 
   resets:
     minItems: 1
-    maxItems: 2
+    maxItems: 4
 
   reset-names:
     minItems: 1
     items:
       - const: phy
       - const: phy_nocsr
+      - const: phy_b
+      - const: phy_b_nocsr
 
   vdda-phy-supply: true
 
@@ -183,6 +191,7 @@ allOf:
             enum:
               - qcom,glymur-qmp-gen4x2-pcie-phy
               - qcom,glymur-qmp-gen5x4-pcie-phy
+              - qcom,glymur-qmp-gen5x8-pcie-phy
               - qcom,qcs8300-qmp-gen4x2-pcie-phy
               - qcom,sa8775p-qmp-gen4x2-pcie-phy
               - qcom,sa8775p-qmp-gen4x4-pcie-phy
@@ -201,6 +210,21 @@ allOf:
         clock-names:
           minItems: 6
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,glymur-qmp-gen5x8-pcie-phy
+    then:
+      properties:
+        power-domains:
+          minItems: 2
+    else:
+      properties:
+        power-domains:
+          maxItems: 1
+
   - if:
       properties:
         compatible:
@@ -223,11 +247,24 @@ allOf:
         reset-names:
           minItems: 2
     else:
-      properties:
-        resets:
-          maxItems: 1
-        reset-names:
-          maxItems: 1
+      if:
+        properties:
+          compatible:
+            contains:
+              enum:
+                - qcom,glymur-qmp-gen5x8-pcie-phy
+      then:
+        properties:
+          resets:
+            minItems: 4
+          reset-names:
+            minItems: 4
+      else:
+        properties:
+          resets:
+            maxItems: 1
+          reset-names:
+            maxItems: 1
 
   - if:
       properties:

-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 0/5] phy: qcom: qmp-pcie: Add PCIe Gen5 8-lane bifurcation support for Glymur
From: Qiang Yu @ 2026-04-13  6:25 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Qiang Yu,
	Dmitry Baryshkov, Abel Vesa

This patch series adds support for PCIe Gen5 8-lane bifurcation mode on
the Glymur SoC's third PCIe controller. In this configuration, pcie3a PHY
acts as leader and pcie3b PHY as follower to form a single 8-lane PCIe
Gen5 interface.

To support 8-lanes mode, this patch series add multiple power domain and
multi nocsr reset infrastructure as the hardware programming guide
specifies a strict initialization sequence for bifurcation mode that
requires coordinated multi-PHY resource management:

1. Turn on both pcie3a_phy_gdsc and pcie3b_phy_gdsc power domains
2. Assert both pcie3a and pcie3b nocsr resets, then deassert them together
3. Enable all pcie3a PHY clocks and pcie3b PHY aux clock (phy_b_aux)
4. Poll for PHY ready status

Changes Overview:

Patch 1: Updates dt-bindings to add qcom,glymur-qmp-gen5x8-pcie-phy
compatible string with proper validation rules for the unique clock
sequence and multiple power domains/resets required for bifurcation mode.

Patch 2: Extends the QMP PCIe driver to support multiple power domains
using devm_pm_domain_attach_list() and enables runtime PM for proper power
domain control during phy_power_on/phy_power_off operations.

Patch 3: Adds infrastructure for handling multiple nocsr resets by
introducing num_nocsr_resets and nocsr_reset_list fields to qmp_phy_cfg,
allowing the driver to manage arrays of nocsr resets using
reset_control_bulk APIs.

Patch 4: Implements the complete Gen5 8-lane configuration for Glymur by
adding the glymur_qmp_gen5x8_pciephy_cfg with proper reset lists, clock
configuration.

Patch 5: Add PCIe3a device tree node and required system resources in
glymur.dtsi. PCIe3a slot is not present on Glymur CRD, so there is no
changes to glymur-crd.dts.

Changes in v3:
- Add description of each power-domain.
- Add 64bit prefetchable memory range required by some EPs eg. AI100 ultra.
- Move PCIe3a after PCIe3b and move PCIe3a PHY before PCIe3b PHY.
- Link to v2: https://lore.kernel.org/all/20260323-glymur_gen5x8_phy_0323-v2-0-ce0fc07f0e52@oss.qualcomm.com/

Changes in v2:
- Remove pd_list from qmp_pcie struct as it is not used in phy driver.
- align clk-names on "
- Link to v1: https://lore.kernel.org/all/20260304-glymur_gen5x8_phy-v1-0-849e9a72e125@oss.qualcomm.com/

Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
---
Qiang Yu (5):
      dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add support for glymur Gen5 x8 bifurcation mode
      phy: qcom: qmp-pcie: Add multiple power-domains support
      phy: qcom: qmp-pcie: Support multiple nocsr resets
      phy: qcom: qmp-pcie: Add Gen5 8-lanes mode for Glymur
      arch: arm64: dts: qcom: Add support for PCIe3a

 .../bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml   |  53 +++-
 arch/arm64/boot/dts/qcom/glymur.dtsi               | 316 ++++++++++++++++++++-
 drivers/phy/qualcomm/phy-qcom-qmp-pcie.c           | 129 ++++++++-
 3 files changed, 478 insertions(+), 20 deletions(-)
---
base-commit: 66672af7a095d89f082c5327f3b15bc2f93d558e
change-id: 20260412-glymur_gen5x8_phy_0413-7dd33c953da7

Best regards,
-- 
Qiang Yu <qiang.yu@oss.qualcomm.com>


^ permalink raw reply

* Re: [PATCH v2 2/3] hte: tegra194: Add Tegra264 GTE support
From: Dipen Patel @ 2026-04-13  6:23 UTC (permalink / raw)
  To: Suneel Garapati, jonathanh, thierry.reding, krzk+dt, conor+dt,
	amhetre, sheetal, kkartik, robh, pshete, timestamp, devicetree,
	linux-tegra, linux-kernel
In-Reply-To: <20260408212413.217692-3-suneelg@nvidia.com>

On 4/8/26 2:24 PM, Suneel Garapati wrote:
> Add AON-GTE mapping and LIC GTE instance support for the Tegra264.
> Move TSC clock parameters from macros to members of SoC data
> as values differ for Tegra264 chip.
> 
> Signed-off-by: Suneel Garapati <suneelg@nvidia.com>
> ---
>  drivers/hte/hte-tegra194.c | 133 +++++++++++++++++++++++++++++++++++--
>  1 file changed, 128 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/hte/hte-tegra194.c b/drivers/hte/hte-tegra194.c
> index 690eb9be30fb..4a7702b32b24 100644
> --- a/drivers/hte/hte-tegra194.c
> +++ b/drivers/hte/hte-tegra194.c
> @@ -20,10 +20,11 @@
>  
>  #define HTE_SUSPEND	0
>  
> -/* HTE source clock TSC is 31.25MHz */
> +/* HTE source clock TSC is 1GHz for T264 and 31.25MHz for others */
>  #define HTE_TS_CLK_RATE_HZ	31250000ULL
> +#define HTE_TS_CLK_RATE_1G	1000000000ULL
>  #define HTE_CLK_RATE_NS		32
> -#define HTE_TS_NS_SHIFT	__builtin_ctz(HTE_CLK_RATE_NS)
> +#define HTE_CLK_RATE_NS_1G	1
>  
>  #define NV_AON_SLICE_INVALID	-1
>  #define NV_LINES_IN_SLICE	32
> @@ -120,6 +121,8 @@ struct tegra_hte_data {
>  	u32 slices;
>  	u32 map_sz;
>  	u32 sec_map_sz;
> +	u64 tsc_clkrate_hz;
> +	u32 tsc_clkrate_ns;
>  	const struct tegra_hte_line_mapped *map;
>  	const struct tegra_hte_line_mapped *sec_map;
>  };
> @@ -317,6 +320,94 @@ static const struct tegra_hte_line_mapped tegra234_aon_gpio_sec_map[] = {
>  	[40] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_23},
>  };
>  
> +static const struct tegra_hte_line_mapped tegra264_aon_gpio_map[] = {
> +	/* gpio, slice, bit_index */
> +	/* AA port */
> +	[0]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_29},
> +	[1]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_28},
> +	[2]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_27},
> +	[3]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_26},
> +	[4]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_25},
> +	[5]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_24},
> +	[6]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_23},
> +	[7]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_22},
> +	/* BB port */
> +	[8]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_21},
> +	[9]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_20},
> +	/* CC port */
> +	[10] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_19},
> +	[11] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_18},
> +	[12] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_17},
> +	[13] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_16},
> +	[14] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_15},
> +	[15] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_14},
> +	[16] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_13},
> +	[17] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_12},
> +	/* DD port */
> +	[18] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_11},
> +	[19] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_10},
> +	[20] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_9},
> +	[21] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_8},
> +	[22] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_7},
> +	[23] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_6},
> +	[24] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_5},
> +	[25] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_4},
> +	/* EE port */
> +	[26] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_3},
> +	[27] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_2},
> +	[28] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_1},
> +	[29] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_0},
> +};
> +
> +static const struct tegra_hte_line_mapped tegra264_aon_gpio_sec_map[] = {
> +	/* gpio, slice, bit_index */
> +	/* AA port */
> +	[0]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_29},
> +	[1]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_28},
> +	[2]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_27},
> +	[3]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_26},
> +	[4]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_25},
> +	[5]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_24},
> +	[6]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_23},
> +	[7]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_22},
> +	/* BB port */
> +	[8]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_21},
> +	[9]  = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_20},
> +	[10] = {NV_AON_SLICE_INVALID, 0},
> +	[11] = {NV_AON_SLICE_INVALID, 0},
> +	[12] = {NV_AON_SLICE_INVALID, 0},
> +	[13] = {NV_AON_SLICE_INVALID, 0},
> +	[14] = {NV_AON_SLICE_INVALID, 0},
> +	[15] = {NV_AON_SLICE_INVALID, 0},
> +	/* CC port */
> +	[16] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_19},
> +	[17] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_18},
> +	[18] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_17},
> +	[19] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_16},
> +	[20] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_15},
> +	[21] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_14},
> +	[22] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_13},
> +	[23] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_12},
> +	/* DD port */
> +	[24] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_11},
> +	[25] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_10},
> +	[26] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_9},
> +	[27] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_8},
> +	[28] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_7},
> +	[29] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_6},
> +	[30] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_5},
> +	[31] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_4},
> +	/* EE port */
> +	[32] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_3},
> +	[33] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_2},
> +	[34] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_1},
> +	[35] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_0},
> +	[36] = {NV_AON_SLICE_INVALID, 0},
> +	[37] = {NV_AON_SLICE_INVALID, 0},
> +	[38] = {NV_AON_SLICE_INVALID, 0},
> +	[39] = {NV_AON_SLICE_INVALID, 0},
> +};
> +
>  static const struct tegra_hte_data t194_aon_hte = {
>  	.map_sz = ARRAY_SIZE(tegra194_aon_gpio_map),
>  	.map = tegra194_aon_gpio_map,
> @@ -324,6 +415,8 @@ static const struct tegra_hte_data t194_aon_hte = {
>  	.sec_map = tegra194_aon_gpio_sec_map,
>  	.type = HTE_TEGRA_TYPE_GPIO,
>  	.slices = 3,
> +	.tsc_clkrate_hz = HTE_TS_CLK_RATE_HZ,
> +	.tsc_clkrate_ns = HTE_CLK_RATE_NS,
>  };
>  
>  static const struct tegra_hte_data t234_aon_hte = {
> @@ -333,6 +426,19 @@ static const struct tegra_hte_data t234_aon_hte = {
>  	.sec_map = tegra234_aon_gpio_sec_map,
>  	.type = HTE_TEGRA_TYPE_GPIO,
>  	.slices = 3,
> +	.tsc_clkrate_hz = HTE_TS_CLK_RATE_HZ,
> +	.tsc_clkrate_ns = HTE_CLK_RATE_NS,
> +};
> +
> +static const struct tegra_hte_data t264_aon_hte = {
> +	.map_sz = ARRAY_SIZE(tegra264_aon_gpio_map),
> +	.map = tegra264_aon_gpio_map,
> +	.sec_map_sz = ARRAY_SIZE(tegra264_aon_gpio_sec_map),
> +	.sec_map = tegra264_aon_gpio_sec_map,
> +	.type = HTE_TEGRA_TYPE_GPIO,
> +	.slices = 4,
> +	.tsc_clkrate_hz = HTE_TS_CLK_RATE_1G,
> +	.tsc_clkrate_ns = HTE_CLK_RATE_NS_1G,
>  };
>  
>  static const struct tegra_hte_data t194_lic_hte = {
> @@ -340,6 +446,8 @@ static const struct tegra_hte_data t194_lic_hte = {
>  	.map = NULL,
>  	.type = HTE_TEGRA_TYPE_LIC,
>  	.slices = 11,
> +	.tsc_clkrate_hz = HTE_TS_CLK_RATE_HZ,
> +	.tsc_clkrate_ns = HTE_CLK_RATE_NS,
>  };
>  
>  static const struct tegra_hte_data t234_lic_hte = {
> @@ -347,6 +455,17 @@ static const struct tegra_hte_data t234_lic_hte = {
>  	.map = NULL,
>  	.type = HTE_TEGRA_TYPE_LIC,
>  	.slices = 17,
> +	.tsc_clkrate_hz = HTE_TS_CLK_RATE_HZ,
> +	.tsc_clkrate_ns = HTE_CLK_RATE_NS,
> +};
> +
> +static const struct tegra_hte_data t264_lic_hte = {
> +	.map_sz = 0,
> +	.map = NULL,
> +	.type = HTE_TEGRA_TYPE_LIC,
> +	.slices = 10,
> +	.tsc_clkrate_hz = HTE_TS_CLK_RATE_1G,
> +	.tsc_clkrate_ns = HTE_CLK_RATE_NS_1G,
>  };
>  
>  static inline u32 tegra_hte_readl(struct tegra_hte_soc *hte, u32 reg)
> @@ -574,12 +693,12 @@ static int tegra_hte_release(struct hte_chip *chip, struct hte_ts_desc *desc,
>  static int tegra_hte_clk_src_info(struct hte_chip *chip,
>  				  struct hte_clk_info *ci)
>  {
> -	(void)chip;
> +	struct tegra_hte_soc *hte_dev = chip->data;
>  
>  	if (!ci)
>  		return -EINVAL;
>  
> -	ci->hz = HTE_TS_CLK_RATE_HZ;
> +	ci->hz = hte_dev->prov_data->tsc_clkrate_hz;
>  	ci->type = CLOCK_MONOTONIC;
>  
>  	return 0;
> @@ -602,8 +721,10 @@ static void tegra_hte_read_fifo(struct tegra_hte_soc *gs)
>  {
>  	u32 tsh, tsl, src, pv, cv, acv, slice, bit_index, line_id;
>  	u64 tsc;
> +	u8 tsc_ns_shift;
>  	struct hte_ts_data el;
>  
> +	tsc_ns_shift = __builtin_ctz(gs->prov_data->tsc_clkrate_ns);
>  	while ((tegra_hte_readl(gs, HTE_TESTATUS) >>
>  		HTE_TESTATUS_OCCUPANCY_SHIFT) &
>  		HTE_TESTATUS_OCCUPANCY_MASK) {
> @@ -621,7 +742,7 @@ static void tegra_hte_read_fifo(struct tegra_hte_soc *gs)
>  		while (acv) {
>  			bit_index = __builtin_ctz(acv);
>  			line_id = bit_index + (slice << 5);
> -			el.tsc = tsc << HTE_TS_NS_SHIFT;
> +			el.tsc = tsc << tsc_ns_shift;
>  			el.raw_level = tegra_hte_get_level(gs, line_id);
>  			hte_push_ts_ns(gs->chip, line_id, &el);
>  			acv &= ~BIT(bit_index);
> @@ -656,6 +777,8 @@ static const struct of_device_id tegra_hte_of_match[] = {
>  	{ .compatible = "nvidia,tegra194-gte-aon", .data = &t194_aon_hte},
>  	{ .compatible = "nvidia,tegra234-gte-lic", .data = &t234_lic_hte},
>  	{ .compatible = "nvidia,tegra234-gte-aon", .data = &t234_aon_hte},
> +	{ .compatible = "nvidia,tegra264-gte-lic", .data = &t264_lic_hte},
> +	{ .compatible = "nvidia,tegra264-gte-aon", .data = &t264_aon_hte},
>  	{ }
>  };
>  MODULE_DEVICE_TABLE(of, tegra_hte_of_match);
Reviewed-by: Dipen Patel <dipenp@nvidia.com>

^ permalink raw reply

* [PATCH v4 2/2] riscv: dts: spacemit: add DeepComputing FML13V05 board device tree
From: Sandie Cao @ 2026-04-13  6:07 UTC (permalink / raw)
  To: Yixun Lan, Troy Mitchell
  Cc: Conor Dooley, Emil Renner Berthing, Rob Herring,
	Krzysztof Kozlowski, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Heinrich Schuchardt, Michael Opdenacker, Guodong Xu,
	Hendrik Hamerlinck, Yangyu Chen, spacemit, linux-riscv,
	devicetree, linux-kernel, Sandie Cao
In-Reply-To: <20260413060524.1235982-1-sandie.cao@deepcomputing.io>

The FML13V05 board from DeepComputing incorporates a SpacemiT K3 RISC-V
SoC.It is a mainboard designed for the Framework Laptop 13 Chassis,
which has (Framework) SKU FRANHQ0001.

The FML13V05 board features:
- SpacemiT K3 RISC-V SoC
- LPDDR5 16GB or 32GB
- eMMC 32GB ~128GB (Optional)
- UFS 3.1 256G (Optional)
- QSPI Flash
- MicroSD Slot
- PCIe-based Wi-Fi
- 4 USB-C Ports
 - Port 1: PD 3.0 (65W Max), USB 3.2 Gen 1
 - Port 2: PD 3.0 (65W Max), USB 3.2 Gen 1, DP 1.4 (4K@60Hz)
 - Port 3 & 4: USB 3.2 Gen 1

This minimal device tree enables booting into a serial console with UART
output.

Signed-off-by: Sandie Cao <sandie.cao@deepcomputing.io>
---
 arch/riscv/boot/dts/spacemit/Makefile         |  1 +
 .../spacemit/k3-deepcomputing-fml13v05.dts    | 31 +++++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 arch/riscv/boot/dts/spacemit/k3-deepcomputing-fml13v05.dts

diff --git a/arch/riscv/boot/dts/spacemit/Makefile b/arch/riscv/boot/dts/spacemit/Makefile
index 7e2b87702571..acb993c452ba 100644
--- a/arch/riscv/boot/dts/spacemit/Makefile
+++ b/arch/riscv/boot/dts/spacemit/Makefile
@@ -4,4 +4,5 @@ dtb-$(CONFIG_ARCH_SPACEMIT) += k1-milkv-jupiter.dtb
 dtb-$(CONFIG_ARCH_SPACEMIT) += k1-musepi-pro.dtb
 dtb-$(CONFIG_ARCH_SPACEMIT) += k1-orangepi-r2s.dtb
 dtb-$(CONFIG_ARCH_SPACEMIT) += k1-orangepi-rv2.dtb
+dtb-$(CONFIG_ARCH_SPACEMIT) += k3-deepcomputing-fml13v05.dtb
 dtb-$(CONFIG_ARCH_SPACEMIT) += k3-pico-itx.dtb
diff --git a/arch/riscv/boot/dts/spacemit/k3-deepcomputing-fml13v05.dts b/arch/riscv/boot/dts/spacemit/k3-deepcomputing-fml13v05.dts
new file mode 100644
index 000000000000..b5d5112de358
--- /dev/null
+++ b/arch/riscv/boot/dts/spacemit/k3-deepcomputing-fml13v05.dts
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2026 DeepComputing (HK) Limited
+ */
+
+#include "k3.dtsi"
+#include "k3-pinctrl.dtsi"
+
+/ {
+	model = "DeepComputing FML13V05";
+	compatible = "deepcomputing,fml13v05", "spacemit,k3";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0";
+	};
+
+	memory@100000000 {
+		device_type = "memory";
+		reg = <0x1 0x00000000 0x4 0x00000000>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_0_cfg>;
+	status = "okay";
+};
-- 
2.43.0

^ permalink raw reply related

* [PATCH v4 1/2] dt-bindings: riscv: spacemit: add deepcomputing,fml13v05
From: Sandie Cao @ 2026-04-13  6:06 UTC (permalink / raw)
  To: Yixun Lan, Troy Mitchell
  Cc: Conor Dooley, Emil Renner Berthing, Rob Herring,
	Krzysztof Kozlowski, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Heinrich Schuchardt, Michael Opdenacker, Guodong Xu,
	Hendrik Hamerlinck, Yangyu Chen, spacemit, linux-riscv,
	devicetree, linux-kernel, Sandie Cao, Conor Dooley
In-Reply-To: <20260413060524.1235982-1-sandie.cao@deepcomputing.io>

Document the compatible string for the Deepcomputing fml13v05.
It's based on the SpacemiT K3 RISC-V SoC and is designed for the Framework
Laptop 13 Chassis, which has (Framework) SKU FRANHQ0001.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Sandie Cao <sandie.cao@deepcomputing.io>
---
 Documentation/devicetree/bindings/riscv/spacemit.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/riscv/spacemit.yaml b/Documentation/devicetree/bindings/riscv/spacemit.yaml
index b958b94a924d..af8030242bdc 100644
--- a/Documentation/devicetree/bindings/riscv/spacemit.yaml
+++ b/Documentation/devicetree/bindings/riscv/spacemit.yaml
@@ -29,6 +29,7 @@ properties:
           - const: spacemit,k1
       - items:
           - enum:
+              - deepcomputing,fml13v05
               - spacemit,k3-pico-itx
           - const: spacemit,k3
 
-- 
2.43.0

^ permalink raw reply related


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