public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Add SDHCI support for Canaan K230 SoC
@ 2026-02-26 11:59 Jiayu Du
  2026-02-26 11:59 ` [PATCH v2 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 Jiayu Du
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Jiayu Du @ 2026-02-26 11:59 UTC (permalink / raw)
  To: krzk, ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt
  Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv,
	linux-kernel, gaohan, me, Jiayu Du

This series is based on the k230 usbphy series[1].

This patch series adds SDHCI support for the Canaan K230 SoC,
which uses Synopsys DWCMSHC SDHCI controllers, include MMC0 and MMC1.
The hardware designs of these two controllers are different.
The MMC0 supports eMMC, while MMC1 only supports SDIO. Detailed
information can be found in the vendor's manual[2].

From the vendor's K230 manual:
 - MMC0 supports eMMC5.0 and SDIO3.0, usually for eMMC chips.
 - MMC1 only does SDIO3.0 in 4/1-bit mode up to SDR104, and the manual
   clearly says it can't handle eMMC because of pin count and limits.

Therefore, there are two separate compatibles and the driver treats them
differently.

Link: https://lore.kernel.org/all/20260121145526.14672-1-jiayu.riscv@isrc.iscas.ac.cn/ [1]
Link: https://github.com/kendryte/k230_docs/blob/main/en/00_hardware/K230_Hardware_Design_Guide.md#mmc-circuit [2]

Changes in v2:
- Change the clock minItems to 5.
- Add comments to explain the reason for setting SDHCI_PROG_CLOCK_MODE.
- Write the power selection logic in the phy init cleaner.
- Replace manual delay loop with read_poll_timeout.
- Drop unnecessarily braces where a single statement will do.
- Add the match_data pointer to dwcmshc_pltfm_data.
- Add dwcmshc_k230_match_data struct to separate eMMC/SDIO config data
- Split K230 into individual emmc/sdio platform data instances instead of
  sharing one.
- Remove redundant have_phy member in k230_priv.
- Replace of_find_compatible_node with of_parse_phandle to get USB PHY
  from DT phandle.
- Link to v1: https://lore.kernel.org/all/20260204082908.27501-1-jiayu.riscv@isrc.iscas.ac.cn/

Jiayu Du (3):
  dt-bindings: mmc: Add sdhci support for Canaan k230
  mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support
  riscv: dts: canaan: Add mmc nodes for K230

 .../bindings/mmc/snps,dwcmshc-sdhci.yaml      |  29 ++
 .../boot/dts/canaan/k230-canmv-dshanpi.dts    |  56 ++++
 .../dts/canaan/k230-canmv-module-dshanpi.dtsi |   7 +
 arch/riscv/boot/dts/canaan/k230.dtsi          |  28 ++
 drivers/mmc/host/sdhci-of-dwcmshc.c           | 288 ++++++++++++++++++
 5 files changed, 408 insertions(+)

-- 
2.53.0


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

* [PATCH v2 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230
  2026-02-26 11:59 [PATCH v2 0/3] Add SDHCI support for Canaan K230 SoC Jiayu Du
@ 2026-02-26 11:59 ` Jiayu Du
  2026-02-26 18:30   ` Conor Dooley
  2026-02-26 11:59 ` [PATCH v2 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support Jiayu Du
  2026-02-26 11:59 ` [PATCH v2 3/3] riscv: dts: canaan: Add mmc nodes for K230 Jiayu Du
  2 siblings, 1 reply; 8+ messages in thread
From: Jiayu Du @ 2026-02-26 11:59 UTC (permalink / raw)
  To: krzk, ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt
  Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv,
	linux-kernel, gaohan, me, Jiayu Du

The Canaan k230 uses the SDHCI from Synopsys. Add compatible strings
to the k230. The k230 has two controllers. MMC0 supports eMMC, while
MMC1 supports SDIO.

Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
---
 .../bindings/mmc/snps,dwcmshc-sdhci.yaml      | 29 +++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
index 7e7c55dc2440..ae63363c0eae 100644
--- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
@@ -23,6 +23,8 @@ properties:
           - const: sophgo,sg2044-dwcmshc
           - const: sophgo,sg2042-dwcmshc
       - enum:
+          - canaan,k230-emmc
+          - canaan,k230-sdio
           - rockchip,rk3568-dwcmshc
           - rockchip,rk3588-dwcmshc
           - snps,dwcmshc-sdhci
@@ -55,6 +57,11 @@ properties:
   reset-names:
     maxItems: 5
 
+  canaan,usb-phy:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: Phandle to the Canaan K230 USB PHY node required for
+                 k230-emmc/sdio.
+
   rockchip,txclk-tapnum:
     description: Specify the number of delay for tx sampling.
     $ref: /schemas/types.yaml#/definitions/uint8
@@ -87,6 +94,28 @@ required:
 allOf:
   - $ref: mmc-controller.yaml#
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - canaan,k230-emmc
+              - canaan,k230-sdio
+    then:
+      properties:
+        clocks:
+          minItems: 5
+          maxItems: 5
+        clock-names:
+          items:
+            - const: core
+            - const: bus
+            - const: axi
+            - const: block
+            - const: timer
+      required:
+        - canaan,usb-phy
+
   - if:
       properties:
         compatible:
-- 
2.53.0


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

* [PATCH v2 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support
  2026-02-26 11:59 [PATCH v2 0/3] Add SDHCI support for Canaan K230 SoC Jiayu Du
  2026-02-26 11:59 ` [PATCH v2 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 Jiayu Du
@ 2026-02-26 11:59 ` Jiayu Du
  2026-03-04  9:25   ` Jiayu Du
  2026-03-05 11:48   ` Ulf Hansson
  2026-02-26 11:59 ` [PATCH v2 3/3] riscv: dts: canaan: Add mmc nodes for K230 Jiayu Du
  2 siblings, 2 replies; 8+ messages in thread
From: Jiayu Du @ 2026-02-26 11:59 UTC (permalink / raw)
  To: krzk, ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt
  Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv,
	linux-kernel, gaohan, me, Jiayu Du

Add SDHCI controller driver for Canaan k230 SoC. Implement custom
sdhci_ops for set_clock, phy init, init and reset.

Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
---
 drivers/mmc/host/sdhci-of-dwcmshc.c | 288 ++++++++++++++++++++++++++++
 1 file changed, 288 insertions(+)

diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
index 2b75a36c096b..21c77e908d77 100644
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
@@ -128,9 +128,11 @@
 #define PHY_CNFG_PHY_PWRGOOD_MASK	BIT_MASK(1) /* bit [1] */
 #define PHY_CNFG_PAD_SP_MASK		GENMASK(19, 16) /* bits [19:16] */
 #define PHY_CNFG_PAD_SP			0x0c /* PMOS TX drive strength */
+#define PHY_CNFG_PAD_SP_k230		0x09 /* PMOS TX drive strength for k230 */
 #define PHY_CNFG_PAD_SP_SG2042		0x09 /* PMOS TX drive strength for SG2042 */
 #define PHY_CNFG_PAD_SN_MASK		GENMASK(23, 20) /* bits [23:20] */
 #define PHY_CNFG_PAD_SN			0x0c /* NMOS TX drive strength */
+#define PHY_CNFG_PAD_SN_k230		0x08 /* NMOS TX drive strength for k230 */
 #define PHY_CNFG_PAD_SN_SG2042		0x08 /* NMOS TX drive strength for SG2042 */
 
 /* PHY command/response pad settings */
@@ -153,14 +155,22 @@
 #define PHY_PAD_RXSEL_3V3		0x2 /* Receiver type select for 3.3V */
 
 #define PHY_PAD_WEAKPULL_MASK		GENMASK(4, 3) /* bits [4:3] */
+#define PHY_PAD_WEAKPULL_DISABLED	0x0 /* Weak pull up and pull down disabled */
 #define PHY_PAD_WEAKPULL_PULLUP		0x1 /* Weak pull up enabled */
 #define PHY_PAD_WEAKPULL_PULLDOWN	0x2 /* Weak pull down enabled */
 
 #define PHY_PAD_TXSLEW_CTRL_P_MASK	GENMASK(8, 5) /* bits [8:5] */
 #define PHY_PAD_TXSLEW_CTRL_P		0x3 /* Slew control for P-Type pad TX */
+#define PHY_PAD_TXSLEW_CTRL_P_k230_VAL2	0x2 /* Slew control for P-Type pad TX for k230 */
 #define PHY_PAD_TXSLEW_CTRL_N_MASK	GENMASK(12, 9) /* bits [12:9] */
 #define PHY_PAD_TXSLEW_CTRL_N		0x3 /* Slew control for N-Type pad TX */
 #define PHY_PAD_TXSLEW_CTRL_N_SG2042	0x2 /* Slew control for N-Type pad TX for SG2042 */
+#define PHY_PAD_TXSLEW_CTRL_N_k230_VAL2	0x2 /* Slew control for N-Type pad TX for k230 */
+#define PHY_PAD_TXSLEW_CTRL_N_k230_VAL1	0x1 /* Slew control for N-Type pad TX for k230 */
+
+/* PHY Common DelayLine config settings */
+#define PHY_COMMDL_CNFG			(DWC_MSHC_PTR_PHY_R + 0x1c)
+#define PHY_COMMDL_CNFG_DLSTEP_SEL	BIT(0) /* DelayLine outputs on PAD enabled */
 
 /* PHY CLK delay line settings */
 #define PHY_SDCLKDL_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x1d)
@@ -174,7 +184,10 @@
 #define PHY_SDCLKDL_DC_HS400		0x18 /* delay code for HS400 mode */
 
 #define PHY_SMPLDL_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x20)
+#define PHY_SMPLDL_CNFG_EXTDLY_EN	BIT(0)
 #define PHY_SMPLDL_CNFG_BYPASS_EN	BIT(1)
+#define PHY_SMPLDL_CNFG_INPSEL_MASK	GENMASK(3, 2) /* bits [3:2] */
+#define PHY_SMPLDL_CNFG_INPSEL		0x3 /* delay line input source */
 
 /* PHY drift_cclk_rx delay line configuration setting */
 #define PHY_ATDL_CNFG_R			(DWC_MSHC_PTR_PHY_R + 0x21)
@@ -227,6 +240,14 @@
 /* SMC call for BlueField-3 eMMC RST_N */
 #define BLUEFIELD_SMC_SET_EMMC_RST_N	0x82000007
 
+/* Canaan specific Registers */
+#define SD0_CTRL			0x00
+#define SD0_HOST_REG_VOL_STABLE		BIT(4)
+#define SD0_CARD_WRITE_PROT		BIT(6)
+#define SD1_CTRL			0x08
+#define SD1_HOST_REG_VOL_STABLE		BIT(0)
+#define SD1_CARD_WRITE_PROT		BIT(2)
+
 /* Eswin specific Registers */
 #define EIC7700_CARD_CLK_STABLE		BIT(28)
 #define EIC7700_INT_BCLK_STABLE		BIT(16)
@@ -268,6 +289,12 @@ struct eic7700_priv {
 	unsigned int drive_impedance;
 };
 
+struct k230_priv  {
+	/* Kendryte k230 specific */
+	struct regmap *hi_sys_regmap;
+	const struct dwcmshc_k230_match_data *match_data;
+};
+
 #define DWCMSHC_MAX_OTHER_CLKS 3
 
 struct dwcmshc_priv {
@@ -284,12 +311,34 @@ struct dwcmshc_priv {
 };
 
 struct dwcmshc_pltfm_data {
+	const void *match_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 (*postinit)(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv);
 };
 
+struct dwcmshc_k230_match_data {
+	bool is_emmc;
+	u32 ctrl_reg;
+	u32 vol_stable_bit;
+	u32 write_prot_bit;
+};
+
+static const struct dwcmshc_k230_match_data k230_emmc_match_data = {
+	.is_emmc = true,
+	.ctrl_reg = SD0_CTRL,
+	.vol_stable_bit = SD0_HOST_REG_VOL_STABLE,
+	.write_prot_bit = SD0_CARD_WRITE_PROT,
+};
+
+static const struct dwcmshc_k230_match_data k230_sdio_match_data = {
+	.is_emmc = false,
+	.ctrl_reg = SD1_CTRL,
+	.vol_stable_bit = SD1_HOST_REG_VOL_STABLE,
+	.write_prot_bit = SD1_CARD_WRITE_PROT,
+};
+
 static void dwcmshc_enable_card_clk(struct sdhci_host *host)
 {
 	u16 ctrl;
@@ -1656,6 +1705,208 @@ static int eic7700_init(struct device *dev, struct sdhci_host *host, struct dwcm
 	return 0;
 }
 
+static void dwcmshc_k230_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	u16 clk;
+
+	sdhci_set_clock(host, clock);
+
+	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+	/*
+	 * It is necessary to enable SDHCI_PROG_CLOCK_MODE. This is a
+	 * vendor-specific quirk. If this is not done, the eMMC will be
+	 * unable to read or write.
+	 */
+	clk |= SDHCI_PROG_CLOCK_MODE;
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static void sdhci_k230_config_phy_delay(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
+	u32 val;
+
+	sdhci_writeb(host, PHY_COMMDL_CNFG_DLSTEP_SEL, PHY_COMMDL_CNFG);
+	sdhci_writeb(host, 0x0, PHY_SDCLKDL_CNFG_R);
+	sdhci_writeb(host, PHY_SDCLKDL_DC_INITIAL,
+		     PHY_SDCLKDL_DC_R);
+
+	val = PHY_SMPLDL_CNFG_EXTDLY_EN;
+	val |= FIELD_PREP(PHY_SMPLDL_CNFG_INPSEL_MASK,
+			  PHY_SMPLDL_CNFG_INPSEL);
+	sdhci_writeb(host, val, PHY_SMPLDL_CNFG_R);
+
+	sdhci_writeb(host, FIELD_PREP(PHY_ATDL_CNFG_INPSEL_MASK,
+		     PHY_ATDL_CNFG_INPSEL), PHY_ATDL_CNFG_R);
+
+	val = sdhci_readl(host, dwc_priv->vendor_specific_area1 +
+		     DWCMSHC_EMMC_ATCTRL);
+	val |= AT_CTRL_TUNE_CLK_STOP_EN;
+	val |= FIELD_PREP(AT_CTRL_PRE_CHANGE_DLY_MASK,
+			  AT_CTRL_PRE_CHANGE_DLY);
+	val |= FIELD_PREP(AT_CTRL_POST_CHANGE_DLY_MASK,
+			  AT_CTRL_POST_CHANGE_DLY);
+	sdhci_writel(host, val, dwc_priv->vendor_specific_area1 +
+		     DWCMSHC_EMMC_ATCTRL);
+	sdhci_writel(host, 0x0, dwc_priv->vendor_specific_area1 +
+		     DWCMSHC_AT_STAT);
+}
+
+static int dwcmshc_k230_phy_init(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	u32 rxsel;
+	u32 val;
+	u32 reg;
+	int ret;
+
+	/* reset phy */
+	sdhci_writew(host, 0, PHY_CNFG_R);
+
+	/* Disable the clock */
+	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+	rxsel = priv->flags & FLAG_IO_FIXED_1V8 ?
+			PHY_PAD_RXSEL_1V8 : PHY_PAD_RXSEL_3V3;
+
+	val = rxsel;
+	val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P_k230_VAL2);
+	val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N_k230_VAL2);
+	val |= FIELD_PREP(PHY_PAD_WEAKPULL_MASK, PHY_PAD_WEAKPULL_PULLUP);
+
+	sdhci_writew(host, val, PHY_CMDPAD_CNFG_R);
+	sdhci_writew(host, val, PHY_DATAPAD_CNFG_R);
+	sdhci_writew(host, val, PHY_RSTNPAD_CNFG_R);
+
+	val = rxsel;
+	val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P_k230_VAL2);
+	val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N_k230_VAL2);
+	sdhci_writew(host, val, PHY_CLKPAD_CNFG_R);
+
+	val = rxsel;
+	val |= FIELD_PREP(PHY_PAD_WEAKPULL_MASK, PHY_PAD_WEAKPULL_PULLDOWN);
+	val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P_k230_VAL2);
+	val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N_k230_VAL2);
+	sdhci_writew(host, val, PHY_STBPAD_CNFG_R);
+
+	sdhci_k230_config_phy_delay(host);
+
+	/* Wait max 150 ms */
+	ret = read_poll_timeout(sdhci_readl, reg,
+				(reg & FIELD_PREP(
+					PHY_CNFG_PHY_PWRGOOD_MASK, 1)),
+				10, 150000, false, host, PHY_CNFG_R);
+	if (ret) {
+		dev_err(mmc_dev(host->mmc),
+			"READ PHY PWRGOOD timeout!\n");
+		return -ETIMEDOUT;
+	}
+
+	reg = FIELD_PREP(PHY_CNFG_PAD_SN_MASK, PHY_CNFG_PAD_SN_k230) |
+	      FIELD_PREP(PHY_CNFG_PAD_SP_MASK, PHY_CNFG_PAD_SP_k230);
+	sdhci_writel(host, reg, PHY_CNFG_R);
+
+	/* de-assert the phy */
+	reg |= PHY_CNFG_RSTN_DEASSERT;
+	sdhci_writel(host, reg, PHY_CNFG_R);
+
+	return 0;
+}
+
+static void dwcmshc_k230_sdhci_reset(struct sdhci_host *host, u8 mask)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
+	struct k230_priv *k230_priv = dwc_priv->priv;
+	u8 emmc_ctrl;
+
+	dwcmshc_reset(host, mask);
+
+	if (mask == SDHCI_RESET_ALL) {
+		emmc_ctrl = sdhci_readw(host,
+				       dwc_priv->vendor_specific_area1 +
+				       DWCMSHC_EMMC_CONTROL);
+		sdhci_writeb(host, emmc_ctrl,
+			     dwc_priv->vendor_specific_area1 +
+			     DWCMSHC_EMMC_CONTROL);
+
+		if (k230_priv->match_data->is_emmc)
+			dwcmshc_k230_phy_init(host);
+		else
+			sdhci_writel(host, 0x0,
+				     dwc_priv->vendor_specific_area1 +
+				     DWCMSHC_HOST_CTRL3);
+	}
+}
+
+static int dwcmshc_k230_init(struct device *dev, struct sdhci_host *host,
+			     struct dwcmshc_priv *dwc_priv)
+{
+	static const char * const clk_ids[] = {"block", "timer", "axi"};
+	const struct dwcmshc_k230_match_data *match_data;
+	const struct dwcmshc_pltfm_data *pltfm_data;
+	struct device_node *usb_phy_node;
+	struct k230_priv *k230_priv;
+	u32 data;
+	int ret;
+
+	pltfm_data = device_get_match_data(dev);
+
+	if (!pltfm_data || !pltfm_data->match_data) {
+		dev_err(dev, "No vendor data found for K230\n");
+		return -EINVAL;
+	}
+	match_data = pltfm_data->match_data;
+
+	k230_priv = devm_kzalloc(dev, sizeof(struct k230_priv), GFP_KERNEL);
+	if (!k230_priv)
+		return -ENOMEM;
+
+	k230_priv->match_data = match_data;
+	dwc_priv->priv = k230_priv;
+
+	usb_phy_node = of_parse_phandle(dev->of_node, "canaan,usb-phy", 0);
+	if (!usb_phy_node)
+		return dev_err_probe(dev, -ENODEV,
+				     "Failed to find canaan,usb-phy phandle\n");
+
+	k230_priv->hi_sys_regmap = device_node_to_regmap(usb_phy_node);
+	of_node_put(usb_phy_node);
+
+	if (IS_ERR(k230_priv->hi_sys_regmap))
+		return dev_err_probe(dev, PTR_ERR(k230_priv->hi_sys_regmap),
+				     "Failed to get k230-usb-phy regmap\n");
+
+	ret = dwcmshc_get_enable_other_clks(mmc_dev(host->mmc), dwc_priv,
+					    ARRAY_SIZE(clk_ids), clk_ids);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Failed to get/enable k230 mmc other clocks\n");
+
+	if (match_data->is_emmc) {
+		host->flags &= ~SDHCI_SIGNALING_330;
+		dwc_priv->flags |= FLAG_IO_FIXED_1V8;
+	} else {
+		host->mmc->caps |= MMC_CAP_SD_HIGHSPEED;
+		host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+	}
+
+	ret = regmap_read(k230_priv->hi_sys_regmap, match_data->ctrl_reg, &data);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to read control reg 0x%x\n",
+				     match_data->ctrl_reg);
+
+	data |= match_data->write_prot_bit | match_data->vol_stable_bit;
+	ret = regmap_write(k230_priv->hi_sys_regmap, match_data->ctrl_reg, data);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to write control reg 0x%x\n",
+				     match_data->ctrl_reg);
+
+	return 0;
+}
+
 static const struct sdhci_ops sdhci_dwcmshc_ops = {
 	.set_clock		= sdhci_set_clock,
 	.set_bus_width		= sdhci_set_bus_width,
@@ -1743,6 +1994,15 @@ static const struct sdhci_ops sdhci_dwcmshc_eic7700_ops = {
 	.platform_execute_tuning = sdhci_eic7700_executing_tuning,
 };
 
+static const struct sdhci_ops sdhci_dwcmshc_k230_ops = {
+	.set_clock = dwcmshc_k230_sdhci_set_clock,
+	.set_bus_width = sdhci_set_bus_width,
+	.set_uhs_signaling = dwcmshc_set_uhs_signaling,
+	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
+	.reset = dwcmshc_k230_sdhci_reset,
+	.adma_write_desc = dwcmshc_adma_write_desc,
+};
+
 static const struct dwcmshc_pltfm_data sdhci_dwcmshc_pdata = {
 	.pdata = {
 		.ops = &sdhci_dwcmshc_ops,
@@ -1834,6 +2094,26 @@ static const struct dwcmshc_pltfm_data sdhci_dwcmshc_eic7700_pdata = {
 	.init = eic7700_init,
 };
 
+static const struct dwcmshc_pltfm_data sdhci_dwcmshc_k230_emmc_pdata = {
+	.pdata = {
+		.ops = &sdhci_dwcmshc_k230_ops,
+		.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
+			  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
+	},
+	.init = dwcmshc_k230_init,
+	.match_data = (void *)&k230_emmc_match_data,
+};
+
+static const struct dwcmshc_pltfm_data sdhci_dwcmshc_k230_sdio_pdata = {
+	.pdata = {
+		.ops = &sdhci_dwcmshc_k230_ops,
+		.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
+			  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
+	},
+	.init = dwcmshc_k230_init,
+	.match_data = (void *)&k230_sdio_match_data,
+};
+
 static const struct cqhci_host_ops dwcmshc_cqhci_ops = {
 	.enable		= dwcmshc_sdhci_cqe_enable,
 	.disable	= sdhci_cqe_disable,
@@ -1906,6 +2186,14 @@ static void dwcmshc_cqhci_init(struct sdhci_host *host, struct platform_device *
 }
 
 static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
+	{
+		.compatible = "canaan,k230-emmc",
+		.data = &sdhci_dwcmshc_k230_emmc_pdata,
+	},
+	{
+		.compatible = "canaan,k230-sdio",
+		.data = &sdhci_dwcmshc_k230_sdio_pdata,
+	},
 	{
 		.compatible = "rockchip,rk3588-dwcmshc",
 		.data = &sdhci_dwcmshc_rk35xx_pdata,
-- 
2.53.0


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

* [PATCH v2 3/3] riscv: dts: canaan: Add mmc nodes for K230
  2026-02-26 11:59 [PATCH v2 0/3] Add SDHCI support for Canaan K230 SoC Jiayu Du
  2026-02-26 11:59 ` [PATCH v2 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 Jiayu Du
  2026-02-26 11:59 ` [PATCH v2 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support Jiayu Du
@ 2026-02-26 11:59 ` Jiayu Du
  2 siblings, 0 replies; 8+ messages in thread
From: Jiayu Du @ 2026-02-26 11:59 UTC (permalink / raw)
  To: krzk, ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt
  Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv,
	linux-kernel, gaohan, me, Jiayu Du

Add MMC nodes to K230, including eMMC and SDIO. Enable HS200 eMMC
on the SoM and SDIO high-speed on the board.

Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
---
 .../boot/dts/canaan/k230-canmv-dshanpi.dts    | 56 +++++++++++++++++++
 .../dts/canaan/k230-canmv-module-dshanpi.dtsi |  7 +++
 arch/riscv/boot/dts/canaan/k230.dtsi          | 28 ++++++++++
 3 files changed, 91 insertions(+)

diff --git a/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts b/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts
index 55197cfc25b4..1877b2049409 100644
--- a/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts
+++ b/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts
@@ -15,6 +15,8 @@ / {
 
 	aliases {
 		serial0 = &uart0;
+		mmc0 = &emmc;
+		mmc1 = &sdio;
 	};
 
 	chosen {
@@ -73,6 +75,60 @@ uart0-rxd-cfg {
 			input-schmitt-enable;
 		};
 	};
+
+	mmc1_pins: mmc1-pins {
+		mmc1-cmd-cfg {
+			pinmux = <K230_PINMUX(54, 2)>;
+			slew-rate = <0>;
+			drive-strength = <7>;
+			power-source = <K230_MSC_3V3>;
+			input-enable;
+			output-enable;
+			bias-pull-up;
+			input-schmitt-enable;
+		};
+
+		mmc1-clk-cfg {
+			pinmux = <K230_PINMUX(55, 2)>;
+			slew-rate = <0>;
+			drive-strength = <7>;
+			power-source = <K230_MSC_3V3>;
+			output-enable;
+			bias-disable;
+			input-schmitt-enable;
+		};
+
+		mmc1-data-cfg {
+			pinmux = <K230_PINMUX(56, 2)>, /* mmc1 data0 */
+				 <K230_PINMUX(57, 2)>, /* mmc1 data1 */
+				 <K230_PINMUX(58, 2)>, /* mmc1 data2 */
+				 <K230_PINMUX(59, 2)>; /* mmc1 data3 */
+			slew-rate = <0>;
+			drive-strength = <7>;
+			power-source = <K230_MSC_3V3>;
+			input-enable;
+			output-enable;
+			bias-pull-up;
+			input-schmitt-enable;
+		};
+	};
+};
+
+&emmc {
+	vmmc-supply = <&vdd_3v3>;
+	vqmmc-supply = <&vdd_1v8>;
+};
+
+&sdio {
+	bus-width = <4>;
+	max-frequency = <50000000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&vdd_3v3>;
+	vqmmc-supply = <&vdd_3v3>;
+	cap-sd-highspeed;
+	no-1-8-v;
+	status = "okay";
 };
 
 &uart0 {
diff --git a/arch/riscv/boot/dts/canaan/k230-canmv-module-dshanpi.dtsi b/arch/riscv/boot/dts/canaan/k230-canmv-module-dshanpi.dtsi
index 566665d39239..1db7569253fe 100644
--- a/arch/riscv/boot/dts/canaan/k230-canmv-module-dshanpi.dtsi
+++ b/arch/riscv/boot/dts/canaan/k230-canmv-module-dshanpi.dtsi
@@ -24,3 +24,10 @@ &sysclk {
 	clocks = <&osc24m>, <&timerx_pulse_in>;
 	clock-names = "osc24m", "timer-pulse-in";
 };
+
+&emmc {
+	bus-width = <8>;
+	max-frequency = <200000000>;
+	mmc-hs200-1_8v;
+	status = "okay";
+};
diff --git a/arch/riscv/boot/dts/canaan/k230.dtsi b/arch/riscv/boot/dts/canaan/k230.dtsi
index e1ec3e1f40a7..e3c6926dbadc 100644
--- a/arch/riscv/boot/dts/canaan/k230.dtsi
+++ b/arch/riscv/boot/dts/canaan/k230.dtsi
@@ -192,6 +192,34 @@ usb1: usb@91540000 {
 			status = "disabled";
 		};
 
+		emmc: mmc@91580000 {
+			compatible = "canaan,k230-emmc";
+			reg = <0x0 0x91580000 0x0 0x1000>;
+			clocks = <&sysclk K230_HS_SD0_CARD_GATE>,
+				 <&sysclk K230_HS_SD0_AHB_GATE>,
+				 <&sysclk K230_HS_SD0_AXI_GATE>,
+				 <&sysclk K230_HS_SD0_BASE_GATE>,
+				 <&sysclk K230_HS_SD0_TIMER_GATE>;
+			clock-names = "core", "bus", "axi", "block", "timer";
+			interrupts = <142 IRQ_TYPE_LEVEL_HIGH>;
+			canaan,usb-phy = <&usbphy>;
+			status = "disabled";
+		};
+
+		sdio: mmc@91581000 {
+			compatible = "canaan,k230-sdio";
+			reg = <0x0 0x91581000 0x0 0x1000>;
+			clocks = <&sysclk K230_HS_SD1_CARD_GATE>,
+				 <&sysclk K230_HS_SD1_AHB_GATE>,
+				 <&sysclk K230_HS_SD1_AXI_GATE>,
+				 <&sysclk K230_HS_SD1_BASE_GATE>,
+				 <&sysclk K230_HS_SD1_TIMER_GATE>;
+			clock-names = "core", "bus", "axi", "block", "timer";
+			interrupts = <144 IRQ_TYPE_LEVEL_HIGH>;
+			canaan,usb-phy = <&usbphy>;
+			status = "disabled";
+		};
+
 		usbphy: usb-phy@91585000 {
 			compatible = "canaan,k230-usb-phy";
 			reg = <0x0 0x91585000 0x0 0x400>;
-- 
2.53.0


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

* Re: [PATCH v2 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230
  2026-02-26 11:59 ` [PATCH v2 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 Jiayu Du
@ 2026-02-26 18:30   ` Conor Dooley
  0 siblings, 0 replies; 8+ messages in thread
From: Conor Dooley @ 2026-02-26 18:30 UTC (permalink / raw)
  To: Jiayu Du
  Cc: krzk, ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt, pjw,
	palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel,
	gaohan, me

[-- Attachment #1: Type: text/plain, Size: 662 bytes --]

On Thu, Feb 26, 2026 at 07:59:21PM +0800, Jiayu Du wrote:

> +    then:
> +      properties:
> +        clocks:
> +          minItems: 5

> +          maxItems: 5

This maxItems is not needed, as 5 is already the max. Drop it if you respin.
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable

> +        clock-names:
> +          items:
> +            - const: core
> +            - const: bus
> +            - const: axi
> +            - const: block
> +            - const: timer
> +      required:
> +        - canaan,usb-phy
> +
>    - if:
>        properties:
>          compatible:
> -- 
> 2.53.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v2 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support
  2026-02-26 11:59 ` [PATCH v2 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support Jiayu Du
@ 2026-03-04  9:25   ` Jiayu Du
  2026-03-05 11:48   ` Ulf Hansson
  1 sibling, 0 replies; 8+ messages in thread
From: Jiayu Du @ 2026-03-04  9:25 UTC (permalink / raw)
  To: ulf.hansson
  Cc: pjw, krzk, palmer, aou, linux-mmc, devicetree, linux-riscv,
	linux-kernel, gaohan, me

On Thu, Feb 26, 2026 at 07:59:22PM +0800, Jiayu Du wrote:
> Add SDHCI controller driver for Canaan k230 SoC. Implement custom
> sdhci_ops for set_clock, phy init, init and reset.
> 
> Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
> ---
>  drivers/mmc/host/sdhci-of-dwcmshc.c | 288 ++++++++++++++++++++++++++++
>  1 file changed, 288 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
> index 2b75a36c096b..21c77e908d77 100644
> --- a/drivers/mmc/host/sdhci-of-dwcmshc.c
> +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
Hi ulf, could you please take a look at this patch? Thank you!

Regards,
Jiayu Du


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

* Re: [PATCH v2 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support
  2026-02-26 11:59 ` [PATCH v2 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support Jiayu Du
  2026-03-04  9:25   ` Jiayu Du
@ 2026-03-05 11:48   ` Ulf Hansson
  2026-03-06  9:00     ` Jiayu Du
  1 sibling, 1 reply; 8+ messages in thread
From: Ulf Hansson @ 2026-03-05 11:48 UTC (permalink / raw)
  To: Jiayu Du
  Cc: krzk, adrian.hunter, robh, krzk+dt, conor+dt, pjw, palmer, aou,
	linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me

On Thu, 26 Feb 2026 at 12:59, Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn> wrote:
>
> Add SDHCI controller driver for Canaan k230 SoC. Implement custom
> sdhci_ops for set_clock, phy init, init and reset.
>
> Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
> ---
>  drivers/mmc/host/sdhci-of-dwcmshc.c | 288 ++++++++++++++++++++++++++++
>  1 file changed, 288 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
> index 2b75a36c096b..21c77e908d77 100644
> --- a/drivers/mmc/host/sdhci-of-dwcmshc.c
> +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
> @@ -128,9 +128,11 @@
>  #define PHY_CNFG_PHY_PWRGOOD_MASK      BIT_MASK(1) /* bit [1] */
>  #define PHY_CNFG_PAD_SP_MASK           GENMASK(19, 16) /* bits [19:16] */
>  #define PHY_CNFG_PAD_SP                        0x0c /* PMOS TX drive strength */
> +#define PHY_CNFG_PAD_SP_k230           0x09 /* PMOS TX drive strength for k230 */
>  #define PHY_CNFG_PAD_SP_SG2042         0x09 /* PMOS TX drive strength for SG2042 */
>  #define PHY_CNFG_PAD_SN_MASK           GENMASK(23, 20) /* bits [23:20] */
>  #define PHY_CNFG_PAD_SN                        0x0c /* NMOS TX drive strength */
> +#define PHY_CNFG_PAD_SN_k230           0x08 /* NMOS TX drive strength for k230 */
>  #define PHY_CNFG_PAD_SN_SG2042         0x08 /* NMOS TX drive strength for SG2042 */
>
>  /* PHY command/response pad settings */
> @@ -153,14 +155,22 @@
>  #define PHY_PAD_RXSEL_3V3              0x2 /* Receiver type select for 3.3V */
>
>  #define PHY_PAD_WEAKPULL_MASK          GENMASK(4, 3) /* bits [4:3] */
> +#define PHY_PAD_WEAKPULL_DISABLED      0x0 /* Weak pull up and pull down disabled */
>  #define PHY_PAD_WEAKPULL_PULLUP                0x1 /* Weak pull up enabled */
>  #define PHY_PAD_WEAKPULL_PULLDOWN      0x2 /* Weak pull down enabled */
>
>  #define PHY_PAD_TXSLEW_CTRL_P_MASK     GENMASK(8, 5) /* bits [8:5] */
>  #define PHY_PAD_TXSLEW_CTRL_P          0x3 /* Slew control for P-Type pad TX */
> +#define PHY_PAD_TXSLEW_CTRL_P_k230_VAL2        0x2 /* Slew control for P-Type pad TX for k230 */
>  #define PHY_PAD_TXSLEW_CTRL_N_MASK     GENMASK(12, 9) /* bits [12:9] */
>  #define PHY_PAD_TXSLEW_CTRL_N          0x3 /* Slew control for N-Type pad TX */
>  #define PHY_PAD_TXSLEW_CTRL_N_SG2042   0x2 /* Slew control for N-Type pad TX for SG2042 */
> +#define PHY_PAD_TXSLEW_CTRL_N_k230_VAL2        0x2 /* Slew control for N-Type pad TX for k230 */
> +#define PHY_PAD_TXSLEW_CTRL_N_k230_VAL1        0x1 /* Slew control for N-Type pad TX for k230 */
> +
> +/* PHY Common DelayLine config settings */
> +#define PHY_COMMDL_CNFG                        (DWC_MSHC_PTR_PHY_R + 0x1c)
> +#define PHY_COMMDL_CNFG_DLSTEP_SEL     BIT(0) /* DelayLine outputs on PAD enabled */
>
>  /* PHY CLK delay line settings */
>  #define PHY_SDCLKDL_CNFG_R             (DWC_MSHC_PTR_PHY_R + 0x1d)
> @@ -174,7 +184,10 @@
>  #define PHY_SDCLKDL_DC_HS400           0x18 /* delay code for HS400 mode */
>
>  #define PHY_SMPLDL_CNFG_R              (DWC_MSHC_PTR_PHY_R + 0x20)
> +#define PHY_SMPLDL_CNFG_EXTDLY_EN      BIT(0)
>  #define PHY_SMPLDL_CNFG_BYPASS_EN      BIT(1)
> +#define PHY_SMPLDL_CNFG_INPSEL_MASK    GENMASK(3, 2) /* bits [3:2] */
> +#define PHY_SMPLDL_CNFG_INPSEL         0x3 /* delay line input source */
>
>  /* PHY drift_cclk_rx delay line configuration setting */
>  #define PHY_ATDL_CNFG_R                        (DWC_MSHC_PTR_PHY_R + 0x21)
> @@ -227,6 +240,14 @@
>  /* SMC call for BlueField-3 eMMC RST_N */
>  #define BLUEFIELD_SMC_SET_EMMC_RST_N   0x82000007
>
> +/* Canaan specific Registers */
> +#define SD0_CTRL                       0x00
> +#define SD0_HOST_REG_VOL_STABLE                BIT(4)
> +#define SD0_CARD_WRITE_PROT            BIT(6)
> +#define SD1_CTRL                       0x08
> +#define SD1_HOST_REG_VOL_STABLE                BIT(0)
> +#define SD1_CARD_WRITE_PROT            BIT(2)
> +
>  /* Eswin specific Registers */
>  #define EIC7700_CARD_CLK_STABLE                BIT(28)
>  #define EIC7700_INT_BCLK_STABLE                BIT(16)
> @@ -268,6 +289,12 @@ struct eic7700_priv {
>         unsigned int drive_impedance;
>  };
>
> +struct k230_priv  {
> +       /* Kendryte k230 specific */
> +       struct regmap *hi_sys_regmap;
> +       const struct dwcmshc_k230_match_data *match_data;
> +};
> +
>  #define DWCMSHC_MAX_OTHER_CLKS 3
>
>  struct dwcmshc_priv {
> @@ -284,12 +311,34 @@ struct dwcmshc_priv {
>  };
>
>  struct dwcmshc_pltfm_data {
> +       const void *match_data;

This makes sense to me!

Although, I realized that dwcmshc_rk35xx_init() could also move its
assignment of "devtype" into this match_data.

Can you please create a follow-up patch to fixup this and to avoid
storing this type of data in two different ways?

>         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 (*postinit)(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv);
>  };
>
> +struct dwcmshc_k230_match_data {
> +       bool is_emmc;
> +       u32 ctrl_reg;
> +       u32 vol_stable_bit;
> +       u32 write_prot_bit;
> +};
> +
> +static const struct dwcmshc_k230_match_data k230_emmc_match_data = {
> +       .is_emmc = true,
> +       .ctrl_reg = SD0_CTRL,
> +       .vol_stable_bit = SD0_HOST_REG_VOL_STABLE,
> +       .write_prot_bit = SD0_CARD_WRITE_PROT,
> +};
> +
> +static const struct dwcmshc_k230_match_data k230_sdio_match_data = {
> +       .is_emmc = false,
> +       .ctrl_reg = SD1_CTRL,
> +       .vol_stable_bit = SD1_HOST_REG_VOL_STABLE,
> +       .write_prot_bit = SD1_CARD_WRITE_PROT,
> +};

[...]

> +
> +static int dwcmshc_k230_init(struct device *dev, struct sdhci_host *host,
> +                            struct dwcmshc_priv *dwc_priv)
> +{
> +       static const char * const clk_ids[] = {"block", "timer", "axi"};
> +       const struct dwcmshc_k230_match_data *match_data;
> +       const struct dwcmshc_pltfm_data *pltfm_data;
> +       struct device_node *usb_phy_node;
> +       struct k230_priv *k230_priv;
> +       u32 data;
> +       int ret;
> +
> +       pltfm_data = device_get_match_data(dev);
> +
> +       if (!pltfm_data || !pltfm_data->match_data) {
> +               dev_err(dev, "No vendor data found for K230\n");
> +               return -EINVAL;
> +       }
> +       match_data = pltfm_data->match_data;

I don't think this should be specific to dwcmshc_k230_init().

Instead I suggest adding a "const void *match_data" to the "struct
dwcmshc_priv" - and copy the pointer in the common dwcmshc_probe()
instead. In this way, all variants will be able to use it.

> +
> +       k230_priv = devm_kzalloc(dev, sizeof(struct k230_priv), GFP_KERNEL);
> +       if (!k230_priv)
> +               return -ENOMEM;
> +
> +       k230_priv->match_data = match_data;
> +       dwc_priv->priv = k230_priv;
> +
> +       usb_phy_node = of_parse_phandle(dev->of_node, "canaan,usb-phy", 0);
> +       if (!usb_phy_node)
> +               return dev_err_probe(dev, -ENODEV,
> +                                    "Failed to find canaan,usb-phy phandle\n");
> +
> +       k230_priv->hi_sys_regmap = device_node_to_regmap(usb_phy_node);
> +       of_node_put(usb_phy_node);
> +
> +       if (IS_ERR(k230_priv->hi_sys_regmap))
> +               return dev_err_probe(dev, PTR_ERR(k230_priv->hi_sys_regmap),
> +                                    "Failed to get k230-usb-phy regmap\n");
> +
> +       ret = dwcmshc_get_enable_other_clks(mmc_dev(host->mmc), dwc_priv,
> +                                           ARRAY_SIZE(clk_ids), clk_ids);
> +       if (ret)
> +               return dev_err_probe(dev, ret,
> +                                    "Failed to get/enable k230 mmc other clocks\n");
> +
> +       if (match_data->is_emmc) {
> +               host->flags &= ~SDHCI_SIGNALING_330;
> +               dwc_priv->flags |= FLAG_IO_FIXED_1V8;
> +       } else {
> +               host->mmc->caps |= MMC_CAP_SD_HIGHSPEED;
> +               host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
> +       }
> +
> +       ret = regmap_read(k230_priv->hi_sys_regmap, match_data->ctrl_reg, &data);
> +       if (ret)
> +               return dev_err_probe(dev, ret, "Failed to read control reg 0x%x\n",
> +                                    match_data->ctrl_reg);
> +
> +       data |= match_data->write_prot_bit | match_data->vol_stable_bit;
> +       ret = regmap_write(k230_priv->hi_sys_regmap, match_data->ctrl_reg, data);
> +       if (ret)
> +               return dev_err_probe(dev, ret, "Failed to write control reg 0x%x\n",
> +                                    match_data->ctrl_reg);
> +
> +       return 0;
> +}

[...]

Kind regards
Uffe

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

* Re: [PATCH v2 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support
  2026-03-05 11:48   ` Ulf Hansson
@ 2026-03-06  9:00     ` Jiayu Du
  0 siblings, 0 replies; 8+ messages in thread
From: Jiayu Du @ 2026-03-06  9:00 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: krzk, adrian.hunter, robh, krzk+dt, conor+dt, pjw, palmer, aou,
	linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me

On Thu, Mar 05, 2026 at 12:48:29PM +0100, Ulf Hansson wrote:
> On Thu, 26 Feb 2026 at 12:59, Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn> wrote:
> >
> > Add SDHCI controller driver for Canaan k230 SoC. Implement custom
> > sdhci_ops for set_clock, phy init, init and reset.
> >
> > Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
> > ---
> >  drivers/mmc/host/sdhci-of-dwcmshc.c | 288 ++++++++++++++++++++++++++++
> >  1 file changed, 288 insertions(+)
> >
> > diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
> > index 2b75a36c096b..21c77e908d77 100644
> > --- a/drivers/mmc/host/sdhci-of-dwcmshc.c
> > +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
...
> >  struct dwcmshc_pltfm_data {
> > +       const void *match_data;
> 
> This makes sense to me!
> 
> Although, I realized that dwcmshc_rk35xx_init() could also move its
> assignment of "devtype" into this match_data.
> 
> Can you please create a follow-up patch to fixup this and to avoid
> storing this type of data in two different ways?
> 
...
> > +static int dwcmshc_k230_init(struct device *dev, struct sdhci_host *host,
> > +                            struct dwcmshc_priv *dwc_priv)
> > +{
> > +       static const char * const clk_ids[] = {"block", "timer", "axi"};
> > +       const struct dwcmshc_k230_match_data *match_data;
> > +       const struct dwcmshc_pltfm_data *pltfm_data;
> > +       struct device_node *usb_phy_node;
> > +       struct k230_priv *k230_priv;
> > +       u32 data;
> > +       int ret;
> > +
> > +       pltfm_data = device_get_match_data(dev);
> > +
> > +       if (!pltfm_data || !pltfm_data->match_data) {
> > +               dev_err(dev, "No vendor data found for K230\n");
> > +               return -EINVAL;
> > +       }
> > +       match_data = pltfm_data->match_data;
> 
> I don't think this should be specific to dwcmshc_k230_init().
> 
> Instead I suggest adding a "const void *match_data" to the "struct
> dwcmshc_priv" - and copy the pointer in the common dwcmshc_probe()
> instead. In this way, all variants will be able to use it.

Your suggestions make perfect sense. I'll prepare a new version to add
the "const void *match_data" to "struct dwcmshc_priv", assign it in
"dwcmshc_probe()", and adjust the K230 init accordingly.

I'll also migrate the rk35xx devtype assignment to match_data for
consistency. Once ready, I'll post the link as a reply to this k230 mmc
series.

Best regards,
Jiayu Du

> 
> Kind regards
> Uffe


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

end of thread, other threads:[~2026-03-06  9:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-26 11:59 [PATCH v2 0/3] Add SDHCI support for Canaan K230 SoC Jiayu Du
2026-02-26 11:59 ` [PATCH v2 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 Jiayu Du
2026-02-26 18:30   ` Conor Dooley
2026-02-26 11:59 ` [PATCH v2 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support Jiayu Du
2026-03-04  9:25   ` Jiayu Du
2026-03-05 11:48   ` Ulf Hansson
2026-03-06  9:00     ` Jiayu Du
2026-02-26 11:59 ` [PATCH v2 3/3] riscv: dts: canaan: Add mmc nodes for K230 Jiayu Du

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