linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead
@ 2023-08-05  3:14 Drew Fustini
  2023-08-05  3:14 ` [PATCH RFC v2 1/4] dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support Drew Fustini
                   ` (4 more replies)
  0 siblings, 5 replies; 16+ messages in thread
From: Drew Fustini @ 2023-08-05  3:14 UTC (permalink / raw)
  To: Jisheng Zhang, Guo Ren, Fu Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Conor Dooley, Adrian Hunter, Ulf Hansson
  Cc: linux-riscv, devicetree, linux-kernel, linux-mmc, Robert Nelson,
	Jason Kridner, Drew Fustini

This series adds initial support for the eMMC on the BeagleV Ahead
board. This allows the kernel to boot with the root fs on eMMC.

I tested [1] on top of v6.5-rc3 with this config [2] along with the
prerequisite series [3] that adds the BeagleV Ahead dts file.

I am submitting this as an RFC for other people that want to test
booting from the eMMC with mainline. There are several issues that need
to be resolved before this code can progress beyond an RFC:

  - Only the MMC controller connected to the eMMC is enabled. I did
    not yet attempt to configure or use the microSD card slot.

  - The thead,th1520-dwcmshc compatible sets quirks which disable DMA
    and forces the use of inefficient PIO mode. I need to determine the
    correct configuration for the SDMA and ADMA modes.

  - th1520-specific code is needed in dwcmshc_set_uhs_signaling() for
    MMC_TIMING_MMC_HS400. I have not figured out add proper way to make
    that code conditional so that it only runs on th1520. One method
    could be to add a th1520 flag to dwcmshc_priv but that seems like a
    hack. Alternatively, set_uhs_signaling in sdhci_dwcmshc_th1520_ops
    could point to a th1520-specific function, but that new function
    would have to duplicate all the code in the current
    dwcmshc_set_uhs_signaling().

NOTE: I combined schema, dts and driver patches into this one series to
simplify review and testing of this RFC.

References:
[1] https://gist.github.com/pdp7/09995be1e30df0a04b9b9cd31420f9d5
[2] https://gist.github.com/pdp7/e4585311eb2cd27df7b50c87babc15fd
[3] https://lore.kernel.org/linux-riscv/20230722-upstream-beaglev-ahead-dts-v2-0-a470ab8fe806@baylibre.com/

Changes in v2:
- Expand dwcmshc_priv based on driver in the T-Head 5.10 kernel:
  delay_line, non_removable, pull_up_en, io_fixed_1v8
- New boolean property "thead,pull-up" indicates phy pull-up config
- New boolean property "thead,io-fixed-1v8" indicates that io voltage
  should be set to 1.8V during reset
- Add th1520_phy_1_8v_init() as voltage_switch op
- Add th1520_execute_tuning() as the platform_execute_tuning op
- Added th1520_sdhci_reset() as the .reset op. This function will set
  io voltage to 1.8V after calling the standard sdhci_reset() function.
- Modified dwcmshc_set_uhs_signaling() to enable SDHCI_CTRL_VDD_180 when
  io_fixed_1v8 is true
- Add many defines for register offsets and settings based on the mmc
  support in the T-Head downstream v5.10 kernel

v1 series:
https://lore.kernel.org/r/20230724-th1520-emmc-v1-0-cca1b2533da2@baylibre.com

Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
Drew Fustini (4):
      dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support
      riscv: dts: thead: Add TH1520 mmc controller and sdhci clock
      riscv: dts: thead: Enable BeagleV Ahead eMMC controller
      mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520

 .../bindings/mmc/snps,dwcmshc-sdhci.yaml           |   9 +
 arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts |  17 ++
 arch/riscv/boot/dts/thead/th1520.dtsi              |  17 ++
 drivers/mmc/host/sdhci-of-dwcmshc.c                | 336 +++++++++++++++++++++
 4 files changed, 379 insertions(+)
---
base-commit: cb8c874afdc063290797ae1776a5d410fecb06cb
change-id: 20230724-th1520-emmc-73cde98805d6

Best regards,
-- 
Drew Fustini <dfustini@baylibre.com>


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

* [PATCH RFC v2 1/4] dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support
  2023-08-05  3:14 [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead Drew Fustini
@ 2023-08-05  3:14 ` Drew Fustini
  2023-08-07  6:29   ` Krzysztof Kozlowski
  2023-08-05  3:14 ` [PATCH RFC v2 2/4] riscv: dts: thead: Add TH1520 mmc controller and sdhci clock Drew Fustini
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 16+ messages in thread
From: Drew Fustini @ 2023-08-05  3:14 UTC (permalink / raw)
  To: Jisheng Zhang, Guo Ren, Fu Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Conor Dooley, Adrian Hunter, Ulf Hansson
  Cc: linux-riscv, devicetree, linux-kernel, linux-mmc, Robert Nelson,
	Jason Kridner, Drew Fustini

Add compatible value for the T-Head TH1520 dwcmshc controller and
thead,io-fixed-1v8 and thead,pull-up properties.

Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
 Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
index a43eb837f8da..57602c345cab 100644
--- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
@@ -19,6 +19,7 @@ properties:
       - rockchip,rk3568-dwcmshc
       - rockchip,rk3588-dwcmshc
       - snps,dwcmshc-sdhci
+      - thead,th1520-dwcmshc
 
   reg:
     maxItems: 1
@@ -60,6 +61,14 @@ properties:
     description: Specify the number of delay for tx sampling.
     $ref: /schemas/types.yaml#/definitions/uint8
 
+  thead,io-fixed-1v8:
+    description: SoC PHY pad is fixed 1.8V
+    type: boolean
+
+  thead,pull-up:
+    description: True if pull-up, false if pull-down
+    type: boolean
+
 
 required:
   - compatible

-- 
2.34.1


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

* [PATCH RFC v2 2/4] riscv: dts: thead: Add TH1520 mmc controller and sdhci clock
  2023-08-05  3:14 [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead Drew Fustini
  2023-08-05  3:14 ` [PATCH RFC v2 1/4] dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support Drew Fustini
@ 2023-08-05  3:14 ` Drew Fustini
  2023-08-05  3:14 ` [PATCH RFC v2 3/4] riscv: dts: thead: Enable BeagleV Ahead eMMC controller Drew Fustini
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 16+ messages in thread
From: Drew Fustini @ 2023-08-05  3:14 UTC (permalink / raw)
  To: Jisheng Zhang, Guo Ren, Fu Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Conor Dooley, Adrian Hunter, Ulf Hansson
  Cc: linux-riscv, devicetree, linux-kernel, linux-mmc, Robert Nelson,
	Jason Kridner, Drew Fustini

Add nodes for the SDHCI fixed clock and the first mmc controller which
is typically connected to the eMMC device.

Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
 arch/riscv/boot/dts/thead/th1520.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/thead/th1520.dtsi
index 56a73134b49e..b33bfb04c955 100644
--- a/arch/riscv/boot/dts/thead/th1520.dtsi
+++ b/arch/riscv/boot/dts/thead/th1520.dtsi
@@ -134,6 +134,13 @@ uart_sclk: uart-sclk-clock {
 		#clock-cells = <0>;
 	};
 
+	sdhci_clk: sdhci-clock {
+		compatible = "fixed-clock";
+		clock-frequency = <198000000>;
+		clock-output-names = "sdhci_clk";
+		#clock-cells = <0>;
+	};
+
 	soc {
 		compatible = "simple-bus";
 		interrupt-parent = <&plic>;
@@ -291,6 +298,16 @@ dmac0: dma-controller@ffefc00000 {
 			status = "disabled";
 		};
 
+		mmc0: mmc@ffe7080000 {
+			compatible = "thead,th1520-dwcmshc";
+			reg = <0xff 0xe7080000 0x0 0x10000
+			       0xff 0xef014060 0x0 0x4>;
+			interrupts = <62 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "sdhciirq";
+			clocks = <&sdhci_clk>;
+			clock-names = "core";
+		};
+
 		timer0: timer@ffefc32000 {
 			compatible = "snps,dw-apb-timer";
 			reg = <0xff 0xefc32000 0x0 0x14>;

-- 
2.34.1


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

* [PATCH RFC v2 3/4] riscv: dts: thead: Enable BeagleV Ahead eMMC controller
  2023-08-05  3:14 [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead Drew Fustini
  2023-08-05  3:14 ` [PATCH RFC v2 1/4] dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support Drew Fustini
  2023-08-05  3:14 ` [PATCH RFC v2 2/4] riscv: dts: thead: Add TH1520 mmc controller and sdhci clock Drew Fustini
@ 2023-08-05  3:14 ` Drew Fustini
  2023-08-05  3:14 ` [PATCH RFC v2 4/4] mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520 Drew Fustini
  2023-08-28  4:40 ` [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead Jiexun Wang
  4 siblings, 0 replies; 16+ messages in thread
From: Drew Fustini @ 2023-08-05  3:14 UTC (permalink / raw)
  To: Jisheng Zhang, Guo Ren, Fu Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Conor Dooley, Adrian Hunter, Ulf Hansson
  Cc: linux-riscv, devicetree, linux-kernel, linux-mmc, Robert Nelson,
	Jason Kridner, Drew Fustini

Add properties to the emmc node and enable it and set the frequency for
the sdhci clock.

Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
 arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts b/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts
index c315e5bd3d2d..f93c11754639 100644
--- a/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts
+++ b/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts
@@ -52,6 +52,10 @@ &uart_sclk {
 	clock-frequency = <100000000>;
 };
 
+&sdhci_clk {
+	clock-frequency = <198000000>;
+};
+
 &dmac0 {
 	status = "okay";
 };
@@ -59,3 +63,16 @@ &dmac0 {
 &uart0 {
 	status = "okay";
 };
+
+&mmc0 {
+	max-frequency = <198000000>;
+	non-removable;
+	mmc-hs400-1_8v;
+	thead,io-fixed-1v8;
+	no-sdio;
+	no-sd;
+	thead,pull-up;
+	bus-width = <8>;
+	status = "okay";
+
+};

-- 
2.34.1


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

* [PATCH RFC v2 4/4] mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520
  2023-08-05  3:14 [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead Drew Fustini
                   ` (2 preceding siblings ...)
  2023-08-05  3:14 ` [PATCH RFC v2 3/4] riscv: dts: thead: Enable BeagleV Ahead eMMC controller Drew Fustini
@ 2023-08-05  3:14 ` Drew Fustini
  2023-08-06 10:09   ` Jisheng Zhang
  2023-08-28  4:40 ` [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead Jiexun Wang
  4 siblings, 1 reply; 16+ messages in thread
From: Drew Fustini @ 2023-08-05  3:14 UTC (permalink / raw)
  To: Jisheng Zhang, Guo Ren, Fu Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Conor Dooley, Adrian Hunter, Ulf Hansson
  Cc: linux-riscv, devicetree, linux-kernel, linux-mmc, Robert Nelson,
	Jason Kridner, Drew Fustini

Add basic support for the T-Head TH1520 SoC mmc controller with the new
compatible "thead,th1520-dwcmshc".

However, quirks are currently set to disable DMA and use PIO. The proper
settings for DMA support still need to be determined.

Another issue is th1520-specific code for MMC_TIMING_MMC_HS400 in
dwcmshc_set_uhs_signaling() will run on all platforms which is not
correct. One solution could be to add a th1520 flag to dwcmshc_priv but
that is hacky. Another solution could be to set the set_uhs_signaling op
in sdhci_dwcmshc_th1520_ops to a th1520-specific function. However, that
new function would have to duplicate all the code in the current
dwcmshc_set_uhs_signaling().

Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
 drivers/mmc/host/sdhci-of-dwcmshc.c | 336 ++++++++++++++++++++++++++++++++++++
 1 file changed, 336 insertions(+)

diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
index e68cd87998c8..d35e204cdb16 100644
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
@@ -71,6 +71,63 @@
 	(((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
 #define RK35xx_MAX_CLKS 3
 
+/* T-Head specific registers */
+#define DWC_MSHC_PTR_PHY_R	0x300
+#define PHY_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x00)
+#define PHY_RSTN		0x0
+#define PAD_SP			0x10
+#define PAD_SN			0x14
+
+#define PHY_CMDPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x04)
+#define PHY_DATAPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x06)
+#define PHY_CLKPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x08)
+#define PHY_STBPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0a)
+#define PHY_RSTNPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0c)
+#define RXSEL			0x0
+#define WEAKPULL_EN		0x3
+#define TXSLEW_CTRL_P		0x5
+#define TXSLEW_CTRL_N		0x9
+
+#define PHY_PADTEST_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0e)
+#define PHY_PADTEST_OUT_R	(DWC_MSHC_PTR_PHY_R + 0x10)
+#define PHY_PADTEST_IN_R	(DWC_MSHC_PTR_PHY_R + 0x12)
+#define PHY_PRBS_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x18)
+#define PHY_PHYLBK_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1a)
+#define PHY_COMMDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1c)
+
+#define PHY_SDCLKDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1d)
+#define UPDATE_DC		0x4
+
+#define PHY_SDCLKDL_DC_R	(DWC_MSHC_PTR_PHY_R + 0x1e)
+#define PHY_SMPLDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x20)
+#define PHY_ATDL_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x21)
+#define INPSEL_CNFG		2
+
+#define PHY_DLL_CTRL_R		(DWC_MSHC_PTR_PHY_R + 0x24)
+#define DLL_EN			0x0
+
+#define PHY_DLL_CNFG1_R		(DWC_MSHC_PTR_PHY_R + 0x25)
+#define PHY_DLL_CNFG2_R		(DWC_MSHC_PTR_PHY_R + 0x26)
+#define PHY_DLLDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x28)
+#define SLV_INPSEL		0x5
+
+#define P_VENDOR_SPECIFIC_AREA	0x500
+#define EMMC_CTRL_R		(P_VENDOR_SPECIFIC_AREA + 0x2c)
+#define AT_CTRL_R		(P_VENDOR_SPECIFIC_AREA + 0x40)
+#define AT_EN			0x0
+#define CI_SEL			0x1
+#define SWIN_TH_EN		0x2
+#define RPT_TUNE_ERR		0x3
+#define SW_TUNE_EN		0x4
+#define WIN_EDGE_SEL		0x8
+#define TUNE_CLK_STOP_EN	0x10
+#define PRE_CHANGE_DLY		0x11
+#define POST_CHANGE_DLY		0x13
+#define SWIN_TH_VAL		0x18
+
+#define DELAY_LINE_HS400	24
+#define DELAY_LINE_DEFAULT	50
+
 #define BOUNDARY_OK(addr, len) \
 	((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
 
@@ -91,6 +148,10 @@ struct dwcmshc_priv {
 	struct clk	*bus_clk;
 	int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */
 	void *priv; /* pointer to SoC private stuff */
+	uint32_t delay_line;
+	bool non_removable;
+	bool pull_up_en;
+	bool io_fixed_1v8;
 };
 
 /*
@@ -156,11 +217,171 @@ static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 	sdhci_request(mmc, mrq);
 }
 
+static void sdhci_phy_1_8v_init_no_pull(struct sdhci_host *host)
+{
+	uint32_t val;
+	sdhci_writel(host, 1, DWC_MSHC_PTR_PHY_R);
+	sdhci_writeb(host, 1 << 4, PHY_SDCLKDL_CNFG_R);
+	sdhci_writeb(host, 0x40, PHY_SDCLKDL_DC_R);
+
+	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
+	val &= ~(1 << 4);
+	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
+
+
+	val = sdhci_readw(host, PHY_CMDPAD_CNFG_R);
+	sdhci_writew(host, val | 1, PHY_CMDPAD_CNFG_R);
+
+	val = sdhci_readw(host, PHY_DATAPAD_CNFG_R);
+	sdhci_writew(host, val | 1, PHY_DATAPAD_CNFG_R);
+
+	val = sdhci_readw(host, PHY_RSTNPAD_CNFG_R);
+	sdhci_writew(host, val | 1, PHY_RSTNPAD_CNFG_R);
+
+	val = sdhci_readw(host, PHY_STBPAD_CNFG_R);
+	sdhci_writew(host, val | 1, PHY_STBPAD_CNFG_R);
+
+	val = sdhci_readb(host, PHY_DLL_CTRL_R);
+	sdhci_writeb(host, val | 1, PHY_DLL_CTRL_R);
+}
+
+static void sdhci_phy_3_3v_init_no_pull(struct sdhci_host *host)
+{
+	uint32_t val;
+
+	sdhci_writel(host, 1, DWC_MSHC_PTR_PHY_R);
+	sdhci_writeb(host, 1 << 4, PHY_SDCLKDL_CNFG_R);
+	sdhci_writeb(host, 0x40, PHY_SDCLKDL_DC_R);
+
+	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
+	val &= ~(1 << 4);
+	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
+
+	val = sdhci_readw(host, PHY_CMDPAD_CNFG_R);
+	sdhci_writew(host, val | 2, PHY_CMDPAD_CNFG_R);
+
+	val = sdhci_readw(host, PHY_DATAPAD_CNFG_R);
+	sdhci_writew(host, val | 2, PHY_DATAPAD_CNFG_R);
+
+	val = sdhci_readw(host, PHY_RSTNPAD_CNFG_R);
+	sdhci_writew(host, val | 2, PHY_RSTNPAD_CNFG_R);
+
+	val = sdhci_readw(host, PHY_STBPAD_CNFG_R);
+	sdhci_writew(host, val | 2, PHY_STBPAD_CNFG_R);
+
+	val = sdhci_readb(host, PHY_DLL_CTRL_R);
+	sdhci_writeb(host, val | 1, PHY_DLL_CTRL_R);
+}
+
+static void th1520_phy_1_8v_init(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	u32 val;
+
+	if (!priv)
+		return;
+
+	if (priv->pull_up_en == 0) {
+		sdhci_phy_1_8v_init_no_pull(host);
+		return;
+	}
+
+	/* set driving force */
+	sdhci_writel(host, (1 << PHY_RSTN) | (0xc << PAD_SP) | (0xc << PAD_SN), PHY_CNFG_R);
+
+	/* disable delay lane */
+	sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
+
+	/* set delay lane */
+	sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R);
+	sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R);
+
+	/* enable delay lane */
+	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
+	val &= ~(1 << UPDATE_DC);
+	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
+
+	val = (1 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
+	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 = (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
+	sdhci_writew(host, val, PHY_CLKPAD_CNFG_R);
+
+	val = (1 << RXSEL) | (2 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
+	sdhci_writew(host, val, PHY_STBPAD_CNFG_R);
+
+	/* enable data strobe mode */
+	sdhci_writeb(host, 3 << SLV_INPSEL, PHY_DLLDL_CNFG_R);
+	sdhci_writeb(host, (1 << DLL_EN),  PHY_DLL_CTRL_R);
+}
+
+static void th1520_phy_3_3v_init(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	u32 val;
+
+	if (priv->pull_up_en == 0) {
+		sdhci_phy_3_3v_init_no_pull(host);
+		return;
+	}
+
+	/* set driving force */
+	sdhci_writel(host, (1 << PHY_RSTN) | (0xc << PAD_SP) | (0xc << PAD_SN), PHY_CNFG_R);
+
+	/* disable delay lane */
+	sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
+
+	/* set delay lane */
+	sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R);
+	sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R);
+
+	/* enable delay lane */
+	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
+	val &= ~(1 << UPDATE_DC);
+	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
+
+	val = (2 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
+	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 = (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
+	sdhci_writew(host, val, PHY_CLKPAD_CNFG_R);
+
+	val = (2 << RXSEL) | (2 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
+	sdhci_writew(host, val, PHY_STBPAD_CNFG_R);
+}
+
+
+static void th1520_sdhci_set_phy(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	u8 emmc_ctl;
+
+	/* Before power on, set PHY configs */
+	emmc_ctl = sdhci_readw(host, EMMC_CTRL_R);
+	if (priv->non_removable) {
+		th1520_phy_1_8v_init(host);
+		emmc_ctl |= (1 << DWCMSHC_CARD_IS_EMMC);
+	} else {
+		th1520_phy_3_3v_init(host);
+		emmc_ctl &=~(1 << DWCMSHC_CARD_IS_EMMC);
+	}
+	sdhci_writeb(host, emmc_ctl, EMMC_CTRL_R);
+	sdhci_writeb(host, 0x25, PHY_DLL_CNFG1_R);
+}
+
 static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
 				      unsigned int timing)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+
 	u16 ctrl, ctrl_2;
 
 	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
@@ -188,7 +409,22 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
 		ctrl_2 |= DWCMSHC_CTRL_HS400;
 	}
 
+	if (priv->io_fixed_1v8)
+		ctrl_2 |= SDHCI_CTRL_VDD_180;
+
 	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+
+	/* TODO: add check so that this only runs on th1520  */
+	if (timing == MMC_TIMING_MMC_HS400) {
+		/* disable auto tuning */
+		u32 reg = sdhci_readl(host, AT_CTRL_R);
+		reg &= ~1;
+		sdhci_writel(host, reg, AT_CTRL_R);
+		priv->delay_line = DELAY_LINE_HS400;
+		th1520_sdhci_set_phy(host);
+	} else {
+		sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R);
+	}
 }
 
 static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc,
@@ -337,6 +573,49 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
 	sdhci_reset(host, mask);
 }
 
+static int th1520_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+	u32 val = 0;
+
+	sdhci_writeb(host, 3 << INPSEL_CNFG, PHY_ATDL_CNFG_R);
+
+	val = sdhci_readl(host, AT_CTRL_R);
+	val &= ~((1 << CI_SEL) | (1 << RPT_TUNE_ERR) \
+	    | (1 << SW_TUNE_EN) |(0xf << WIN_EDGE_SEL));
+	val |= (1 << AT_EN) | (1 << SWIN_TH_EN) | (1 << TUNE_CLK_STOP_EN)\
+	    | (1 << PRE_CHANGE_DLY) | (3 << POST_CHANGE_DLY) | (9 << SWIN_TH_VAL);
+
+	sdhci_writel(host, val, AT_CTRL_R);
+
+	val = sdhci_readl(host, AT_CTRL_R);
+	if(!(val & (1 << AT_EN))) {
+		pr_warn("%s(): auto tuning is not enabled", __func__);
+		return -1;
+	}
+
+	val &= ~(1 << AT_EN);
+	sdhci_writel(host, val, AT_CTRL_R);
+
+	return 0;
+}
+
+static void th1520_sdhci_reset(struct sdhci_host *host, u8 mask)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	u16 ctrl_2;
+
+	sdhci_reset(host, mask);
+
+	if(priv->io_fixed_1v8){
+		ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+		if(! (ctrl_2 & SDHCI_CTRL_VDD_180)){
+			ctrl_2 |= SDHCI_CTRL_VDD_180;
+			sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+		}
+	}
+}
+
 static const struct sdhci_ops sdhci_dwcmshc_ops = {
 	.set_clock		= sdhci_set_clock,
 	.set_bus_width		= sdhci_set_bus_width,
@@ -355,6 +634,17 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
 	.adma_write_desc	= dwcmshc_adma_write_desc,
 };
 
+static const struct sdhci_ops sdhci_dwcmshc_th1520_ops = {
+	.set_clock		= sdhci_set_clock,
+	.set_bus_width		= sdhci_set_bus_width,
+	.set_uhs_signaling	= dwcmshc_set_uhs_signaling,
+	.get_max_clock		= dwcmshc_get_max_clock,
+	.reset			= th1520_sdhci_reset,
+	.adma_write_desc	= dwcmshc_adma_write_desc,
+	.voltage_switch		= th1520_phy_1_8v_init,
+	.platform_execute_tuning = &th1520_execute_tuning,
+};
+
 static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
 	.ops = &sdhci_dwcmshc_ops,
 	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
@@ -378,6 +668,15 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
 		   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
 };
 
+static const struct sdhci_pltfm_data sdhci_dwcmshc_th1520_pdata = {
+	.ops = &sdhci_dwcmshc_th1520_ops,
+
+	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
+		  SDHCI_QUIRK_BROKEN_DMA |
+		  SDHCI_QUIRK_BROKEN_ADMA,
+	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+};
+
 static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
 {
 	int err;
@@ -434,6 +733,10 @@ static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv
 }
 
 static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
+	{
+		.compatible = "thead,th1520-dwcmshc",
+		.data = &sdhci_dwcmshc_th1520_pdata,
+	},
 	{
 		.compatible = "rockchip,rk3588-dwcmshc",
 		.data = &sdhci_dwcmshc_rk35xx_pdata,
@@ -541,6 +844,39 @@ static int dwcmshc_probe(struct platform_device *pdev)
 			goto err_clk;
 	}
 
+	if (pltfm_data == &sdhci_dwcmshc_th1520_pdata) {
+
+		priv->delay_line = DELAY_LINE_DEFAULT;
+
+		if (device_property_present(&pdev->dev, "non-removable"))
+			priv->non_removable = 1;
+		else
+			priv->non_removable = 0;
+
+		if (device_property_present(&pdev->dev, "thead,pull-up"))
+			priv->pull_up_en = 1;
+		else
+			priv->pull_up_en = 0;
+
+		if (device_property_present(&pdev->dev, "thead,io-fixed-1v8"))
+			priv->io_fixed_1v8 = true;
+		else
+			priv->io_fixed_1v8 = false;
+
+		/*
+		 * start_signal_voltage_switch() will try 3.3V first
+		 * then 1.8V. Use SDHCI_SIGNALING_180 ranther than
+		 * SDHCI_SIGNALING_330 to avoid setting voltage to 3.3V
+		 * in sdhci_start_signal_voltage_switch().
+		 */
+		if(priv->io_fixed_1v8){
+			host->flags &=~SDHCI_SIGNALING_330;
+			host->flags |= SDHCI_SIGNALING_180;
+		}
+
+		sdhci_enable_v4_mode(host);
+	}
+
 #ifdef CONFIG_ACPI
 	if (pltfm_data == &sdhci_dwcmshc_bf3_pdata)
 		sdhci_enable_v4_mode(host);

-- 
2.34.1


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

* Re: [PATCH RFC v2 4/4] mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520
  2023-08-05  3:14 ` [PATCH RFC v2 4/4] mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520 Drew Fustini
@ 2023-08-06 10:09   ` Jisheng Zhang
  2023-08-16 21:17     ` Drew Fustini
  0 siblings, 1 reply; 16+ messages in thread
From: Jisheng Zhang @ 2023-08-06 10:09 UTC (permalink / raw)
  To: Drew Fustini
  Cc: Guo Ren, Fu Wei, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Paul Walmsley, Palmer Dabbelt, Albert Ou, Conor Dooley,
	Adrian Hunter, Ulf Hansson, linux-riscv, devicetree,
	linux-kernel, linux-mmc, Robert Nelson, Jason Kridner

On Fri, Aug 04, 2023 at 08:14:48PM -0700, Drew Fustini wrote:
> Add basic support for the T-Head TH1520 SoC mmc controller with the new
> compatible "thead,th1520-dwcmshc".
> 
> However, quirks are currently set to disable DMA and use PIO. The proper
> settings for DMA support still need to be determined.

Hi Drew,

Thank you for this patch. I think we need to make DMA work even in the
first version.

Several comments below.

> 
> Another issue is th1520-specific code for MMC_TIMING_MMC_HS400 in
> dwcmshc_set_uhs_signaling() will run on all platforms which is not
> correct. One solution could be to add a th1520 flag to dwcmshc_priv but
> that is hacky. Another solution could be to set the set_uhs_signaling op
> in sdhci_dwcmshc_th1520_ops to a th1520-specific function. However, that
> new function would have to duplicate all the code in the current
> dwcmshc_set_uhs_signaling().
> 
> Signed-off-by: Drew Fustini <dfustini@baylibre.com>
> ---
>  drivers/mmc/host/sdhci-of-dwcmshc.c | 336 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 336 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
> index e68cd87998c8..d35e204cdb16 100644
> --- a/drivers/mmc/host/sdhci-of-dwcmshc.c
> +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
> @@ -71,6 +71,63 @@
>  	(((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
>  #define RK35xx_MAX_CLKS 3
>  
> +/* T-Head specific registers */

I guess this may not be T-HEAD specific but dwc phy, could you please
check?
> +#define DWC_MSHC_PTR_PHY_R	0x300
> +#define PHY_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x00)
> +#define PHY_RSTN		0x0
> +#define PAD_SP			0x10
> +#define PAD_SN			0x14
> +
> +#define PHY_CMDPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x04)
> +#define PHY_DATAPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x06)
> +#define PHY_CLKPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x08)
> +#define PHY_STBPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0a)
> +#define PHY_RSTNPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0c)
> +#define RXSEL			0x0
> +#define WEAKPULL_EN		0x3
> +#define TXSLEW_CTRL_P		0x5
> +#define TXSLEW_CTRL_N		0x9
> +
> +#define PHY_PADTEST_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0e)
> +#define PHY_PADTEST_OUT_R	(DWC_MSHC_PTR_PHY_R + 0x10)
> +#define PHY_PADTEST_IN_R	(DWC_MSHC_PTR_PHY_R + 0x12)
> +#define PHY_PRBS_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x18)
> +#define PHY_PHYLBK_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1a)
> +#define PHY_COMMDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1c)
> +
> +#define PHY_SDCLKDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1d)
> +#define UPDATE_DC		0x4
> +
> +#define PHY_SDCLKDL_DC_R	(DWC_MSHC_PTR_PHY_R + 0x1e)
> +#define PHY_SMPLDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x20)
> +#define PHY_ATDL_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x21)
> +#define INPSEL_CNFG		2
> +
> +#define PHY_DLL_CTRL_R		(DWC_MSHC_PTR_PHY_R + 0x24)
> +#define DLL_EN			0x0
> +
> +#define PHY_DLL_CNFG1_R		(DWC_MSHC_PTR_PHY_R + 0x25)
> +#define PHY_DLL_CNFG2_R		(DWC_MSHC_PTR_PHY_R + 0x26)
> +#define PHY_DLLDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x28)
> +#define SLV_INPSEL		0x5
> +
> +#define P_VENDOR_SPECIFIC_AREA	0x500
> +#define EMMC_CTRL_R		(P_VENDOR_SPECIFIC_AREA + 0x2c)
> +#define AT_CTRL_R		(P_VENDOR_SPECIFIC_AREA + 0x40)
> +#define AT_EN			0x0
> +#define CI_SEL			0x1
> +#define SWIN_TH_EN		0x2
> +#define RPT_TUNE_ERR		0x3
> +#define SW_TUNE_EN		0x4
> +#define WIN_EDGE_SEL		0x8
> +#define TUNE_CLK_STOP_EN	0x10
> +#define PRE_CHANGE_DLY		0x11
> +#define POST_CHANGE_DLY		0x13
> +#define SWIN_TH_VAL		0x18
> +
> +#define DELAY_LINE_HS400	24
> +#define DELAY_LINE_DEFAULT	50
> +
>  #define BOUNDARY_OK(addr, len) \
>  	((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
>  
> @@ -91,6 +148,10 @@ struct dwcmshc_priv {
>  	struct clk	*bus_clk;
>  	int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */
>  	void *priv; /* pointer to SoC private stuff */
> +	uint32_t delay_line;
> +	bool non_removable;

can be replaced with mmc_host.caps & MMC_CAP_NONREMOVABLE

> +	bool pull_up_en;
> +	bool io_fixed_1v8;

replace them with flag?

>  };
>  
>  /*
> @@ -156,11 +217,171 @@ static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq)
>  	sdhci_request(mmc, mrq);
>  }
>  
> +static void sdhci_phy_1_8v_init_no_pull(struct sdhci_host *host)
> +{
> +	uint32_t val;
> +	sdhci_writel(host, 1, DWC_MSHC_PTR_PHY_R);
> +	sdhci_writeb(host, 1 << 4, PHY_SDCLKDL_CNFG_R);
> +	sdhci_writeb(host, 0x40, PHY_SDCLKDL_DC_R);

These magic numbers need a proper macro definitions.

> +
> +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> +	val &= ~(1 << 4);

ditto

> +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> +
> +
> +	val = sdhci_readw(host, PHY_CMDPAD_CNFG_R);
> +	sdhci_writew(host, val | 1, PHY_CMDPAD_CNFG_R);
> +
> +	val = sdhci_readw(host, PHY_DATAPAD_CNFG_R);
> +	sdhci_writew(host, val | 1, PHY_DATAPAD_CNFG_R);
> +
> +	val = sdhci_readw(host, PHY_RSTNPAD_CNFG_R);
> +	sdhci_writew(host, val | 1, PHY_RSTNPAD_CNFG_R);
> +
> +	val = sdhci_readw(host, PHY_STBPAD_CNFG_R);
> +	sdhci_writew(host, val | 1, PHY_STBPAD_CNFG_R);
> +
> +	val = sdhci_readb(host, PHY_DLL_CTRL_R);
> +	sdhci_writeb(host, val | 1, PHY_DLL_CTRL_R);
> +}
> +
> +static void sdhci_phy_3_3v_init_no_pull(struct sdhci_host *host)
> +{
> +	uint32_t val;
> +
> +	sdhci_writel(host, 1, DWC_MSHC_PTR_PHY_R);
> +	sdhci_writeb(host, 1 << 4, PHY_SDCLKDL_CNFG_R);
> +	sdhci_writeb(host, 0x40, PHY_SDCLKDL_DC_R);
> +
> +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> +	val &= ~(1 << 4);
> +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> +
> +	val = sdhci_readw(host, PHY_CMDPAD_CNFG_R);
> +	sdhci_writew(host, val | 2, PHY_CMDPAD_CNFG_R);
> +
> +	val = sdhci_readw(host, PHY_DATAPAD_CNFG_R);
> +	sdhci_writew(host, val | 2, PHY_DATAPAD_CNFG_R);
> +
> +	val = sdhci_readw(host, PHY_RSTNPAD_CNFG_R);
> +	sdhci_writew(host, val | 2, PHY_RSTNPAD_CNFG_R);
> +
> +	val = sdhci_readw(host, PHY_STBPAD_CNFG_R);
> +	sdhci_writew(host, val | 2, PHY_STBPAD_CNFG_R);
> +
> +	val = sdhci_readb(host, PHY_DLL_CTRL_R);
> +	sdhci_writeb(host, val | 1, PHY_DLL_CTRL_R);
> +}
> +
> +static void th1520_phy_1_8v_init(struct sdhci_host *host)
> +{
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> +	u32 val;
> +
> +	if (!priv)
> +		return;
> +
> +	if (priv->pull_up_en == 0) {
> +		sdhci_phy_1_8v_init_no_pull(host);
> +		return;
> +	}
> +
> +	/* set driving force */
> +	sdhci_writel(host, (1 << PHY_RSTN) | (0xc << PAD_SP) | (0xc << PAD_SN), PHY_CNFG_R);
> +
> +	/* disable delay lane */
> +	sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
> +
> +	/* set delay lane */
> +	sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R);
> +	sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R);
> +
> +	/* enable delay lane */
> +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> +	val &= ~(1 << UPDATE_DC);
> +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> +
> +	val = (1 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> +	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 = (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> +	sdhci_writew(host, val, PHY_CLKPAD_CNFG_R);
> +
> +	val = (1 << RXSEL) | (2 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> +	sdhci_writew(host, val, PHY_STBPAD_CNFG_R);
> +
> +	/* enable data strobe mode */
> +	sdhci_writeb(host, 3 << SLV_INPSEL, PHY_DLLDL_CNFG_R);
> +	sdhci_writeb(host, (1 << DLL_EN),  PHY_DLL_CTRL_R);
> +}
> +
> +static void th1520_phy_3_3v_init(struct sdhci_host *host)
> +{
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> +	u32 val;
> +
> +	if (priv->pull_up_en == 0) {
> +		sdhci_phy_3_3v_init_no_pull(host);
> +		return;
> +	}
> +
> +	/* set driving force */
> +	sdhci_writel(host, (1 << PHY_RSTN) | (0xc << PAD_SP) | (0xc << PAD_SN), PHY_CNFG_R);
> +
> +	/* disable delay lane */
> +	sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
> +
> +	/* set delay lane */
> +	sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R);
> +	sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R);
> +
> +	/* enable delay lane */
> +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> +	val &= ~(1 << UPDATE_DC);
> +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> +
> +	val = (2 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> +	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 = (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> +	sdhci_writew(host, val, PHY_CLKPAD_CNFG_R);
> +
> +	val = (2 << RXSEL) | (2 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> +	sdhci_writew(host, val, PHY_STBPAD_CNFG_R);
> +}
> +
> +
> +static void th1520_sdhci_set_phy(struct sdhci_host *host)
> +{
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> +	u8 emmc_ctl;
> +
> +	/* Before power on, set PHY configs */
> +	emmc_ctl = sdhci_readw(host, EMMC_CTRL_R);
> +	if (priv->non_removable) {
> +		th1520_phy_1_8v_init(host);
> +		emmc_ctl |= (1 << DWCMSHC_CARD_IS_EMMC);
> +	} else {
> +		th1520_phy_3_3v_init(host);
> +		emmc_ctl &=~(1 << DWCMSHC_CARD_IS_EMMC);
> +	}
> +	sdhci_writeb(host, emmc_ctl, EMMC_CTRL_R);
> +	sdhci_writeb(host, 0x25, PHY_DLL_CNFG1_R);

magic 0x25 needs a meaningful MACRO definition.

> +}
> +
>  static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
>  				      unsigned int timing)
>  {
>  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>  	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> +

we don't need this extra blank line

>  	u16 ctrl, ctrl_2;
>  
>  	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> @@ -188,7 +409,22 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
>  		ctrl_2 |= DWCMSHC_CTRL_HS400;
>  	}
>  
> +	if (priv->io_fixed_1v8)
> +		ctrl_2 |= SDHCI_CTRL_VDD_180;
> +
>  	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
> +
> +	/* TODO: add check so that this only runs on th1520  */

this TODO needs to be solved since it affects other platforms such as NV
and RK

> +	if (timing == MMC_TIMING_MMC_HS400) {
> +		/* disable auto tuning */
> +		u32 reg = sdhci_readl(host, AT_CTRL_R);
> +		reg &= ~1;
> +		sdhci_writel(host, reg, AT_CTRL_R);
> +		priv->delay_line = DELAY_LINE_HS400;
> +		th1520_sdhci_set_phy(host);
> +	} else {
> +		sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R);
> +	}
>  }
>  
>  static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc,
> @@ -337,6 +573,49 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
>  	sdhci_reset(host, mask);
>  }
>  
> +static int th1520_execute_tuning(struct sdhci_host *host, u32 opcode)
> +{
> +	u32 val = 0;
> +
> +	sdhci_writeb(host, 3 << INPSEL_CNFG, PHY_ATDL_CNFG_R);
> +
> +	val = sdhci_readl(host, AT_CTRL_R);
> +	val &= ~((1 << CI_SEL) | (1 << RPT_TUNE_ERR) \
> +	    | (1 << SW_TUNE_EN) |(0xf << WIN_EDGE_SEL));
> +	val |= (1 << AT_EN) | (1 << SWIN_TH_EN) | (1 << TUNE_CLK_STOP_EN)\
> +	    | (1 << PRE_CHANGE_DLY) | (3 << POST_CHANGE_DLY) | (9 << SWIN_TH_VAL);
> +
> +	sdhci_writel(host, val, AT_CTRL_R);
> +
> +	val = sdhci_readl(host, AT_CTRL_R);
> +	if(!(val & (1 << AT_EN))) {
> +		pr_warn("%s(): auto tuning is not enabled", __func__);

AFAIK, the controller supports both auto tuning and sw tuning.

> +		return -1;

can we replace -1 with meaningful error number?

> +	}
> +
> +	val &= ~(1 << AT_EN);
> +	sdhci_writel(host, val, AT_CTRL_R);
> +
> +	return 0;
> +}
> +
> +static void th1520_sdhci_reset(struct sdhci_host *host, u8 mask)
> +{
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> +	u16 ctrl_2;
> +
> +	sdhci_reset(host, mask);
> +
> +	if(priv->io_fixed_1v8){
> +		ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> +		if(! (ctrl_2 & SDHCI_CTRL_VDD_180)){
> +			ctrl_2 |= SDHCI_CTRL_VDD_180;
> +			sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
> +		}
> +	}
> +}
> +
>  static const struct sdhci_ops sdhci_dwcmshc_ops = {
>  	.set_clock		= sdhci_set_clock,
>  	.set_bus_width		= sdhci_set_bus_width,
> @@ -355,6 +634,17 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
>  	.adma_write_desc	= dwcmshc_adma_write_desc,
>  };
>  
> +static const struct sdhci_ops sdhci_dwcmshc_th1520_ops = {
> +	.set_clock		= sdhci_set_clock,
> +	.set_bus_width		= sdhci_set_bus_width,
> +	.set_uhs_signaling	= dwcmshc_set_uhs_signaling,
> +	.get_max_clock		= dwcmshc_get_max_clock,
> +	.reset			= th1520_sdhci_reset,
> +	.adma_write_desc	= dwcmshc_adma_write_desc,
> +	.voltage_switch		= th1520_phy_1_8v_init,
> +	.platform_execute_tuning = &th1520_execute_tuning,
> +};
> +
>  static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
>  	.ops = &sdhci_dwcmshc_ops,
>  	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
> @@ -378,6 +668,15 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
>  		   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
>  };
>  
> +static const struct sdhci_pltfm_data sdhci_dwcmshc_th1520_pdata = {
> +	.ops = &sdhci_dwcmshc_th1520_ops,
> +
> +	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
> +		  SDHCI_QUIRK_BROKEN_DMA |
> +		  SDHCI_QUIRK_BROKEN_ADMA,
> +	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
> +};
> +
>  static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
>  {
>  	int err;
> @@ -434,6 +733,10 @@ static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv
>  }
>  
>  static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
> +	{
> +		.compatible = "thead,th1520-dwcmshc",
> +		.data = &sdhci_dwcmshc_th1520_pdata,
> +	},
>  	{
>  		.compatible = "rockchip,rk3588-dwcmshc",
>  		.data = &sdhci_dwcmshc_rk35xx_pdata,
> @@ -541,6 +844,39 @@ static int dwcmshc_probe(struct platform_device *pdev)
>  			goto err_clk;
>  	}
>  
> +	if (pltfm_data == &sdhci_dwcmshc_th1520_pdata) {
> +
> +		priv->delay_line = DELAY_LINE_DEFAULT;
> +
> +		if (device_property_present(&pdev->dev, "non-removable"))
> +			priv->non_removable = 1;
> +		else
> +			priv->non_removable = 0;
> +
> +		if (device_property_present(&pdev->dev, "thead,pull-up"))
> +			priv->pull_up_en = 1;
> +		else
> +			priv->pull_up_en = 0;
> +
> +		if (device_property_present(&pdev->dev, "thead,io-fixed-1v8"))
> +			priv->io_fixed_1v8 = true;
> +		else
> +			priv->io_fixed_1v8 = false;
> +
> +		/*
> +		 * start_signal_voltage_switch() will try 3.3V first
> +		 * then 1.8V. Use SDHCI_SIGNALING_180 ranther than
> +		 * SDHCI_SIGNALING_330 to avoid setting voltage to 3.3V
> +		 * in sdhci_start_signal_voltage_switch().
> +		 */
> +		if(priv->io_fixed_1v8){
> +			host->flags &=~SDHCI_SIGNALING_330;
> +			host->flags |= SDHCI_SIGNALING_180;
> +		}
> +
> +		sdhci_enable_v4_mode(host);
> +	}
> +
>  #ifdef CONFIG_ACPI
>  	if (pltfm_data == &sdhci_dwcmshc_bf3_pdata)
>  		sdhci_enable_v4_mode(host);
> 
> -- 
> 2.34.1
> 

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

* Re: [PATCH RFC v2 1/4] dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support
  2023-08-05  3:14 ` [PATCH RFC v2 1/4] dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support Drew Fustini
@ 2023-08-07  6:29   ` Krzysztof Kozlowski
  2023-08-16 22:26     ` Drew Fustini
  0 siblings, 1 reply; 16+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-07  6:29 UTC (permalink / raw)
  To: Drew Fustini, Jisheng Zhang, Guo Ren, Fu Wei, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Conor Dooley, Adrian Hunter, Ulf Hansson
  Cc: linux-riscv, devicetree, linux-kernel, linux-mmc, Robert Nelson,
	Jason Kridner

On 05/08/2023 05:14, Drew Fustini wrote:
> Add compatible value for the T-Head TH1520 dwcmshc controller and
> thead,io-fixed-1v8 and thead,pull-up properties.
> 
> Signed-off-by: Drew Fustini <dfustini@baylibre.com>
> ---
>  Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
> index a43eb837f8da..57602c345cab 100644
> --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
> +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
> @@ -19,6 +19,7 @@ properties:
>        - rockchip,rk3568-dwcmshc
>        - rockchip,rk3588-dwcmshc
>        - snps,dwcmshc-sdhci
> +      - thead,th1520-dwcmshc
>  
>    reg:
>      maxItems: 1
> @@ -60,6 +61,14 @@ properties:
>      description: Specify the number of delay for tx sampling.
>      $ref: /schemas/types.yaml#/definitions/uint8
>  
> +  thead,io-fixed-1v8:
> +    description: SoC PHY pad is fixed 1.8V
> +    type: boolean

Isn't this duplicating existing properties for MMC modes with 1.8 V?

> +
> +  thead,pull-up:
> +    description: True if pull-up, false if pull-down

This explains me nothing. No clue what you are pulling and why do you
need it. Pin pulls should be done via pin controller, not MMC.

Anyway you should have here allOf:if:then (move the allOf: from top to
behind "required:") which will disallow these properties for other variants.

> +    type: boolean
> +
>  
>  required:
>    - compatible
> 

Best regards,
Krzysztof


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

* Re: [PATCH RFC v2 4/4] mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520
  2023-08-06 10:09   ` Jisheng Zhang
@ 2023-08-16 21:17     ` Drew Fustini
  2023-08-17 23:32       ` Guo Ren
  0 siblings, 1 reply; 16+ messages in thread
From: Drew Fustini @ 2023-08-16 21:17 UTC (permalink / raw)
  To: Jisheng Zhang
  Cc: Guo Ren, Fu Wei, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Paul Walmsley, Palmer Dabbelt, Albert Ou, Conor Dooley,
	Adrian Hunter, Ulf Hansson, linux-riscv, devicetree,
	linux-kernel, linux-mmc, Robert Nelson, Jason Kridner

On Sun, Aug 06, 2023 at 06:09:39PM +0800, Jisheng Zhang wrote:
> On Fri, Aug 04, 2023 at 08:14:48PM -0700, Drew Fustini wrote:
> > Add basic support for the T-Head TH1520 SoC mmc controller with the new
> > compatible "thead,th1520-dwcmshc".
> > 
> > However, quirks are currently set to disable DMA and use PIO. The proper
> > settings for DMA support still need to be determined.
> 
> Hi Drew,
> 
> Thank you for this patch. I think we need to make DMA work even in the
> first version.

Thanks for your review. I agree that DMA should be made to work.
When I remove the SDHCI_QUIRK_BROKEN_ADMA quirk, I see the following in
the boot log [1]:

[    3.633611] mmc0: SDHCI controller on ffe7080000.mmc [ffe7080000.mmc] using ADMA 64-bit
[    3.723080] mmc0: ADMA error: 0x02000000
[    4.327491] mmc0: error -5 whilst initialising MMC card

I'm going to add some more debug output so I can better understand what
exactly is failing.

> 
> Several comments below.
> 
> > 
> > Another issue is th1520-specific code for MMC_TIMING_MMC_HS400 in
> > dwcmshc_set_uhs_signaling() will run on all platforms which is not
> > correct. One solution could be to add a th1520 flag to dwcmshc_priv but
> > that is hacky. Another solution could be to set the set_uhs_signaling op
> > in sdhci_dwcmshc_th1520_ops to a th1520-specific function. However, that
> > new function would have to duplicate all the code in the current
> > dwcmshc_set_uhs_signaling().
> > 
> > Signed-off-by: Drew Fustini <dfustini@baylibre.com>
> > ---
> >  drivers/mmc/host/sdhci-of-dwcmshc.c | 336 ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 336 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
> > index e68cd87998c8..d35e204cdb16 100644
> > --- a/drivers/mmc/host/sdhci-of-dwcmshc.c
> > +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
> > @@ -71,6 +71,63 @@
> >  	(((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
> >  #define RK35xx_MAX_CLKS 3
> >  
> > +/* T-Head specific registers */
> 
> I guess this may not be T-HEAD specific but dwc phy, could you please
> check?

Yes, I will try to find out if if this really is t-head specific or just
standard for the DWC PHY.

> > +#define DWC_MSHC_PTR_PHY_R	0x300
> > +#define PHY_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x00)
> > +#define PHY_RSTN		0x0
> > +#define PAD_SP			0x10
> > +#define PAD_SN			0x14
> > +
> > +#define PHY_CMDPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x04)
> > +#define PHY_DATAPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x06)
> > +#define PHY_CLKPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x08)
> > +#define PHY_STBPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0a)
> > +#define PHY_RSTNPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0c)
> > +#define RXSEL			0x0
> > +#define WEAKPULL_EN		0x3
> > +#define TXSLEW_CTRL_P		0x5
> > +#define TXSLEW_CTRL_N		0x9
> > +
> > +#define PHY_PADTEST_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0e)
> > +#define PHY_PADTEST_OUT_R	(DWC_MSHC_PTR_PHY_R + 0x10)
> > +#define PHY_PADTEST_IN_R	(DWC_MSHC_PTR_PHY_R + 0x12)
> > +#define PHY_PRBS_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x18)
> > +#define PHY_PHYLBK_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1a)
> > +#define PHY_COMMDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1c)
> > +
> > +#define PHY_SDCLKDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1d)
> > +#define UPDATE_DC		0x4
> > +
> > +#define PHY_SDCLKDL_DC_R	(DWC_MSHC_PTR_PHY_R + 0x1e)
> > +#define PHY_SMPLDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x20)
> > +#define PHY_ATDL_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x21)
> > +#define INPSEL_CNFG		2
> > +
> > +#define PHY_DLL_CTRL_R		(DWC_MSHC_PTR_PHY_R + 0x24)
> > +#define DLL_EN			0x0
> > +
> > +#define PHY_DLL_CNFG1_R		(DWC_MSHC_PTR_PHY_R + 0x25)
> > +#define PHY_DLL_CNFG2_R		(DWC_MSHC_PTR_PHY_R + 0x26)
> > +#define PHY_DLLDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x28)
> > +#define SLV_INPSEL		0x5
> > +
> > +#define P_VENDOR_SPECIFIC_AREA	0x500
> > +#define EMMC_CTRL_R		(P_VENDOR_SPECIFIC_AREA + 0x2c)
> > +#define AT_CTRL_R		(P_VENDOR_SPECIFIC_AREA + 0x40)
> > +#define AT_EN			0x0
> > +#define CI_SEL			0x1
> > +#define SWIN_TH_EN		0x2
> > +#define RPT_TUNE_ERR		0x3
> > +#define SW_TUNE_EN		0x4
> > +#define WIN_EDGE_SEL		0x8
> > +#define TUNE_CLK_STOP_EN	0x10
> > +#define PRE_CHANGE_DLY		0x11
> > +#define POST_CHANGE_DLY		0x13
> > +#define SWIN_TH_VAL		0x18
> > +
> > +#define DELAY_LINE_HS400	24
> > +#define DELAY_LINE_DEFAULT	50
> > +
> >  #define BOUNDARY_OK(addr, len) \
> >  	((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
> >  
> > @@ -91,6 +148,10 @@ struct dwcmshc_priv {
> >  	struct clk	*bus_clk;
> >  	int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */
> >  	void *priv; /* pointer to SoC private stuff */
> > +	uint32_t delay_line;
> > +	bool non_removable;
> 
> can be replaced with mmc_host.caps & MMC_CAP_NONREMOVABLE

Thank you, I'll change in the next version.

> 
> > +	bool pull_up_en;
> > +	bool io_fixed_1v8;
> 
> replace them with flag?

Do you mean that I should replace the above bool's with a single flags
field in the struct where the bool's would become bit fields in flags?

> 
> >  };
> >  
> >  /*
> > @@ -156,11 +217,171 @@ static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> >  	sdhci_request(mmc, mrq);
> >  }
> >  
> > +static void sdhci_phy_1_8v_init_no_pull(struct sdhci_host *host)
> > +{
> > +	uint32_t val;
> > +	sdhci_writel(host, 1, DWC_MSHC_PTR_PHY_R);
> > +	sdhci_writeb(host, 1 << 4, PHY_SDCLKDL_CNFG_R);
> > +	sdhci_writeb(host, 0x40, PHY_SDCLKDL_DC_R);
> 
> These magic numbers need a proper macro definitions.

I'll try to find out their meaning and document it.

> 
> > +
> > +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> > +	val &= ~(1 << 4);
> 
> ditto
> 
> > +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> > +
> > +
> > +	val = sdhci_readw(host, PHY_CMDPAD_CNFG_R);
> > +	sdhci_writew(host, val | 1, PHY_CMDPAD_CNFG_R);
> > +
> > +	val = sdhci_readw(host, PHY_DATAPAD_CNFG_R);
> > +	sdhci_writew(host, val | 1, PHY_DATAPAD_CNFG_R);
> > +
> > +	val = sdhci_readw(host, PHY_RSTNPAD_CNFG_R);
> > +	sdhci_writew(host, val | 1, PHY_RSTNPAD_CNFG_R);
> > +
> > +	val = sdhci_readw(host, PHY_STBPAD_CNFG_R);
> > +	sdhci_writew(host, val | 1, PHY_STBPAD_CNFG_R);
> > +
> > +	val = sdhci_readb(host, PHY_DLL_CTRL_R);
> > +	sdhci_writeb(host, val | 1, PHY_DLL_CTRL_R);
> > +}
> > +
> > +static void sdhci_phy_3_3v_init_no_pull(struct sdhci_host *host)
> > +{
> > +	uint32_t val;
> > +
> > +	sdhci_writel(host, 1, DWC_MSHC_PTR_PHY_R);
> > +	sdhci_writeb(host, 1 << 4, PHY_SDCLKDL_CNFG_R);
> > +	sdhci_writeb(host, 0x40, PHY_SDCLKDL_DC_R);
> > +
> > +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> > +	val &= ~(1 << 4);
> > +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> > +
> > +	val = sdhci_readw(host, PHY_CMDPAD_CNFG_R);
> > +	sdhci_writew(host, val | 2, PHY_CMDPAD_CNFG_R);
> > +
> > +	val = sdhci_readw(host, PHY_DATAPAD_CNFG_R);
> > +	sdhci_writew(host, val | 2, PHY_DATAPAD_CNFG_R);
> > +
> > +	val = sdhci_readw(host, PHY_RSTNPAD_CNFG_R);
> > +	sdhci_writew(host, val | 2, PHY_RSTNPAD_CNFG_R);
> > +
> > +	val = sdhci_readw(host, PHY_STBPAD_CNFG_R);
> > +	sdhci_writew(host, val | 2, PHY_STBPAD_CNFG_R);
> > +
> > +	val = sdhci_readb(host, PHY_DLL_CTRL_R);
> > +	sdhci_writeb(host, val | 1, PHY_DLL_CTRL_R);
> > +}
> > +
> > +static void th1520_phy_1_8v_init(struct sdhci_host *host)
> > +{
> > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> > +	u32 val;
> > +
> > +	if (!priv)
> > +		return;
> > +
> > +	if (priv->pull_up_en == 0) {
> > +		sdhci_phy_1_8v_init_no_pull(host);
> > +		return;
> > +	}
> > +
> > +	/* set driving force */
> > +	sdhci_writel(host, (1 << PHY_RSTN) | (0xc << PAD_SP) | (0xc << PAD_SN), PHY_CNFG_R);
> > +
> > +	/* disable delay lane */
> > +	sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
> > +
> > +	/* set delay lane */
> > +	sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R);
> > +	sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R);
> > +
> > +	/* enable delay lane */
> > +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> > +	val &= ~(1 << UPDATE_DC);
> > +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> > +
> > +	val = (1 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > +	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 = (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > +	sdhci_writew(host, val, PHY_CLKPAD_CNFG_R);
> > +
> > +	val = (1 << RXSEL) | (2 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > +	sdhci_writew(host, val, PHY_STBPAD_CNFG_R);
> > +
> > +	/* enable data strobe mode */
> > +	sdhci_writeb(host, 3 << SLV_INPSEL, PHY_DLLDL_CNFG_R);
> > +	sdhci_writeb(host, (1 << DLL_EN),  PHY_DLL_CTRL_R);
> > +}
> > +
> > +static void th1520_phy_3_3v_init(struct sdhci_host *host)
> > +{
> > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> > +	u32 val;
> > +
> > +	if (priv->pull_up_en == 0) {
> > +		sdhci_phy_3_3v_init_no_pull(host);
> > +		return;
> > +	}
> > +
> > +	/* set driving force */
> > +	sdhci_writel(host, (1 << PHY_RSTN) | (0xc << PAD_SP) | (0xc << PAD_SN), PHY_CNFG_R);
> > +
> > +	/* disable delay lane */
> > +	sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
> > +
> > +	/* set delay lane */
> > +	sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R);
> > +	sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R);
> > +
> > +	/* enable delay lane */
> > +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> > +	val &= ~(1 << UPDATE_DC);
> > +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> > +
> > +	val = (2 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > +	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 = (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > +	sdhci_writew(host, val, PHY_CLKPAD_CNFG_R);
> > +
> > +	val = (2 << RXSEL) | (2 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > +	sdhci_writew(host, val, PHY_STBPAD_CNFG_R);
> > +}
> > +
> > +
> > +static void th1520_sdhci_set_phy(struct sdhci_host *host)
> > +{
> > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> > +	u8 emmc_ctl;
> > +
> > +	/* Before power on, set PHY configs */
> > +	emmc_ctl = sdhci_readw(host, EMMC_CTRL_R);
> > +	if (priv->non_removable) {
> > +		th1520_phy_1_8v_init(host);
> > +		emmc_ctl |= (1 << DWCMSHC_CARD_IS_EMMC);
> > +	} else {
> > +		th1520_phy_3_3v_init(host);
> > +		emmc_ctl &=~(1 << DWCMSHC_CARD_IS_EMMC);
> > +	}
> > +	sdhci_writeb(host, emmc_ctl, EMMC_CTRL_R);
> > +	sdhci_writeb(host, 0x25, PHY_DLL_CNFG1_R);
> 
> magic 0x25 needs a meaningful MACRO definition.

Okay, I'll investigate the meaning of that value and define it.

> 
> > +}
> > +
> >  static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
> >  				      unsigned int timing)
> >  {
> >  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> >  	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> > +
> 
> we don't need this extra blank line

Okay

> 
> >  	u16 ctrl, ctrl_2;
> >  
> >  	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> > @@ -188,7 +409,22 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
> >  		ctrl_2 |= DWCMSHC_CTRL_HS400;
> >  	}
> >  
> > +	if (priv->io_fixed_1v8)
> > +		ctrl_2 |= SDHCI_CTRL_VDD_180;
> > +
> >  	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
> > +
> > +	/* TODO: add check so that this only runs on th1520  */
> 
> this TODO needs to be solved since it affects other platforms such as NV
> and RK

Yes, I need to fix this. For the next version, I am considering adding
a flag to dwcmshc_priv that would gate the following code block.


> > +	if (timing == MMC_TIMING_MMC_HS400) {
> > +		/* disable auto tuning */
> > +		u32 reg = sdhci_readl(host, AT_CTRL_R);
> > +		reg &= ~1;
> > +		sdhci_writel(host, reg, AT_CTRL_R);
> > +		priv->delay_line = DELAY_LINE_HS400;
> > +		th1520_sdhci_set_phy(host);
> > +	} else {
> > +		sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R);
> > +	}
> >  }
> >  
> >  static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc,
> > @@ -337,6 +573,49 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
> >  	sdhci_reset(host, mask);
> >  }
> >  
> > +static int th1520_execute_tuning(struct sdhci_host *host, u32 opcode)
> > +{
> > +	u32 val = 0;
> > +
> > +	sdhci_writeb(host, 3 << INPSEL_CNFG, PHY_ATDL_CNFG_R);
> > +
> > +	val = sdhci_readl(host, AT_CTRL_R);
> > +	val &= ~((1 << CI_SEL) | (1 << RPT_TUNE_ERR) \
> > +	    | (1 << SW_TUNE_EN) |(0xf << WIN_EDGE_SEL));
> > +	val |= (1 << AT_EN) | (1 << SWIN_TH_EN) | (1 << TUNE_CLK_STOP_EN)\
> > +	    | (1 << PRE_CHANGE_DLY) | (3 << POST_CHANGE_DLY) | (9 << SWIN_TH_VAL);
> > +
> > +	sdhci_writel(host, val, AT_CTRL_R);
> > +
> > +	val = sdhci_readl(host, AT_CTRL_R);
> > +	if(!(val & (1 << AT_EN))) {
> > +		pr_warn("%s(): auto tuning is not enabled", __func__);
> 
> AFAIK, the controller supports both auto tuning and sw tuning.

Okay, I'll have to investigate further why it is like this in the vendor
kernel [2].

> 
> > +		return -1;
> 
> can we replace -1 with meaningful error number?
> 

Yes, will do for next version.

> > +	}
> > +
> > +	val &= ~(1 << AT_EN);
> > +	sdhci_writel(host, val, AT_CTRL_R);
> > +
> > +	return 0;
> > +}
> > +
> > +static void th1520_sdhci_reset(struct sdhci_host *host, u8 mask)
> > +{
> > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> > +	u16 ctrl_2;
> > +
> > +	sdhci_reset(host, mask);
> > +
> > +	if(priv->io_fixed_1v8){
> > +		ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> > +		if(! (ctrl_2 & SDHCI_CTRL_VDD_180)){
> > +			ctrl_2 |= SDHCI_CTRL_VDD_180;
> > +			sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
> > +		}
> > +	}
> > +}
> > +
> >  static const struct sdhci_ops sdhci_dwcmshc_ops = {
> >  	.set_clock		= sdhci_set_clock,
> >  	.set_bus_width		= sdhci_set_bus_width,
> > @@ -355,6 +634,17 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
> >  	.adma_write_desc	= dwcmshc_adma_write_desc,
> >  };
> >  
> > +static const struct sdhci_ops sdhci_dwcmshc_th1520_ops = {
> > +	.set_clock		= sdhci_set_clock,
> > +	.set_bus_width		= sdhci_set_bus_width,
> > +	.set_uhs_signaling	= dwcmshc_set_uhs_signaling,
> > +	.get_max_clock		= dwcmshc_get_max_clock,
> > +	.reset			= th1520_sdhci_reset,
> > +	.adma_write_desc	= dwcmshc_adma_write_desc,
> > +	.voltage_switch		= th1520_phy_1_8v_init,
> > +	.platform_execute_tuning = &th1520_execute_tuning,
> > +};
> > +
> >  static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
> >  	.ops = &sdhci_dwcmshc_ops,
> >  	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
> > @@ -378,6 +668,15 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
> >  		   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
> >  };
> >  
> > +static const struct sdhci_pltfm_data sdhci_dwcmshc_th1520_pdata = {
> > +	.ops = &sdhci_dwcmshc_th1520_ops,
> > +
> > +	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
> > +		  SDHCI_QUIRK_BROKEN_DMA |
> > +		  SDHCI_QUIRK_BROKEN_ADMA,
> > +	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
> > +};
> > +
> >  static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
> >  {
> >  	int err;
> > @@ -434,6 +733,10 @@ static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv
> >  }
> >  
> >  static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
> > +	{
> > +		.compatible = "thead,th1520-dwcmshc",
> > +		.data = &sdhci_dwcmshc_th1520_pdata,
> > +	},
> >  	{
> >  		.compatible = "rockchip,rk3588-dwcmshc",
> >  		.data = &sdhci_dwcmshc_rk35xx_pdata,
> > @@ -541,6 +844,39 @@ static int dwcmshc_probe(struct platform_device *pdev)
> >  			goto err_clk;
> >  	}
> >  
> > +	if (pltfm_data == &sdhci_dwcmshc_th1520_pdata) {
> > +
> > +		priv->delay_line = DELAY_LINE_DEFAULT;
> > +
> > +		if (device_property_present(&pdev->dev, "non-removable"))
> > +			priv->non_removable = 1;
> > +		else
> > +			priv->non_removable = 0;
> > +
> > +		if (device_property_present(&pdev->dev, "thead,pull-up"))
> > +			priv->pull_up_en = 1;
> > +		else
> > +			priv->pull_up_en = 0;
> > +
> > +		if (device_property_present(&pdev->dev, "thead,io-fixed-1v8"))
> > +			priv->io_fixed_1v8 = true;
> > +		else
> > +			priv->io_fixed_1v8 = false;
> > +
> > +		/*
> > +		 * start_signal_voltage_switch() will try 3.3V first
> > +		 * then 1.8V. Use SDHCI_SIGNALING_180 ranther than
> > +		 * SDHCI_SIGNALING_330 to avoid setting voltage to 3.3V
> > +		 * in sdhci_start_signal_voltage_switch().
> > +		 */
> > +		if(priv->io_fixed_1v8){
> > +			host->flags &=~SDHCI_SIGNALING_330;
> > +			host->flags |= SDHCI_SIGNALING_180;
> > +		}
> > +
> > +		sdhci_enable_v4_mode(host);
> > +	}
> > +
> >  #ifdef CONFIG_ACPI
> >  	if (pltfm_data == &sdhci_dwcmshc_bf3_pdata)
> >  		sdhci_enable_v4_mode(host);
> > 
> > -- 
> > 2.34.1
> > 

Thank you,
Drew

[1] https://gist.github.com/pdp7/a8301b895c2dc293f2e0210e77e45e01
[2] https://git.beagleboard.org/beaglev-ahead/beaglev-ahead-linux/-/blob/beaglev-v5.10.113-1.1.2/drivers/mmc/host/sdhci-of-dwcmshc.c#L238

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

* Re: [PATCH RFC v2 1/4] dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support
  2023-08-07  6:29   ` Krzysztof Kozlowski
@ 2023-08-16 22:26     ` Drew Fustini
  2023-08-19 13:06       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 16+ messages in thread
From: Drew Fustini @ 2023-08-16 22:26 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Jisheng Zhang, Guo Ren, Fu Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Conor Dooley, Adrian Hunter, Ulf Hansson, linux-riscv,
	devicetree, linux-kernel, linux-mmc, Robert Nelson,
	Jason Kridner

On Mon, Aug 07, 2023 at 08:29:21AM +0200, Krzysztof Kozlowski wrote:
> On 05/08/2023 05:14, Drew Fustini wrote:
> > Add compatible value for the T-Head TH1520 dwcmshc controller and
> > thead,io-fixed-1v8 and thead,pull-up properties.
> > 
> > Signed-off-by: Drew Fustini <dfustini@baylibre.com>
> > ---
> >  Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 9 +++++++++
> >  1 file changed, 9 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
> > index a43eb837f8da..57602c345cab 100644
> > --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
> > +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
> > @@ -19,6 +19,7 @@ properties:
> >        - rockchip,rk3568-dwcmshc
> >        - rockchip,rk3588-dwcmshc
> >        - snps,dwcmshc-sdhci
> > +      - thead,th1520-dwcmshc
> >  
> >    reg:
> >      maxItems: 1
> > @@ -60,6 +61,14 @@ properties:
> >      description: Specify the number of delay for tx sampling.
> >      $ref: /schemas/types.yaml#/definitions/uint8
> >  
> > +  thead,io-fixed-1v8:
> > +    description: SoC PHY pad is fixed 1.8V
> > +    type: boolean
> 
> Isn't this duplicating existing properties for MMC modes with 1.8 V?

Thank you for reviewing. Yes, now that you mention it, I do see those
properties now in mmc-controller.yaml. It seems like the existing
mmc-ddr-1_8v property would be appropriate.

> 
> > +
> > +  thead,pull-up:
> > +    description: True if pull-up, false if pull-down
> 
> This explains me nothing. No clue what you are pulling and why do you
> need it. Pin pulls should be done via pin controller, not MMC.

Good point that my description is not helpful. The pull-up property
determines whether certain phy registers are written to. I need to try
to can get documentation on the phy so that I can better understand the
details of the pull-up configuration in the phy registers.

> 
> Anyway you should have here allOf:if:then (move the allOf: from top to
> behind "required:") which will disallow these properties for other variants.

I noticed that nvidia,tegra20-sdhci.yaml has several lines related to
pull-up/down configuration:

218   - if:
219       properties:
220         compatible:
221           contains:
222             const: nvidia,tegra210-sdhci
223     then:
224       properties:
225         pinctrl-names:
226           oneOf:
227             - items:
228                 - const: sdmmc-3v3
229                   description: pad configuration for 3.3 V
230                 - const: sdmmc-1v8
231                   description: pad configuration for 1.8 V
232                 - const: sdmmc-3v3-drv
233                   description: pull-up/down configuration for 3.3 V
234                 - const: sdmmc-1v8-drv
235                   description: pull-up/down configuration for 1.8 V
236             - items:
237                 - const: sdmmc-3v3-drv
238                   description: pull-up/down configuration for 3.3 V
239                 - const: sdmmc-1v8-drv
240                   description: pull-up/down configuration for 1.8 V
241             - items:
242                 - const: sdmmc-1v8-drv
243                   description: pull-up/down configuration for 1.8 V

Do you think creating something like that would be a good approach?

Thank you,
Drew

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

* Re: [PATCH RFC v2 4/4] mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520
  2023-08-16 21:17     ` Drew Fustini
@ 2023-08-17 23:32       ` Guo Ren
  0 siblings, 0 replies; 16+ messages in thread
From: Guo Ren @ 2023-08-17 23:32 UTC (permalink / raw)
  To: Drew Fustini
  Cc: Jisheng Zhang, Fu Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Conor Dooley, Adrian Hunter, Ulf Hansson, linux-riscv,
	devicetree, linux-kernel, linux-mmc, Robert Nelson,
	Jason Kridner

On Wed, Aug 16, 2023 at 02:17:16PM -0700, Drew Fustini wrote:
> On Sun, Aug 06, 2023 at 06:09:39PM +0800, Jisheng Zhang wrote:
> > On Fri, Aug 04, 2023 at 08:14:48PM -0700, Drew Fustini wrote:
> > > Add basic support for the T-Head TH1520 SoC mmc controller with the new
> > > compatible "thead,th1520-dwcmshc".
> > > 
> > > However, quirks are currently set to disable DMA and use PIO. The proper
> > > settings for DMA support still need to be determined.
> > 
> > Hi Drew,
> > 
> > Thank you for this patch. I think we need to make DMA work even in the
> > first version.
> 
> Thanks for your review. I agree that DMA should be made to work.
> When I remove the SDHCI_QUIRK_BROKEN_ADMA quirk, I see the following in
> the boot log [1]:
> 
> [    3.633611] mmc0: SDHCI controller on ffe7080000.mmc [ffe7080000.mmc] using ADMA 64-bit
> [    3.723080] mmc0: ADMA error: 0x02000000
> [    4.327491] mmc0: error -5 whilst initialising MMC card
> 
> I'm going to add some more debug output so I can better understand what
> exactly is failing.
> 
> > 
> > Several comments below.
> > 
> > > 
> > > Another issue is th1520-specific code for MMC_TIMING_MMC_HS400 in
> > > dwcmshc_set_uhs_signaling() will run on all platforms which is not
> > > correct. One solution could be to add a th1520 flag to dwcmshc_priv but
> > > that is hacky. Another solution could be to set the set_uhs_signaling op
> > > in sdhci_dwcmshc_th1520_ops to a th1520-specific function. However, that
> > > new function would have to duplicate all the code in the current
> > > dwcmshc_set_uhs_signaling().
> > > 
> > > Signed-off-by: Drew Fustini <dfustini@baylibre.com>
> > > ---
> > >  drivers/mmc/host/sdhci-of-dwcmshc.c | 336 ++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 336 insertions(+)
> > > 
> > > diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
> > > index e68cd87998c8..d35e204cdb16 100644
> > > --- a/drivers/mmc/host/sdhci-of-dwcmshc.c
> > > +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
> > > @@ -71,6 +71,63 @@
> > >  	(((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
> > >  #define RK35xx_MAX_CLKS 3
> > >  
> > > +/* T-Head specific registers */
> > 
> > I guess this may not be T-HEAD specific but dwc phy, could you please
> > check?
It's not a standard DesginWare MMC PHY registers, and we modiified
something. We could keep this code in custom first to make it work around
and see how to merge it into standard DesginWare MMC PHY registers next.

> 
> Yes, I will try to find out if if this really is t-head specific or just
> standard for the DWC PHY.
> 
> > > +#define DWC_MSHC_PTR_PHY_R	0x300
> > > +#define PHY_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x00)
> > > +#define PHY_RSTN		0x0
> > > +#define PAD_SP			0x10
> > > +#define PAD_SN			0x14
> > > +
> > > +#define PHY_CMDPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x04)
> > > +#define PHY_DATAPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x06)
> > > +#define PHY_CLKPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x08)
> > > +#define PHY_STBPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0a)
> > > +#define PHY_RSTNPAD_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0c)
> > > +#define RXSEL			0x0
> > > +#define WEAKPULL_EN		0x3
> > > +#define TXSLEW_CTRL_P		0x5
> > > +#define TXSLEW_CTRL_N		0x9
> > > +
> > > +#define PHY_PADTEST_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x0e)
> > > +#define PHY_PADTEST_OUT_R	(DWC_MSHC_PTR_PHY_R + 0x10)
> > > +#define PHY_PADTEST_IN_R	(DWC_MSHC_PTR_PHY_R + 0x12)
> > > +#define PHY_PRBS_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x18)
> > > +#define PHY_PHYLBK_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1a)
> > > +#define PHY_COMMDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1c)
> > > +
> > > +#define PHY_SDCLKDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x1d)
> > > +#define UPDATE_DC		0x4
> > > +
> > > +#define PHY_SDCLKDL_DC_R	(DWC_MSHC_PTR_PHY_R + 0x1e)
> > > +#define PHY_SMPLDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x20)
> > > +#define PHY_ATDL_CNFG_R		(DWC_MSHC_PTR_PHY_R + 0x21)
> > > +#define INPSEL_CNFG		2
> > > +
> > > +#define PHY_DLL_CTRL_R		(DWC_MSHC_PTR_PHY_R + 0x24)
> > > +#define DLL_EN			0x0
> > > +
> > > +#define PHY_DLL_CNFG1_R		(DWC_MSHC_PTR_PHY_R + 0x25)
> > > +#define PHY_DLL_CNFG2_R		(DWC_MSHC_PTR_PHY_R + 0x26)
> > > +#define PHY_DLLDL_CNFG_R	(DWC_MSHC_PTR_PHY_R + 0x28)
> > > +#define SLV_INPSEL		0x5
> > > +
> > > +#define P_VENDOR_SPECIFIC_AREA	0x500
> > > +#define EMMC_CTRL_R		(P_VENDOR_SPECIFIC_AREA + 0x2c)
> > > +#define AT_CTRL_R		(P_VENDOR_SPECIFIC_AREA + 0x40)
> > > +#define AT_EN			0x0
> > > +#define CI_SEL			0x1
> > > +#define SWIN_TH_EN		0x2
> > > +#define RPT_TUNE_ERR		0x3
> > > +#define SW_TUNE_EN		0x4
> > > +#define WIN_EDGE_SEL		0x8
> > > +#define TUNE_CLK_STOP_EN	0x10
> > > +#define PRE_CHANGE_DLY		0x11
> > > +#define POST_CHANGE_DLY		0x13
> > > +#define SWIN_TH_VAL		0x18
> > > +
> > > +#define DELAY_LINE_HS400	24
> > > +#define DELAY_LINE_DEFAULT	50
> > > +
> > >  #define BOUNDARY_OK(addr, len) \
> > >  	((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
> > >  
> > > @@ -91,6 +148,10 @@ struct dwcmshc_priv {
> > >  	struct clk	*bus_clk;
> > >  	int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */
> > >  	void *priv; /* pointer to SoC private stuff */
> > > +	uint32_t delay_line;
> > > +	bool non_removable;
> > 
> > can be replaced with mmc_host.caps & MMC_CAP_NONREMOVABLE
> 
> Thank you, I'll change in the next version.
> 
> > 
> > > +	bool pull_up_en;
> > > +	bool io_fixed_1v8;
> > 
> > replace them with flag?
> 
> Do you mean that I should replace the above bool's with a single flags
> field in the struct where the bool's would become bit fields in flags?
> 
> > 
> > >  };
> > >  
> > >  /*
> > > @@ -156,11 +217,171 @@ static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> > >  	sdhci_request(mmc, mrq);
> > >  }
> > >  
> > > +static void sdhci_phy_1_8v_init_no_pull(struct sdhci_host *host)
> > > +{
> > > +	uint32_t val;
> > > +	sdhci_writel(host, 1, DWC_MSHC_PTR_PHY_R);
> > > +	sdhci_writeb(host, 1 << 4, PHY_SDCLKDL_CNFG_R);
> > > +	sdhci_writeb(host, 0x40, PHY_SDCLKDL_DC_R);
> > 
> > These magic numbers need a proper macro definitions.
> 
> I'll try to find out their meaning and document it.
> 
> > 
> > > +
> > > +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> > > +	val &= ~(1 << 4);
> > 
> > ditto
> > 
> > > +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> > > +
> > > +
> > > +	val = sdhci_readw(host, PHY_CMDPAD_CNFG_R);
> > > +	sdhci_writew(host, val | 1, PHY_CMDPAD_CNFG_R);
> > > +
> > > +	val = sdhci_readw(host, PHY_DATAPAD_CNFG_R);
> > > +	sdhci_writew(host, val | 1, PHY_DATAPAD_CNFG_R);
> > > +
> > > +	val = sdhci_readw(host, PHY_RSTNPAD_CNFG_R);
> > > +	sdhci_writew(host, val | 1, PHY_RSTNPAD_CNFG_R);
> > > +
> > > +	val = sdhci_readw(host, PHY_STBPAD_CNFG_R);
> > > +	sdhci_writew(host, val | 1, PHY_STBPAD_CNFG_R);
> > > +
> > > +	val = sdhci_readb(host, PHY_DLL_CTRL_R);
> > > +	sdhci_writeb(host, val | 1, PHY_DLL_CTRL_R);
> > > +}
> > > +
> > > +static void sdhci_phy_3_3v_init_no_pull(struct sdhci_host *host)
> > > +{
> > > +	uint32_t val;
> > > +
> > > +	sdhci_writel(host, 1, DWC_MSHC_PTR_PHY_R);
> > > +	sdhci_writeb(host, 1 << 4, PHY_SDCLKDL_CNFG_R);
> > > +	sdhci_writeb(host, 0x40, PHY_SDCLKDL_DC_R);
> > > +
> > > +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> > > +	val &= ~(1 << 4);
> > > +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> > > +
> > > +	val = sdhci_readw(host, PHY_CMDPAD_CNFG_R);
> > > +	sdhci_writew(host, val | 2, PHY_CMDPAD_CNFG_R);
> > > +
> > > +	val = sdhci_readw(host, PHY_DATAPAD_CNFG_R);
> > > +	sdhci_writew(host, val | 2, PHY_DATAPAD_CNFG_R);
> > > +
> > > +	val = sdhci_readw(host, PHY_RSTNPAD_CNFG_R);
> > > +	sdhci_writew(host, val | 2, PHY_RSTNPAD_CNFG_R);
> > > +
> > > +	val = sdhci_readw(host, PHY_STBPAD_CNFG_R);
> > > +	sdhci_writew(host, val | 2, PHY_STBPAD_CNFG_R);
> > > +
> > > +	val = sdhci_readb(host, PHY_DLL_CTRL_R);
> > > +	sdhci_writeb(host, val | 1, PHY_DLL_CTRL_R);
> > > +}
> > > +
> > > +static void th1520_phy_1_8v_init(struct sdhci_host *host)
> > > +{
> > > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > > +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> > > +	u32 val;
> > > +
> > > +	if (!priv)
> > > +		return;
> > > +
> > > +	if (priv->pull_up_en == 0) {
> > > +		sdhci_phy_1_8v_init_no_pull(host);
> > > +		return;
> > > +	}
> > > +
> > > +	/* set driving force */
> > > +	sdhci_writel(host, (1 << PHY_RSTN) | (0xc << PAD_SP) | (0xc << PAD_SN), PHY_CNFG_R);
> > > +
> > > +	/* disable delay lane */
> > > +	sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
> > > +
> > > +	/* set delay lane */
> > > +	sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R);
> > > +	sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R);
> > > +
> > > +	/* enable delay lane */
> > > +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> > > +	val &= ~(1 << UPDATE_DC);
> > > +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> > > +
> > > +	val = (1 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > > +	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 = (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > > +	sdhci_writew(host, val, PHY_CLKPAD_CNFG_R);
> > > +
> > > +	val = (1 << RXSEL) | (2 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > > +	sdhci_writew(host, val, PHY_STBPAD_CNFG_R);
> > > +
> > > +	/* enable data strobe mode */
> > > +	sdhci_writeb(host, 3 << SLV_INPSEL, PHY_DLLDL_CNFG_R);
> > > +	sdhci_writeb(host, (1 << DLL_EN),  PHY_DLL_CTRL_R);
> > > +}
> > > +
> > > +static void th1520_phy_3_3v_init(struct sdhci_host *host)
> > > +{
> > > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > > +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> > > +	u32 val;
> > > +
> > > +	if (priv->pull_up_en == 0) {
> > > +		sdhci_phy_3_3v_init_no_pull(host);
> > > +		return;
> > > +	}
> > > +
> > > +	/* set driving force */
> > > +	sdhci_writel(host, (1 << PHY_RSTN) | (0xc << PAD_SP) | (0xc << PAD_SN), PHY_CNFG_R);
> > > +
> > > +	/* disable delay lane */
> > > +	sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
> > > +
> > > +	/* set delay lane */
> > > +	sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R);
> > > +	sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R);
> > > +
> > > +	/* enable delay lane */
> > > +	val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
> > > +	val &= ~(1 << UPDATE_DC);
> > > +	sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
> > > +
> > > +	val = (2 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > > +	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 = (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > > +	sdhci_writew(host, val, PHY_CLKPAD_CNFG_R);
> > > +
> > > +	val = (2 << RXSEL) | (2 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
> > > +	sdhci_writew(host, val, PHY_STBPAD_CNFG_R);
> > > +}
> > > +
> > > +
> > > +static void th1520_sdhci_set_phy(struct sdhci_host *host)
> > > +{
> > > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > > +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> > > +	u8 emmc_ctl;
> > > +
> > > +	/* Before power on, set PHY configs */
> > > +	emmc_ctl = sdhci_readw(host, EMMC_CTRL_R);
> > > +	if (priv->non_removable) {
> > > +		th1520_phy_1_8v_init(host);
> > > +		emmc_ctl |= (1 << DWCMSHC_CARD_IS_EMMC);
> > > +	} else {
> > > +		th1520_phy_3_3v_init(host);
> > > +		emmc_ctl &=~(1 << DWCMSHC_CARD_IS_EMMC);
> > > +	}
> > > +	sdhci_writeb(host, emmc_ctl, EMMC_CTRL_R);
> > > +	sdhci_writeb(host, 0x25, PHY_DLL_CNFG1_R);
> > 
> > magic 0x25 needs a meaningful MACRO definition.
> 
> Okay, I'll investigate the meaning of that value and define it.
> 
> > 
> > > +}
> > > +
> > >  static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
> > >  				      unsigned int timing)
> > >  {
> > >  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > >  	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> > > +
> > 
> > we don't need this extra blank line
> 
> Okay
> 
> > 
> > >  	u16 ctrl, ctrl_2;
> > >  
> > >  	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> > > @@ -188,7 +409,22 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
> > >  		ctrl_2 |= DWCMSHC_CTRL_HS400;
> > >  	}
> > >  
> > > +	if (priv->io_fixed_1v8)
> > > +		ctrl_2 |= SDHCI_CTRL_VDD_180;
> > > +
> > >  	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
> > > +
> > > +	/* TODO: add check so that this only runs on th1520  */
> > 
> > this TODO needs to be solved since it affects other platforms such as NV
> > and RK
> 
> Yes, I need to fix this. For the next version, I am considering adding
> a flag to dwcmshc_priv that would gate the following code block.
> 
> 
> > > +	if (timing == MMC_TIMING_MMC_HS400) {
> > > +		/* disable auto tuning */
> > > +		u32 reg = sdhci_readl(host, AT_CTRL_R);
> > > +		reg &= ~1;
> > > +		sdhci_writel(host, reg, AT_CTRL_R);
> > > +		priv->delay_line = DELAY_LINE_HS400;
> > > +		th1520_sdhci_set_phy(host);
> > > +	} else {
> > > +		sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R);
> > > +	}
> > >  }
> > >  
> > >  static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc,
> > > @@ -337,6 +573,49 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
> > >  	sdhci_reset(host, mask);
> > >  }
> > >  
> > > +static int th1520_execute_tuning(struct sdhci_host *host, u32 opcode)
> > > +{
> > > +	u32 val = 0;
> > > +
> > > +	sdhci_writeb(host, 3 << INPSEL_CNFG, PHY_ATDL_CNFG_R);
> > > +
> > > +	val = sdhci_readl(host, AT_CTRL_R);
> > > +	val &= ~((1 << CI_SEL) | (1 << RPT_TUNE_ERR) \
> > > +	    | (1 << SW_TUNE_EN) |(0xf << WIN_EDGE_SEL));
> > > +	val |= (1 << AT_EN) | (1 << SWIN_TH_EN) | (1 << TUNE_CLK_STOP_EN)\
> > > +	    | (1 << PRE_CHANGE_DLY) | (3 << POST_CHANGE_DLY) | (9 << SWIN_TH_VAL);
> > > +
> > > +	sdhci_writel(host, val, AT_CTRL_R);
> > > +
> > > +	val = sdhci_readl(host, AT_CTRL_R);
> > > +	if(!(val & (1 << AT_EN))) {
> > > +		pr_warn("%s(): auto tuning is not enabled", __func__);
> > 
> > AFAIK, the controller supports both auto tuning and sw tuning.
> 
> Okay, I'll have to investigate further why it is like this in the vendor
> kernel [2].
> 
> > 
> > > +		return -1;
> > 
> > can we replace -1 with meaningful error number?
> > 
> 
> Yes, will do for next version.
> 
> > > +	}
> > > +
> > > +	val &= ~(1 << AT_EN);
> > > +	sdhci_writel(host, val, AT_CTRL_R);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static void th1520_sdhci_reset(struct sdhci_host *host, u8 mask)
> > > +{
> > > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > > +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
> > > +	u16 ctrl_2;
> > > +
> > > +	sdhci_reset(host, mask);
> > > +
> > > +	if(priv->io_fixed_1v8){
> > > +		ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> > > +		if(! (ctrl_2 & SDHCI_CTRL_VDD_180)){
> > > +			ctrl_2 |= SDHCI_CTRL_VDD_180;
> > > +			sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
> > > +		}
> > > +	}
> > > +}
> > > +
> > >  static const struct sdhci_ops sdhci_dwcmshc_ops = {
> > >  	.set_clock		= sdhci_set_clock,
> > >  	.set_bus_width		= sdhci_set_bus_width,
> > > @@ -355,6 +634,17 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
> > >  	.adma_write_desc	= dwcmshc_adma_write_desc,
> > >  };
> > >  
> > > +static const struct sdhci_ops sdhci_dwcmshc_th1520_ops = {
> > > +	.set_clock		= sdhci_set_clock,
> > > +	.set_bus_width		= sdhci_set_bus_width,
> > > +	.set_uhs_signaling	= dwcmshc_set_uhs_signaling,
> > > +	.get_max_clock		= dwcmshc_get_max_clock,
> > > +	.reset			= th1520_sdhci_reset,
> > > +	.adma_write_desc	= dwcmshc_adma_write_desc,
> > > +	.voltage_switch		= th1520_phy_1_8v_init,
> > > +	.platform_execute_tuning = &th1520_execute_tuning,
> > > +};
> > > +
> > >  static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
> > >  	.ops = &sdhci_dwcmshc_ops,
> > >  	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
> > > @@ -378,6 +668,15 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
> > >  		   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
> > >  };
> > >  
> > > +static const struct sdhci_pltfm_data sdhci_dwcmshc_th1520_pdata = {
> > > +	.ops = &sdhci_dwcmshc_th1520_ops,
> > > +
> > > +	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
> > > +		  SDHCI_QUIRK_BROKEN_DMA |
> > > +		  SDHCI_QUIRK_BROKEN_ADMA,
> > > +	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
> > > +};
> > > +
> > >  static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
> > >  {
> > >  	int err;
> > > @@ -434,6 +733,10 @@ static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv
> > >  }
> > >  
> > >  static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
> > > +	{
> > > +		.compatible = "thead,th1520-dwcmshc",
> > > +		.data = &sdhci_dwcmshc_th1520_pdata,
> > > +	},
> > >  	{
> > >  		.compatible = "rockchip,rk3588-dwcmshc",
> > >  		.data = &sdhci_dwcmshc_rk35xx_pdata,
> > > @@ -541,6 +844,39 @@ static int dwcmshc_probe(struct platform_device *pdev)
> > >  			goto err_clk;
> > >  	}
> > >  
> > > +	if (pltfm_data == &sdhci_dwcmshc_th1520_pdata) {
> > > +
> > > +		priv->delay_line = DELAY_LINE_DEFAULT;
> > > +
> > > +		if (device_property_present(&pdev->dev, "non-removable"))
> > > +			priv->non_removable = 1;
> > > +		else
> > > +			priv->non_removable = 0;
> > > +
> > > +		if (device_property_present(&pdev->dev, "thead,pull-up"))
> > > +			priv->pull_up_en = 1;
> > > +		else
> > > +			priv->pull_up_en = 0;
> > > +
> > > +		if (device_property_present(&pdev->dev, "thead,io-fixed-1v8"))
> > > +			priv->io_fixed_1v8 = true;
> > > +		else
> > > +			priv->io_fixed_1v8 = false;
> > > +
> > > +		/*
> > > +		 * start_signal_voltage_switch() will try 3.3V first
> > > +		 * then 1.8V. Use SDHCI_SIGNALING_180 ranther than
> > > +		 * SDHCI_SIGNALING_330 to avoid setting voltage to 3.3V
> > > +		 * in sdhci_start_signal_voltage_switch().
> > > +		 */
> > > +		if(priv->io_fixed_1v8){
> > > +			host->flags &=~SDHCI_SIGNALING_330;
> > > +			host->flags |= SDHCI_SIGNALING_180;
> > > +		}
> > > +
> > > +		sdhci_enable_v4_mode(host);
> > > +	}
> > > +
> > >  #ifdef CONFIG_ACPI
> > >  	if (pltfm_data == &sdhci_dwcmshc_bf3_pdata)
> > >  		sdhci_enable_v4_mode(host);
> > > 
> > > -- 
> > > 2.34.1
> > > 
> 
> Thank you,
> Drew
> 
> [1] https://gist.github.com/pdp7/a8301b895c2dc293f2e0210e77e45e01
> [2] https://git.beagleboard.org/beaglev-ahead/beaglev-ahead-linux/-/blob/beaglev-v5.10.113-1.1.2/drivers/mmc/host/sdhci-of-dwcmshc.c#L238
> 

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

* Re: [PATCH RFC v2 1/4] dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support
  2023-08-16 22:26     ` Drew Fustini
@ 2023-08-19 13:06       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 16+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-19 13:06 UTC (permalink / raw)
  To: Drew Fustini
  Cc: Jisheng Zhang, Guo Ren, Fu Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Conor Dooley, Adrian Hunter, Ulf Hansson, linux-riscv,
	devicetree, linux-kernel, linux-mmc, Robert Nelson,
	Jason Kridner

On 17/08/2023 00:26, Drew Fustini wrote:
> On Mon, Aug 07, 2023 at 08:29:21AM +0200, Krzysztof Kozlowski wrote:
>> On 05/08/2023 05:14, Drew Fustini wrote:
>>> Add compatible value for the T-Head TH1520 dwcmshc controller and
>>> thead,io-fixed-1v8 and thead,pull-up properties.
>>>
>>> Signed-off-by: Drew Fustini <dfustini@baylibre.com>
>>> ---
>>>  Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 9 +++++++++
>>>  1 file changed, 9 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
>>> index a43eb837f8da..57602c345cab 100644
>>> --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
>>> +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
>>> @@ -19,6 +19,7 @@ properties:
>>>        - rockchip,rk3568-dwcmshc
>>>        - rockchip,rk3588-dwcmshc
>>>        - snps,dwcmshc-sdhci
>>> +      - thead,th1520-dwcmshc
>>>  
>>>    reg:
>>>      maxItems: 1
>>> @@ -60,6 +61,14 @@ properties:
>>>      description: Specify the number of delay for tx sampling.
>>>      $ref: /schemas/types.yaml#/definitions/uint8
>>>  
>>> +  thead,io-fixed-1v8:
>>> +    description: SoC PHY pad is fixed 1.8V
>>> +    type: boolean
>>
>> Isn't this duplicating existing properties for MMC modes with 1.8 V?
> 
> Thank you for reviewing. Yes, now that you mention it, I do see those
> properties now in mmc-controller.yaml. It seems like the existing
> mmc-ddr-1_8v property would be appropriate.
> 
>>
>>> +
>>> +  thead,pull-up:
>>> +    description: True if pull-up, false if pull-down
>>
>> This explains me nothing. No clue what you are pulling and why do you
>> need it. Pin pulls should be done via pin controller, not MMC.
> 
> Good point that my description is not helpful. The pull-up property
> determines whether certain phy registers are written to. I need to try
> to can get documentation on the phy so that I can better understand the
> details of the pull-up configuration in the phy registers.
> 
>>
>> Anyway you should have here allOf:if:then (move the allOf: from top to
>> behind "required:") which will disallow these properties for other variants.
> 
> I noticed that nvidia,tegra20-sdhci.yaml has several lines related to
> pull-up/down configuration:
> 
> 218   - if:
> 219       properties:
> 220         compatible:
> 221           contains:
> 222             const: nvidia,tegra210-sdhci
> 223     then:
> 224       properties:
> 225         pinctrl-names:
> 226           oneOf:
> 227             - items:
> 228                 - const: sdmmc-3v3
> 229                   description: pad configuration for 3.3 V
> 230                 - const: sdmmc-1v8
> 231                   description: pad configuration for 1.8 V
> 232                 - const: sdmmc-3v3-drv
> 233                   description: pull-up/down configuration for 3.3 V
> 234                 - const: sdmmc-1v8-drv
> 235                   description: pull-up/down configuration for 1.8 V
> 236             - items:
> 237                 - const: sdmmc-3v3-drv
> 238                   description: pull-up/down configuration for 3.3 V
> 239                 - const: sdmmc-1v8-drv
> 240                   description: pull-up/down configuration for 1.8 V
> 241             - items:
> 242                 - const: sdmmc-1v8-drv
> 243                   description: pull-up/down configuration for 1.8 V
> 
> Do you think creating something like that would be a good approach?

This depends. Does your driver implementation will make use of it? If
yes, then it makes sense.

Best regards,
Krzysztof


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

* Re: [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead
  2023-08-05  3:14 [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead Drew Fustini
                   ` (3 preceding siblings ...)
  2023-08-05  3:14 ` [PATCH RFC v2 4/4] mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520 Drew Fustini
@ 2023-08-28  4:40 ` Jiexun Wang
  2023-08-28 15:05   ` Jisheng Zhang
  4 siblings, 1 reply; 16+ messages in thread
From: Jiexun Wang @ 2023-08-28  4:40 UTC (permalink / raw)
  To: dfustini
  Cc: adrian.hunter, aou, conor+dt, conor, devicetree, guoren,
	jkridner, jszhang, krzysztof.kozlowski+dt, linux-kernel,
	linux-mmc, linux-riscv, palmer, paul.walmsley, robertcnelson,
	robh+dt, ulf.hansson, wefu

Hello,
I tested the patch on my LicheePi 4A board.
It can successfully boot with eMMC, but when I use the eMMC more frequently - for instance:

$ while true; do /bin/dd if=/dev/zero of=bigfile bs=1024000 count=1024; done &

I encounter the following error:

sbi_trap_error: hart1: illegal instruction handler failed (error -2)
sbi_trap_error: hart1: mcause=0x0000000000000002 mtval=0x0000000060e2de4f
sbi_trap_error: hart1: mepc=0x000000000001897c mstatus=0x0000000a00001820
sbi_trap_error: hart1: ra=0x00000000000170f8 sp=0x000000000004adc8
sbi_trap_error: hart1: gp=0xffffffff8136ea90 tp=0xffffffd900228000
sbi_trap_error: hart1: s0=0x0000000000000000 s1=0x000000000004ae08
sbi_trap_error: hart1: a0=0x000000003f9aa9bc a1=0x0000000000000004
sbi_trap_error: hart1: a2=0x0000000000000000 a3=0x0000000000000000
sbi_trap_error: hart1: a4=0x0000000000042248 a5=0x00000000000170e5
sbi_trap_error: hart1: a6=0x0000000000000000 a7=0x0000000054494d45
sbi_trap_error: hart1: s2=0x000000000004aee8 s3=0x0000000000000000
sbi_trap_error: hart1: s4=0x000000000004ae08 s5=0x0000000000000000
sbi_trap_error: hart1: s6=0xffffffff813aa240 s7=0x0000000000000080
sbi_trap_error: hart1: s8=0xffffffff80a1b5f0 s9=0x0000000000000000
sbi_trap_error: hart1: s10=0xffffffd9fef5d380 s11=0xffffffff81290a80
sbi_trap_error: hart1: t0=0x0000000a00000820 t1=0x0000000000000000
sbi_trap_error: hart1: t2=0xffffffff80c00318 t3=0x0000000000000001
sbi_trap_error: hart1: t4=0x0000000000000330 t5=0x0000000000000001
sbi_trap_error: hart1: t6=0x0000000000040000

My kernel version is v6.5-rc3.
My OpenSBI version is 1.3.
I tried to use other versions of OpenSBI, yet the problem persists. 
Is there a possibility of any underlying bug? Your insights into this would be greatly appreciated.

Thanks,
Jiexun Wang


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

* Re: [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead
  2023-08-28  4:40 ` [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead Jiexun Wang
@ 2023-08-28 15:05   ` Jisheng Zhang
  2023-08-29  1:56     ` Jiexun Wang
  0 siblings, 1 reply; 16+ messages in thread
From: Jisheng Zhang @ 2023-08-28 15:05 UTC (permalink / raw)
  To: Jiexun Wang
  Cc: dfustini, adrian.hunter, aou, conor+dt, conor, devicetree,
	guoren, jkridner, krzysztof.kozlowski+dt, linux-kernel,
	linux-mmc, linux-riscv, palmer, paul.walmsley, robertcnelson,
	robh+dt, ulf.hansson, wefu

On Mon, Aug 28, 2023 at 12:40:16PM +0800, Jiexun Wang wrote:
> Hello,
> I tested the patch on my LicheePi 4A board.
> It can successfully boot with eMMC, but when I use the eMMC more frequently - for instance:
> 
> $ while true; do /bin/dd if=/dev/zero of=bigfile bs=1024000 count=1024; done &
> 
> I encounter the following error:
> 
> sbi_trap_error: hart1: illegal instruction handler failed (error -2)

> sbi_trap_error: hart1: mcause=0x0000000000000002 mtval=0x0000000060e2de4f
> sbi_trap_error: hart1: mepc=0x000000000001897c mstatus=0x0000000a00001820
> sbi_trap_error: hart1: ra=0x00000000000170f8 sp=0x000000000004adc8
> sbi_trap_error: hart1: gp=0xffffffff8136ea90 tp=0xffffffd900228000
> sbi_trap_error: hart1: s0=0x0000000000000000 s1=0x000000000004ae08
> sbi_trap_error: hart1: a0=0x000000003f9aa9bc a1=0x0000000000000004
> sbi_trap_error: hart1: a2=0x0000000000000000 a3=0x0000000000000000
> sbi_trap_error: hart1: a4=0x0000000000042248 a5=0x00000000000170e5
> sbi_trap_error: hart1: a6=0x0000000000000000 a7=0x0000000054494d45
> sbi_trap_error: hart1: s2=0x000000000004aee8 s3=0x0000000000000000
> sbi_trap_error: hart1: s4=0x000000000004ae08 s5=0x0000000000000000
> sbi_trap_error: hart1: s6=0xffffffff813aa240 s7=0x0000000000000080
> sbi_trap_error: hart1: s8=0xffffffff80a1b5f0 s9=0x0000000000000000
> sbi_trap_error: hart1: s10=0xffffffd9fef5d380 s11=0xffffffff81290a80
> sbi_trap_error: hart1: t0=0x0000000a00000820 t1=0x0000000000000000
> sbi_trap_error: hart1: t2=0xffffffff80c00318 t3=0x0000000000000001
> sbi_trap_error: hart1: t4=0x0000000000000330 t5=0x0000000000000001
> sbi_trap_error: hart1: t6=0x0000000000040000
> 
> My kernel version is v6.5-rc3.
> My OpenSBI version is 1.3.
> I tried to use other versions of OpenSBI, yet the problem persists. 
> Is there a possibility of any underlying bug? Your insights into this would be greatly appreciated.


Can you plz try below opensbi?
https://github.com/xhackerustc/thead-opensbi.git


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

* Re: [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead
  2023-08-28 15:05   ` Jisheng Zhang
@ 2023-08-29  1:56     ` Jiexun Wang
  2023-08-29 15:19       ` Drew Fustini
  0 siblings, 1 reply; 16+ messages in thread
From: Jiexun Wang @ 2023-08-29  1:56 UTC (permalink / raw)
  To: jszhang
  Cc: adrian.hunter, aou, conor+dt, conor, devicetree, dfustini,
	guoren, jkridner, krzysztof.kozlowski+dt, linux-kernel,
	linux-mmc, linux-riscv, palmer, paul.walmsley, robertcnelson,
	robh+dt, ulf.hansson, wangjiexun, wefu

Date: Mon, 28 Aug 2023 23:05:35 +0800, Jisheng Zhang wrote:
>On Mon, Aug 28, 2023 at 12:40:16PM +0800, Jiexun Wang wrote:
>> Hello,
>> I tested the patch on my LicheePi 4A board.
>> It can successfully boot with eMMC, but when I use the eMMC more frequently - for instance:
>> 
>> $ while true; do /bin/dd if=/dev/zero of=bigfile bs=1024000 count=1024; done &
>> 
>> I encounter the following error:
>> 
>> sbi_trap_error: hart1: illegal instruction handler failed (error -2)
>
>> sbi_trap_error: hart1: mcause=0x0000000000000002 mtval=0x0000000060e2de4f
>> sbi_trap_error: hart1: mepc=0x000000000001897c mstatus=0x0000000a00001820
>> sbi_trap_error: hart1: ra=0x00000000000170f8 sp=0x000000000004adc8
>> sbi_trap_error: hart1: gp=0xffffffff8136ea90 tp=0xffffffd900228000
>> sbi_trap_error: hart1: s0=0x0000000000000000 s1=0x000000000004ae08
>> sbi_trap_error: hart1: a0=0x000000003f9aa9bc a1=0x0000000000000004
>> sbi_trap_error: hart1: a2=0x0000000000000000 a3=0x0000000000000000
>> sbi_trap_error: hart1: a4=0x0000000000042248 a5=0x00000000000170e5
>> sbi_trap_error: hart1: a6=0x0000000000000000 a7=0x0000000054494d45
>> sbi_trap_error: hart1: s2=0x000000000004aee8 s3=0x0000000000000000
>> sbi_trap_error: hart1: s4=0x000000000004ae08 s5=0x0000000000000000
>> sbi_trap_error: hart1: s6=0xffffffff813aa240 s7=0x0000000000000080
>> sbi_trap_error: hart1: s8=0xffffffff80a1b5f0 s9=0x0000000000000000
>> sbi_trap_error: hart1: s10=0xffffffd9fef5d380 s11=0xffffffff81290a80
>> sbi_trap_error: hart1: t0=0x0000000a00000820 t1=0x0000000000000000
>> sbi_trap_error: hart1: t2=0xffffffff80c00318 t3=0x0000000000000001
>> sbi_trap_error: hart1: t4=0x0000000000000330 t5=0x0000000000000001
>> sbi_trap_error: hart1: t6=0x0000000000040000
>> 
>> My kernel version is v6.5-rc3.
>> My OpenSBI version is 1.3.
>> I tried to use other versions of OpenSBI, yet the problem persists. 
>> Is there a possibility of any underlying bug? Your insights into this would be greatly appreciated.
>
>
>Can you plz try below opensbi?

I tried the OpenSBI you provided and the issue didn't recur.
I conducted stress test about 30 minutes and the system appears to be functioning very well.
Thank you so much for helping me resolve this problem.

Best regards,
Jiexun Wang


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

* Re: [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead
  2023-08-29  1:56     ` Jiexun Wang
@ 2023-08-29 15:19       ` Drew Fustini
  2023-09-04 14:53         ` Jisheng Zhang
  0 siblings, 1 reply; 16+ messages in thread
From: Drew Fustini @ 2023-08-29 15:19 UTC (permalink / raw)
  To: Jiexun Wang
  Cc: jszhang, adrian.hunter, aou, conor+dt, conor, devicetree, guoren,
	jkridner, krzysztof.kozlowski+dt, linux-kernel, linux-mmc,
	linux-riscv, palmer, paul.walmsley, robertcnelson, robh+dt,
	ulf.hansson, wefu

On Tue, Aug 29, 2023 at 09:56:47AM +0800, Jiexun Wang wrote:
> Date: Mon, 28 Aug 2023 23:05:35 +0800, Jisheng Zhang wrote:
> >On Mon, Aug 28, 2023 at 12:40:16PM +0800, Jiexun Wang wrote:
> >> Hello,
> >> I tested the patch on my LicheePi 4A board.
> >> It can successfully boot with eMMC, but when I use the eMMC more frequently - for instance:
> >> 
> >> $ while true; do /bin/dd if=/dev/zero of=bigfile bs=1024000 count=1024; done &
> >> 
> >> I encounter the following error:
> >> 
> >> sbi_trap_error: hart1: illegal instruction handler failed (error -2)
> >
> >> sbi_trap_error: hart1: mcause=0x0000000000000002 mtval=0x0000000060e2de4f
> >> sbi_trap_error: hart1: mepc=0x000000000001897c mstatus=0x0000000a00001820
> >> sbi_trap_error: hart1: ra=0x00000000000170f8 sp=0x000000000004adc8
> >> sbi_trap_error: hart1: gp=0xffffffff8136ea90 tp=0xffffffd900228000
> >> sbi_trap_error: hart1: s0=0x0000000000000000 s1=0x000000000004ae08
> >> sbi_trap_error: hart1: a0=0x000000003f9aa9bc a1=0x0000000000000004
> >> sbi_trap_error: hart1: a2=0x0000000000000000 a3=0x0000000000000000
> >> sbi_trap_error: hart1: a4=0x0000000000042248 a5=0x00000000000170e5
> >> sbi_trap_error: hart1: a6=0x0000000000000000 a7=0x0000000054494d45
> >> sbi_trap_error: hart1: s2=0x000000000004aee8 s3=0x0000000000000000
> >> sbi_trap_error: hart1: s4=0x000000000004ae08 s5=0x0000000000000000
> >> sbi_trap_error: hart1: s6=0xffffffff813aa240 s7=0x0000000000000080
> >> sbi_trap_error: hart1: s8=0xffffffff80a1b5f0 s9=0x0000000000000000
> >> sbi_trap_error: hart1: s10=0xffffffd9fef5d380 s11=0xffffffff81290a80
> >> sbi_trap_error: hart1: t0=0x0000000a00000820 t1=0x0000000000000000
> >> sbi_trap_error: hart1: t2=0xffffffff80c00318 t3=0x0000000000000001
> >> sbi_trap_error: hart1: t4=0x0000000000000330 t5=0x0000000000000001
> >> sbi_trap_error: hart1: t6=0x0000000000040000
> >> 
> >> My kernel version is v6.5-rc3.
> >> My OpenSBI version is 1.3.
> >> I tried to use other versions of OpenSBI, yet the problem persists. 
> >> Is there a possibility of any underlying bug? Your insights into this would be greatly appreciated.
> >
> >
> >Can you plz try below opensbi?
> 
> I tried the OpenSBI you provided and the issue didn't recur.
> I conducted stress test about 30 minutes and the system appears to be functioning very well.
> Thank you so much for helping me resolve this problem.

That's great!

Jisheng - are these the commits that fix the error?

d98da90a19b5 ("lib: sbi_illegal_insn: Fix FENCE.TSO emulation infinite trap loop")
39d1e698c975 ("lib: sbi_illegal_insn: Add emulation for fence.tso")

thanks,
drew

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

* Re: [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead
  2023-08-29 15:19       ` Drew Fustini
@ 2023-09-04 14:53         ` Jisheng Zhang
  0 siblings, 0 replies; 16+ messages in thread
From: Jisheng Zhang @ 2023-09-04 14:53 UTC (permalink / raw)
  To: Drew Fustini
  Cc: Jiexun Wang, adrian.hunter, aou, conor+dt, conor, devicetree,
	guoren, jkridner, krzysztof.kozlowski+dt, linux-kernel,
	linux-mmc, linux-riscv, palmer, paul.walmsley, robertcnelson,
	robh+dt, ulf.hansson, wefu

On Tue, Aug 29, 2023 at 08:19:53AM -0700, Drew Fustini wrote:
> On Tue, Aug 29, 2023 at 09:56:47AM +0800, Jiexun Wang wrote:
> > Date: Mon, 28 Aug 2023 23:05:35 +0800, Jisheng Zhang wrote:
> > >On Mon, Aug 28, 2023 at 12:40:16PM +0800, Jiexun Wang wrote:
> > >> Hello,
> > >> I tested the patch on my LicheePi 4A board.
> > >> It can successfully boot with eMMC, but when I use the eMMC more frequently - for instance:
> > >> 
> > >> $ while true; do /bin/dd if=/dev/zero of=bigfile bs=1024000 count=1024; done &
> > >> 
> > >> I encounter the following error:
> > >> 
> > >> sbi_trap_error: hart1: illegal instruction handler failed (error -2)
> > >
> > >> sbi_trap_error: hart1: mcause=0x0000000000000002 mtval=0x0000000060e2de4f
> > >> sbi_trap_error: hart1: mepc=0x000000000001897c mstatus=0x0000000a00001820
> > >> sbi_trap_error: hart1: ra=0x00000000000170f8 sp=0x000000000004adc8
> > >> sbi_trap_error: hart1: gp=0xffffffff8136ea90 tp=0xffffffd900228000
> > >> sbi_trap_error: hart1: s0=0x0000000000000000 s1=0x000000000004ae08
> > >> sbi_trap_error: hart1: a0=0x000000003f9aa9bc a1=0x0000000000000004
> > >> sbi_trap_error: hart1: a2=0x0000000000000000 a3=0x0000000000000000
> > >> sbi_trap_error: hart1: a4=0x0000000000042248 a5=0x00000000000170e5
> > >> sbi_trap_error: hart1: a6=0x0000000000000000 a7=0x0000000054494d45
> > >> sbi_trap_error: hart1: s2=0x000000000004aee8 s3=0x0000000000000000
> > >> sbi_trap_error: hart1: s4=0x000000000004ae08 s5=0x0000000000000000
> > >> sbi_trap_error: hart1: s6=0xffffffff813aa240 s7=0x0000000000000080
> > >> sbi_trap_error: hart1: s8=0xffffffff80a1b5f0 s9=0x0000000000000000
> > >> sbi_trap_error: hart1: s10=0xffffffd9fef5d380 s11=0xffffffff81290a80
> > >> sbi_trap_error: hart1: t0=0x0000000a00000820 t1=0x0000000000000000
> > >> sbi_trap_error: hart1: t2=0xffffffff80c00318 t3=0x0000000000000001
> > >> sbi_trap_error: hart1: t4=0x0000000000000330 t5=0x0000000000000001
> > >> sbi_trap_error: hart1: t6=0x0000000000040000
> > >> 
> > >> My kernel version is v6.5-rc3.
> > >> My OpenSBI version is 1.3.
> > >> I tried to use other versions of OpenSBI, yet the problem persists. 
> > >> Is there a possibility of any underlying bug? Your insights into this would be greatly appreciated.
> > >
> > >
> > >Can you plz try below opensbi?
> > 
> > I tried the OpenSBI you provided and the issue didn't recur.
> > I conducted stress test about 30 minutes and the system appears to be functioning very well.
> > Thank you so much for helping me resolve this problem.
> 
> That's great!
> 
> Jisheng - are these the commits that fix the error?
> 
> d98da90a19b5 ("lib: sbi_illegal_insn: Fix FENCE.TSO emulation infinite trap loop")
> 39d1e698c975 ("lib: sbi_illegal_insn: Add emulation for fence.tso")
> 

These two commits have been in upstream OpenSBI, so there
must be something to be patched/fixed in the upstream OpenSBI, but I have not
yet bisected the upstream OpenSBI to find the root cause.
This issue is on my TODO list.

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

end of thread, other threads:[~2023-09-04 15:05 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-05  3:14 [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead Drew Fustini
2023-08-05  3:14 ` [PATCH RFC v2 1/4] dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support Drew Fustini
2023-08-07  6:29   ` Krzysztof Kozlowski
2023-08-16 22:26     ` Drew Fustini
2023-08-19 13:06       ` Krzysztof Kozlowski
2023-08-05  3:14 ` [PATCH RFC v2 2/4] riscv: dts: thead: Add TH1520 mmc controller and sdhci clock Drew Fustini
2023-08-05  3:14 ` [PATCH RFC v2 3/4] riscv: dts: thead: Enable BeagleV Ahead eMMC controller Drew Fustini
2023-08-05  3:14 ` [PATCH RFC v2 4/4] mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520 Drew Fustini
2023-08-06 10:09   ` Jisheng Zhang
2023-08-16 21:17     ` Drew Fustini
2023-08-17 23:32       ` Guo Ren
2023-08-28  4:40 ` [PATCH RFC v2 0/4] RISC-V: Add basic eMMC support for BeagleV Ahead Jiexun Wang
2023-08-28 15:05   ` Jisheng Zhang
2023-08-29  1:56     ` Jiexun Wang
2023-08-29 15:19       ` Drew Fustini
2023-09-04 14:53         ` Jisheng Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).