mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v1 0/2] Add StarFive JHB100 DWCMSHC controller support
@ 2026-09-19  9:29 Changhuang Liang
  2026-09-19  9:29 ` [PATCH v1 1/2] dt-bindings: mmc: snps,dwcmshc-sdhci: Add starfive,jhb100-dwcmshc Changhuang Liang
  2026-09-19  9:29 ` [PATCH v1 2/2] mmc: sdhci-of-dwcmshc: Add support for StarFive JHB100 Changhuang Liang
  0 siblings, 2 replies; 3+ messages in thread
From: Changhuang Liang @ 2026-09-19  9:29 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
	Adrian Hunter, Inochi Amaoto, Chen Wang, Jisheng Zhang
  Cc: linux-mmc, linux-kernel, devicetree, sophgo, Philipp Zabel,
	Changhuang Liang

Add DWCMSHC controller driver for StarFive JHB100 SoC.
This series has been tested on the JHB100 EVB1 board.

Due to syscon limitations, it is necessary to use dma-ranges
to restrict the DMA address space of the eMMC controller to:
[0x400000000 - 0x4ffffffff]

bus_nioc_4g: bus_nioc_4g {
	compatible = "simple-bus";
	#address-cells = <2>;
	#size-cells = <2>;
	dma-noncoherent;
	ranges;
	dma-ranges = <0x4 0x00000000 0x0 0x40000000 0x1 0x0>,
		     <0x4 0x00000000 0x4 0x00000000 0x1 0x0>;

	emmc0: mmc@11b00000 {
		compatible = "starfive,jhb100-dwcmshc";
		reg = <0x0 0x11b00000 0x0 0x10000>;
	};
};

Changhuang Liang (2):
  dt-bindings: mmc: snps,dwcmshc-sdhci: Add starfive,jhb100-dwcmshc
  mmc: sdhci-of-dwcmshc: Add support for StarFive JHB100

 .../bindings/mmc/snps,dwcmshc-sdhci.yaml      |  74 +++++++-
 drivers/mmc/host/sdhci-of-dwcmshc.c           | 158 ++++++++++++++++++
 2 files changed, 228 insertions(+), 4 deletions(-)

--
2.25.1

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

* [PATCH v1 1/2] dt-bindings: mmc: snps,dwcmshc-sdhci: Add starfive,jhb100-dwcmshc
  2026-09-19  9:29 [PATCH v1 0/2] Add StarFive JHB100 DWCMSHC controller support Changhuang Liang
@ 2026-09-19  9:29 ` Changhuang Liang
  2026-09-19  9:29 ` [PATCH v1 2/2] mmc: sdhci-of-dwcmshc: Add support for StarFive JHB100 Changhuang Liang
  1 sibling, 0 replies; 3+ messages in thread
From: Changhuang Liang @ 2026-09-19  9:29 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
	Adrian Hunter, Inochi Amaoto, Chen Wang, Jisheng Zhang
  Cc: linux-mmc, linux-kernel, devicetree, sophgo, Philipp Zabel,
	Changhuang Liang

Add compatible string "starfive,jhb100-dwcmshc" for the StarFive
JHB100 SoC.

The JHB100 controller uses three clocks (core, bus and cclk_tx) and a
single reset, so relax the common resets/reset-names minItems from 4
to 1 and add a dedicated conditional schema for the JHB100 compatible
that constrains the clocks, clock-names, resets, reset-names and the
required starfive,jhb100-per1-syscon property. The property describes
the phandle to the PER1 SYSCON and the offset of the register holding
the upper DMA address bits [35:32] of the eMMC DMA address, used to
extend the default 32-bit DMA capability to 36-bit.

Also rework the existing if/else blocks so that the JHB100 compatible
is excluded from the branch that requires the extra resets, while
keeping the same constraints for the other SoCs.

Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
---
 .../bindings/mmc/snps,dwcmshc-sdhci.yaml      | 74 ++++++++++++++++++-
 1 file changed, 70 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
index cd823a3ef213..b5cdcc6e8f38 100644
--- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
@@ -32,6 +32,7 @@ properties:
           - sophgo,cv1800b-dwcmshc
           - sophgo,sg2002-dwcmshc
           - sophgo,sg2042-dwcmshc
+          - starfive,jhb100-dwcmshc
           - thead,th1520-dwcmshc
           - eswin,eic7700-dwcmshc
 
@@ -53,11 +54,11 @@ properties:
     maxItems: 1
 
   resets:
-    minItems: 4
+    minItems: 1
     maxItems: 5
 
   reset-names:
-    minItems: 4
+    minItems: 1
     maxItems: 5
 
   canaan,usb-phy:
@@ -98,6 +99,22 @@ properties:
       offset of the MSHCCS register used to configure clock
       synchronisation for HS200 tuning.
 
+  starfive,jhb100-per1-syscon:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    items:
+      - items:
+          - description: Phandle to StarFive JHB100 SoC Peripheral-1 syscon
+                         register block.
+          - description: Offset of the register used to configure the
+                         upper DMA address bits [35:32] of the eMMC DMA
+                         address.
+    description:
+      Phandle to the StarFive JHB100 SoC Peripheral-1 syscon register
+      block, and the offset of the register that holds the upper DMA
+      address bits [35:32] of the eMMC DMA address. This is used to
+      extend the default 32-bit DMA capability of the CMSHC controller
+      up to 36-bit.
+
 required:
   - compatible
   - reg
@@ -167,7 +184,16 @@ allOf:
             - const: core
             - const: bus
             - const: timer
-    else:
+
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              enum:
+                - sophgo,sg2042-dwcmshc
+                - starfive,jhb100-dwcmshc
+    then:
       properties:
         clocks:
           minItems: 1
@@ -205,7 +231,16 @@ allOf:
       required:
         - eswin,hsp-sp-csr
         - eswin,drive-impedance-ohms
-    else:
+
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              enum:
+                - eswin,eic7700-dwcmshc
+                - starfive,jhb100-dwcmshc
+    then:
       properties:
         resets:
           minItems: 5
@@ -228,6 +263,37 @@ allOf:
       required:
         - power-domains
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: starfive,jhb100-dwcmshc
+    then:
+      properties:
+        clocks:
+          items:
+            - description: core clock
+            - description: bus clock
+            - description: card transmit clock
+        clock-names:
+          items:
+            - const: core
+            - const: bus
+            - const: cclk_tx
+        resets:
+          maxItems: 1
+        reset-names:
+          items:
+            - const: core
+        starfive,jhb100-per1-syscon: true
+      required:
+        - resets
+        - reset-names
+        - starfive,jhb100-per1-syscon
+    else:
+      properties:
+        starfive,jhb100-per1-syscon: false
+
 unevaluatedProperties: false
 
 examples:
-- 
2.25.1


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

* [PATCH v1 2/2] mmc: sdhci-of-dwcmshc: Add support for StarFive JHB100
  2026-09-19  9:29 [PATCH v1 0/2] Add StarFive JHB100 DWCMSHC controller support Changhuang Liang
  2026-09-19  9:29 ` [PATCH v1 1/2] dt-bindings: mmc: snps,dwcmshc-sdhci: Add starfive,jhb100-dwcmshc Changhuang Liang
@ 2026-09-19  9:29 ` Changhuang Liang
  1 sibling, 0 replies; 3+ messages in thread
From: Changhuang Liang @ 2026-09-19  9:29 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
	Adrian Hunter, Inochi Amaoto, Chen Wang, Jisheng Zhang
  Cc: linux-mmc, linux-kernel, devicetree, sophgo, Philipp Zabel,
	Changhuang Liang

Add support for the DWCMSHC controller found on the StarFive JHB100
SoC.

The JHB100 CMSHC controller has only 32-bit DMA capability by default.
The higher DMA address bits [35:32] can be configured through the
PER1 SYSCON, extending the DMA address range up to 36 bits. Fix these
bits to 4, which limits the DMA range to [0x40000000 - 0x4ffffffff].

The cclk_tx clock must be disabled before sdhci_set_clock() to
eliminate glitches, and re-enabled afterwards. It is enabled during
probe and disabled in the platform deinit callback, which is invoked
from dwcmshc_remove().

Additionally, clear the PHY_DLLDL_CNFG_R register and re-initialize
the PHY when setting UHS signaling, and force 1.8V fixed I/O when the
DT specifies a DDR/HS200/HS400 1.8V mode.

Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
---
 drivers/mmc/host/sdhci-of-dwcmshc.c | 158 ++++++++++++++++++++++++++++
 1 file changed, 158 insertions(+)

diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
index 1baa2379c9c3..021b03c17312 100644
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
@@ -48,6 +48,9 @@
 #define DWCMSHC_ENHANCED_STROBE		BIT(8)
 #define DWCMSHC_EMMC_ATCTRL		0x40
 #define DWCMSHC_AT_STAT			0x44
+/* StarFive JHB100 SoC MSHCCS register */
+#define DWCMSHC_ARWADDR			GENMASK(3, 0)
+#define DWCMSHC_ARWADDR_DEFAULT		4
 /* Tuning and auto-tuning fields in AT_CTRL_R control register */
 #define AT_CTRL_AT_EN			BIT(0) /* autotuning is enabled */
 #define AT_CTRL_CI_SEL			BIT(1) /* interval to drive center phase select */
@@ -294,6 +297,11 @@ struct k230_priv  {
 	struct regmap *hi_sys_regmap;
 };

+struct jhb100_priv {
+	struct clk *cclk_tx;
+	bool cclk_tx_on;
+};
+
 #define DWCMSHC_MAX_OTHER_CLKS 3

 struct dwcmshc_priv {
@@ -314,6 +322,7 @@ struct dwcmshc_pltfm_data {
 	const struct sdhci_pltfm_data pdata;
 	const struct cqhci_host_ops *cqhci_host_ops;
 	int (*init)(struct device *dev, struct sdhci_host *host, struct dwcmshc_priv *dwc_priv);
+	void (*deinit)(struct dwcmshc_priv *dwc_priv);
 	void (*postinit)(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv);
 };

@@ -2257,6 +2266,145 @@ static const struct dwcmshc_pltfm_data sdhci_dwcmshc_hpe_gsc_pdata = {
 	.init = dwcmshc_hpe_gsc_init,
 };

+static int sdhci_jhb100_set_dma_mask(struct sdhci_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+	struct device *dev = mmc_dev(mmc);
+	int ret;
+
+	/*
+	 * The StarFive JHB100's CMSHC controller only has 32-bit DMA
+	 * capability by default, but the higher DMA address bits [35:32]
+	 * can be configured through SYSCON, thus supporting up to 36-bit
+	 * DMA capability.
+	 */
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36));
+	if (ret)
+		dev_err(dev, "Failed to set 36-bit DMA mask.\n");
+
+	return ret;
+}
+
+static void sdhci_jhb100_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
+	struct jhb100_priv *priv = dwc_priv->priv;
+
+	/* the cclk_tx clock is disabled before sdhci_set_clock() to eliminate glitches */
+	if (priv->cclk_tx_on) {
+		clk_disable_unprepare(priv->cclk_tx);
+		priv->cclk_tx_on = false;
+	}
+
+	fsleep(15);
+
+	sdhci_set_clock(host, clock);
+
+	if (clk_prepare_enable(priv->cclk_tx))
+		dev_err(mmc_dev(host->mmc), "failed to re-enable cclk_tx\n");
+	else
+		priv->cclk_tx_on = true;
+}
+
+static void sdhci_jhb100_set_uhs_signaling(struct sdhci_host *host,
+					   unsigned int timing)
+{
+	dwcmshc_set_uhs_signaling(host, timing);
+	sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R);
+	th1520_sdhci_set_phy(host);
+}
+
+static const struct sdhci_ops starfive_jhb100_ops = {
+	.set_dma_mask		= sdhci_jhb100_set_dma_mask,
+	.set_clock		= sdhci_jhb100_set_clock,
+	.set_uhs_signaling	= sdhci_jhb100_set_uhs_signaling,
+	.set_bus_width		= sdhci_set_bus_width,
+	.reset			= sdhci_reset,
+	.get_max_clock		= dwcmshc_get_max_clock,
+	.adma_write_desc	= dwcmshc_adma_write_desc,
+	.irq			= dwcmshc_cqe_irq_handler,
+	.voltage_switch		= dwcmshc_phy_init,
+	.platform_execute_tuning = th1520_execute_tuning,
+};
+
+static int dwcmshc_starfive_jhb100_init(struct device *dev, struct sdhci_host *host,
+					struct dwcmshc_priv *dwc_priv)
+{
+	struct reset_control *reset;
+	struct jhb100_priv *priv;
+	unsigned int reg_offset;
+	struct regmap *syscon;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(struct jhb100_priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	syscon = syscon_regmap_lookup_by_phandle_args(dev->of_node,
+						      "starfive,jhb100-per1-syscon",
+						      1, &reg_offset);
+	if (IS_ERR(syscon))
+		return PTR_ERR(syscon);
+
+	/* configure the higher DMA address bits [35:32] */
+	ret = regmap_update_bits(syscon, reg_offset, DWCMSHC_ARWADDR,
+				 DWCMSHC_ARWADDR_DEFAULT);
+	if (ret)
+		return ret;
+
+	reset = devm_reset_control_get_exclusive_deasserted(mmc_dev(host->mmc), NULL);
+	if (IS_ERR(reset))
+		return dev_err_probe(mmc_dev(host->mmc), PTR_ERR(reset),
+				     "Failed to get&deassert reset control\n");
+
+	priv->cclk_tx = devm_clk_get(dev, "cclk_tx");
+	if (IS_ERR(priv->cclk_tx))
+		return dev_err_probe(dev, PTR_ERR(priv->cclk_tx),
+				     "Failed to get cclk_tx clock\n");
+
+	ret = clk_prepare_enable(priv->cclk_tx);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to enable cclk_tx clock\n");
+
+	priv->cclk_tx_on = true;
+
+	if (device_property_read_bool(mmc_dev(host->mmc), "mmc-ddr-1_8v") ||
+	    device_property_read_bool(mmc_dev(host->mmc), "mmc-hs200-1_8v") ||
+	    device_property_read_bool(mmc_dev(host->mmc), "mmc-hs400-1_8v"))
+		dwc_priv->flags |= FLAG_IO_FIXED_1V8;
+	else
+		dwc_priv->flags &= ~FLAG_IO_FIXED_1V8;
+
+	dwc_priv->delay_line = 0x10;
+	dwc_priv->priv = priv;
+
+	if (dwc_priv->flags & FLAG_IO_FIXED_1V8) {
+		host->flags &= ~SDHCI_SIGNALING_330;
+		host->flags |=  SDHCI_SIGNALING_180;
+	}
+
+	return 0;
+}
+
+static void dwcmshc_starfive_jhb100_deinit(struct dwcmshc_priv *dwc_priv)
+{
+	struct jhb100_priv *priv = dwc_priv->priv;
+
+	if (priv->cclk_tx_on)
+		clk_disable_unprepare(priv->cclk_tx);
+}
+
+static const struct dwcmshc_pltfm_data sdhci_dwcmshc_jhb100_pdata = {
+	.pdata = {
+		.ops = &starfive_jhb100_ops,
+		.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+		.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+	},
+	.init = dwcmshc_starfive_jhb100_init,
+	.deinit = dwcmshc_starfive_jhb100_deinit,
+};
+
 static const struct cqhci_host_ops dwcmshc_cqhci_ops = {
 	.enable		= dwcmshc_sdhci_cqe_enable,
 	.disable	= sdhci_cqe_disable,
@@ -2377,6 +2525,10 @@ static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
 		.compatible = "hpe,gsc-dwcmshc",
 		.data = &sdhci_dwcmshc_hpe_gsc_pdata,
 	},
+	{
+		.compatible = "starfive,jhb100-dwcmshc",
+		.data = &sdhci_dwcmshc_jhb100_pdata,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids);
@@ -2503,6 +2655,8 @@ static int dwcmshc_probe(struct platform_device *pdev)
 err_rpm:
 	pm_runtime_disable(dev);
 	pm_runtime_put_noidle(dev);
+	if (pltfm_data->deinit)
+		pltfm_data->deinit(priv);
 err_bus_clk:
 	clk_disable_unprepare(priv->bus_clk);
 err_clk:
@@ -2527,6 +2681,7 @@ static void dwcmshc_remove(struct platform_device *pdev)
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	const struct dwcmshc_pltfm_data *pltfm_data = priv->dwcmshc_pdata;

 	pm_runtime_get_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
@@ -2534,6 +2689,9 @@ static void dwcmshc_remove(struct platform_device *pdev)

 	sdhci_remove_host(host, 0);

+	if (pltfm_data->deinit)
+		pltfm_data->deinit(priv);
+
 	dwcmshc_disable_card_clk(host);

 	clk_disable_unprepare(pltfm_host->clk);
--
2.25.1

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

end of thread, other threads:[~2026-09-19  9:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-19  9:29 [PATCH v1 0/2] Add StarFive JHB100 DWCMSHC controller support Changhuang Liang
2026-09-19  9:29 ` [PATCH v1 1/2] dt-bindings: mmc: snps,dwcmshc-sdhci: Add starfive,jhb100-dwcmshc Changhuang Liang
2026-09-19  9:29 ` [PATCH v1 2/2] mmc: sdhci-of-dwcmshc: Add support for StarFive JHB100 Changhuang Liang

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

all inboxes | Powered by JetHome®