linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] Add ARTPEC-8 support to DWMMC controller
@ 2021-12-06 14:29 Mårten Lindahl
  2021-12-06 14:29 ` [PATCH v2 1/4] dt-bindings: mmc: exynos-dw-mshc: Add support for ARTPEC-8 Mårten Lindahl
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Mårten Lindahl @ 2021-12-06 14:29 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Jaehoon Chung
  Cc: Doug Anderson, kernel, linux-mmc, devicetree, linux-arm-kernel,
	linux-samsung-soc, Mårten Lindahl

Hi!

The ARTPEC-8 SoC has a DWMMC controller that is compatible with the
Exynos 7 version v2.70a. The main differences from Exynos 7 is that it
does not support HS400 and has an extended data read timeout. To run
this controller we need to add compatibility for ARTPEC-8, because we
need a quirk to separate the configuration of the TMOUT register from
the non ARTPEC-8 versions.

This patchset is dependent on 2 changes that has been added to the mmc
git next branch, but has not yet been merged to mainline:

Patch 2 of this patchset depends on commit 0e6f2c4c2072b ("mmc: dw_mmc:
add common capabilities to replace caps").

Patch 3 of this patchset depends on commit d5bc33487eab3 ("mmc: dw_mmc:
Allow lower TMOUT value than maximum").

Kind regards
Mårten Lindahl

Changes in v2:
 - Change compatible string vendor prefix
 - Removed unnecessary comment
 - Change 1<<0 to BIT(0)

Mårten Lindahl (4):
  dt-bindings: mmc: exynos-dw-mshc: Add support for ARTPEC-8
  mmc: dw_mmc-exynos: Add support for ARTPEC-8
  mmc: dw_mmc: Add quirk for extended data read timeout
  mmc: dw_mmc: Do not wait for DTO in case of error

 .../bindings/mmc/exynos-dw-mshc.txt           |  2 +
 drivers/mmc/host/dw_mmc-exynos.c              | 52 +++++++++++++++----
 drivers/mmc/host/dw_mmc.c                     | 41 +++++++++++++--
 drivers/mmc/host/dw_mmc.h                     |  6 +++
 4 files changed, 86 insertions(+), 15 deletions(-)

-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v2 1/4] dt-bindings: mmc: exynos-dw-mshc: Add support for ARTPEC-8
  2021-12-06 14:29 [PATCH v2 0/4] Add ARTPEC-8 support to DWMMC controller Mårten Lindahl
@ 2021-12-06 14:29 ` Mårten Lindahl
  2021-12-07  9:40   ` Krzysztof Kozlowski
  2021-12-06 14:29 ` [PATCH v2 2/4] mmc: dw_mmc-exynos: " Mårten Lindahl
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 12+ messages in thread
From: Mårten Lindahl @ 2021-12-06 14:29 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Jaehoon Chung
  Cc: Doug Anderson, kernel, linux-mmc, devicetree, linux-arm-kernel,
	linux-samsung-soc, Mårten Lindahl

The ARTPEC-8 SoC has a DWMMC controller that is compatible with the
Exynos 7 version v2.70a. The main differences from Exynos 7 is that it
does not support HS400 and has extended data read timeout.

Add compatibility string "axis,artpec8-dw-mshc" for ARTPEC-8.

Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---

v2:
 - Change compatible string vendor prefix

 Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
index 0419a63f73a0..753e9d7d8956 100644
--- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
@@ -22,6 +22,8 @@ Required Properties:
 	  specific extensions.
 	- "samsung,exynos7-dw-mshc-smu": for controllers with Samsung Exynos7
 	  specific extensions having an SMU.
+	- "axis,artpec8-dw-mshc": for controllers with ARTPEC-8 specific
+	  extensions.
 
 * samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface
   unit (ciu) clock. This property is applicable only for Exynos5 SoC's and
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v2 2/4] mmc: dw_mmc-exynos: Add support for ARTPEC-8
  2021-12-06 14:29 [PATCH v2 0/4] Add ARTPEC-8 support to DWMMC controller Mårten Lindahl
  2021-12-06 14:29 ` [PATCH v2 1/4] dt-bindings: mmc: exynos-dw-mshc: Add support for ARTPEC-8 Mårten Lindahl
@ 2021-12-06 14:29 ` Mårten Lindahl
  2021-12-07  9:40   ` Krzysztof Kozlowski
  2021-12-06 14:29 ` [PATCH v2 3/4] mmc: dw_mmc: Add quirk for extended data read timeout Mårten Lindahl
  2021-12-06 14:29 ` [PATCH v2 4/4] mmc: dw_mmc: Do not wait for DTO in case of error Mårten Lindahl
  3 siblings, 1 reply; 12+ messages in thread
From: Mårten Lindahl @ 2021-12-06 14:29 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Jaehoon Chung
  Cc: Doug Anderson, kernel, linux-mmc, devicetree, linux-arm-kernel,
	linux-samsung-soc, Mårten Lindahl

The ARTPEC-8 SoC has a DWMMC controller that is compatible with the
Exynos 7 version v2.70a. The main differences from Exynos 7 is that it
does not support HS400 and has extended data read timeout.

This patch adds compatibility string "axis,artpec8-dw-mshc" for
ARTPEC-8, and DW_MCI_TYPE_ARTPEC8 is added to the dw_mci_exynos_type.

Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---

v2:
 - Change compatible string vendor prefix

 drivers/mmc/host/dw_mmc-exynos.c | 47 ++++++++++++++++++++++++--------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index f76eeeb0cc53..86486e6659de 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -28,6 +28,7 @@ enum dw_mci_exynos_type {
 	DW_MCI_TYPE_EXYNOS5420_SMU,
 	DW_MCI_TYPE_EXYNOS7,
 	DW_MCI_TYPE_EXYNOS7_SMU,
+	DW_MCI_TYPE_ARTPEC8,
 };
 
 /* Exynos implementation specific driver private data */
@@ -69,6 +70,9 @@ static struct dw_mci_exynos_compatible {
 	}, {
 		.compatible	= "samsung,exynos7-dw-mshc-smu",
 		.ctrl_type	= DW_MCI_TYPE_EXYNOS7_SMU,
+	}, {
+		.compatible	= "axis,artpec8-dw-mshc",
+		.ctrl_type	= DW_MCI_TYPE_ARTPEC8,
 	},
 };
 
@@ -81,7 +85,8 @@ static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host)
 	else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
 		return EXYNOS4210_FIXED_CIU_CLK_DIV;
 	else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-			priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+			priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+			priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
 		return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1;
 	else
 		return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1;
@@ -133,7 +138,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
 	u32 clksel;
 
 	if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+		priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
 		clksel = mci_readl(host, CLKSEL64);
 	else
 		clksel = mci_readl(host, CLKSEL);
@@ -141,7 +147,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
 	clksel = (clksel & ~SDMMC_CLKSEL_TIMING_MASK) | timing;
 
 	if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+		priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
 		mci_writel(host, CLKSEL64, clksel);
 	else
 		mci_writel(host, CLKSEL, clksel);
@@ -210,14 +217,16 @@ static int dw_mci_exynos_resume_noirq(struct device *dev)
 		return ret;
 
 	if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+		priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
 		clksel = mci_readl(host, CLKSEL64);
 	else
 		clksel = mci_readl(host, CLKSEL);
 
 	if (clksel & SDMMC_CLKSEL_WAKEUP_INT) {
 		if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-			priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+			priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+			priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
 			mci_writel(host, CLKSEL64, clksel);
 		else
 			mci_writel(host, CLKSEL, clksel);
@@ -238,7 +247,8 @@ static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)
 	 * Not supported to configure register
 	 * related to HS400
 	 */
-	if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420) {
+	if ((priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420) ||
+		(priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)) {
 		if (timing == MMC_TIMING_MMC_HS400)
 			dev_warn(host->dev,
 				 "cannot configure HS400, unsupported chipset\n");
@@ -394,7 +404,8 @@ static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host)
 	struct dw_mci_exynos_priv_data *priv = host->priv;
 
 	if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+		priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
 		return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL64));
 	else
 		return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL));
@@ -406,13 +417,15 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
 	struct dw_mci_exynos_priv_data *priv = host->priv;
 
 	if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+		priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
 		clksel = mci_readl(host, CLKSEL64);
 	else
 		clksel = mci_readl(host, CLKSEL);
 	clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
 	if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+		priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
 		mci_writel(host, CLKSEL64, clksel);
 	else
 		mci_writel(host, CLKSEL, clksel);
@@ -425,7 +438,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
 	u8 sample;
 
 	if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+		priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
 		clksel = mci_readl(host, CLKSEL64);
 	else
 		clksel = mci_readl(host, CLKSEL);
@@ -434,7 +448,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
 	clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
 
 	if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+		priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
 		mci_writel(host, CLKSEL64, clksel);
 	else
 		mci_writel(host, CLKSEL, clksel);
@@ -543,6 +558,14 @@ static const struct dw_mci_drv_data exynos_drv_data = {
 	.prepare_hs400_tuning	= dw_mci_exynos_prepare_hs400_tuning,
 };
 
+static const struct dw_mci_drv_data artpec_drv_data = {
+	.common_caps		= MMC_CAP_CMD23,
+	.init			= dw_mci_exynos_priv_init,
+	.set_ios		= dw_mci_exynos_set_ios,
+	.parse_dt		= dw_mci_exynos_parse_dt,
+	.execute_tuning		= dw_mci_exynos_execute_tuning,
+};
+
 static const struct of_device_id dw_mci_exynos_match[] = {
 	{ .compatible = "samsung,exynos4412-dw-mshc",
 			.data = &exynos_drv_data, },
@@ -556,6 +579,8 @@ static const struct of_device_id dw_mci_exynos_match[] = {
 			.data = &exynos_drv_data, },
 	{ .compatible = "samsung,exynos7-dw-mshc-smu",
 			.data = &exynos_drv_data, },
+	{ .compatible = "axis,artpec8-dw-mshc",
+			.data = &artpec_drv_data, },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v2 3/4] mmc: dw_mmc: Add quirk for extended data read timeout
  2021-12-06 14:29 [PATCH v2 0/4] Add ARTPEC-8 support to DWMMC controller Mårten Lindahl
  2021-12-06 14:29 ` [PATCH v2 1/4] dt-bindings: mmc: exynos-dw-mshc: Add support for ARTPEC-8 Mårten Lindahl
  2021-12-06 14:29 ` [PATCH v2 2/4] mmc: dw_mmc-exynos: " Mårten Lindahl
@ 2021-12-06 14:29 ` Mårten Lindahl
  2021-12-07  9:41   ` Krzysztof Kozlowski
  2021-12-08 14:41   ` Ulf Hansson
  2021-12-06 14:29 ` [PATCH v2 4/4] mmc: dw_mmc: Do not wait for DTO in case of error Mårten Lindahl
  3 siblings, 2 replies; 12+ messages in thread
From: Mårten Lindahl @ 2021-12-06 14:29 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Jaehoon Chung
  Cc: Doug Anderson, kernel, linux-mmc, devicetree, linux-arm-kernel,
	linux-samsung-soc, Mårten Lindahl

Current dw_mci driver supports a TMOUT register which consists of a 24
bit field (TMOUT[31:8]) for the DATA_TIMEOUT. The maximum value of this
field is 0xFFFFFF, which with a 200MHz clock will give a full DRTO of:

0xFFFFFF / 200000000 => ~84 ms

However, the ARTPEC-8 SoC DWMMC IP version has a TMOUT register with an
extended DATA_TIMEOUT field, which supports longer timers for the DRTO.
In this version the DATA_TIMEOUT field is split into two, which with the
same 200MHz clock as above will allow a maximum timeout of:

((TMOUT[10:8] -1) * 0xFFFFFF + TMOUT[31:11] * 8) / 200000000 => ~587 ms

Add a quirk to support this. The quirk is enabled for ARTPEC-8 SoCs.

Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---

v2:
 - Removed unnecessary comment
 - Change 1<<0 to BIT(0)

 drivers/mmc/host/dw_mmc-exynos.c |  5 +++++
 drivers/mmc/host/dw_mmc.c        | 33 ++++++++++++++++++++++++++++----
 drivers/mmc/host/dw_mmc.h        |  6 ++++++
 3 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 86486e6659de..1b625642c5b4 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -127,6 +127,11 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
 				DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
 	}
 
+	if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) {
+		/* Quirk needed for ARTPEC-8 SoCs */
+		host->quirks |= DW_MMC_QUIRK_EXTENDED_TMOUT;
+	}
+
 	host->bus_hz /= (priv->ciu_div + 1);
 
 	return 0;
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index f2a14a434bef..45ea9fd97a6a 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1289,6 +1289,7 @@ static void dw_mci_set_data_timeout(struct dw_mci *host,
 {
 	u32 clk_div, tmout;
 	u64 tmp;
+	unsigned int tmp2;
 
 	clk_div = (mci_readl(host, CLKDIV) & 0xFF) * 2;
 	if (clk_div == 0)
@@ -1301,10 +1302,28 @@ static void dw_mci_set_data_timeout(struct dw_mci *host,
 	tmout = 0xFF; /* Set maximum */
 
 	/* TMOUT[31:8] (DATA_TIMEOUT) */
-	if (!tmp || tmp > 0xFFFFFF)
-		tmout |= (0xFFFFFF << 8);
-	else
-		tmout |= (tmp & 0xFFFFFF) << 8;
+	if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT) {
+		/*
+		 * Extended HW timer (max = 0x6FFFFF2):
+		 * ((TMOUT[10:8] - 1) * 0xFFFFFF + TMOUT[31:11] * 8)
+		 */
+		if (!tmp || tmp > 0x6FFFFF2)
+			tmout |= (0xFFFFFF << 8);
+		else {
+			/* TMOUT[10:8] */
+			tmp2 = (((unsigned int)tmp / 0xFFFFFF) + 1) & 0x7;
+			tmout |= tmp2 << 8;
+
+			/* TMOUT[31:11] */
+			tmp = tmp - ((tmp2 - 1) * 0xFFFFFF);
+			tmout |= (tmp & 0xFFFFF8) << 8;
+		}
+	} else {
+		if (!tmp || tmp > 0xFFFFFF)
+			tmout |= (0xFFFFFF << 8);
+		else
+			tmout |= (tmp & 0xFFFFFF) << 8;
+	}
 
 	mci_writel(host, TMOUT, tmout);
 	dev_dbg(host->dev, "timeout_ns: %u => TMOUT[31:8]: 0x%#08x",
@@ -2005,9 +2024,15 @@ static void dw_mci_set_drto(struct dw_mci *host)
 	if (drto_div == 0)
 		drto_div = 1;
 
+	if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
+		drto_clks = (((drto_clks & 0x7) - 1) * 0xFFFFFF) +
+			((drto_clks & 0xFFFFF8));
+
 	drto_ms = DIV_ROUND_UP_ULL((u64)MSEC_PER_SEC * drto_clks * drto_div,
 				   host->bus_hz);
 
+	dev_dbg(host->dev, "drto_ms: %u\n", drto_ms);
+
 	/* add a bit spare time */
 	drto_ms += 10;
 
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 771d5afa3136..3b6510d4a684 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -118,6 +118,7 @@ struct dw_mci_dma_slave {
  * @part_buf: Simple buffer for partial fifo reads/writes.
  * @push_data: Pointer to FIFO push function.
  * @pull_data: Pointer to FIFO pull function.
+ * @quirks: Set of quirks that apply to specific versions of the IP.
  * @vqmmc_enabled: Status of vqmmc, should be true or false.
  * @irq_flags: The flags to be passed to request_irq.
  * @irq: The irq value to be passed to request_irq.
@@ -223,6 +224,8 @@ struct dw_mci {
 	void (*push_data)(struct dw_mci *host, void *buf, int cnt);
 	void (*pull_data)(struct dw_mci *host, void *buf, int cnt);
 
+	u32			quirks;
+
 	bool			vqmmc_enabled;
 	unsigned long		irq_flags; /* IRQ flags */
 	int			irq;
@@ -274,6 +277,9 @@ struct dw_mci_board {
 	struct dma_pdata *data;
 };
 
+/* Support for longer data read timeout */
+#define DW_MMC_QUIRK_EXTENDED_TMOUT		BIT(0)
+
 #define DW_MMC_240A		0x240a
 #define DW_MMC_280A		0x280a
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v2 4/4] mmc: dw_mmc: Do not wait for DTO in case of error
  2021-12-06 14:29 [PATCH v2 0/4] Add ARTPEC-8 support to DWMMC controller Mårten Lindahl
                   ` (2 preceding siblings ...)
  2021-12-06 14:29 ` [PATCH v2 3/4] mmc: dw_mmc: Add quirk for extended data read timeout Mårten Lindahl
@ 2021-12-06 14:29 ` Mårten Lindahl
  2021-12-08 14:53   ` Ulf Hansson
  3 siblings, 1 reply; 12+ messages in thread
From: Mårten Lindahl @ 2021-12-06 14:29 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Jaehoon Chung
  Cc: Doug Anderson, kernel, linux-mmc, devicetree, linux-arm-kernel,
	linux-samsung-soc, Mårten Lindahl

When running the ARTPEC-8 DWMMC IP version, and a data error interrupt
comes during a data read transfer, there is no guarantee for the data
transfer over interrupt (DTO) to come within the specified data timeout.
This case is handled by the dto_timer handler which will complete the
request with the comment:

 /*
  * If DTO interrupt does NOT come in sending data state,
  * we should notify the driver to terminate current transfer
  * and report a data timeout to the core.
  */

But since the ARTPEC-8 DWMMC IP version, supports an extended TMOUT
register which allows longer timeouts than the non ARTPEC-8 version
does, waiting for the dto_timer to complete the request in error cases
may cause the request to take significantly longer time than necessary.
This is specifically true for the failing steps during tuning of a
device.

Fix this by completing the request when the error interrupt comes.

Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---
 drivers/mmc/host/dw_mmc.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 45ea9fd97a6a..d6b76f47b1a2 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -2777,11 +2777,19 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 		if (pending & DW_MCI_DATA_ERROR_FLAGS) {
 			spin_lock(&host->irq_lock);
 
+			if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
+				del_timer(&host->dto_timer);
+
 			/* if there is an error report DATA_ERROR */
 			mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
 			host->data_status = pending;
 			smp_wmb(); /* drain writebuffer */
 			set_bit(EVENT_DATA_ERROR, &host->pending_events);
+
+			if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
+				/* In case of error, we cannot expect a DTO */
+				set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
+
 			tasklet_schedule(&host->tasklet);
 
 			spin_unlock(&host->irq_lock);
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v2 1/4] dt-bindings: mmc: exynos-dw-mshc: Add support for ARTPEC-8
  2021-12-06 14:29 ` [PATCH v2 1/4] dt-bindings: mmc: exynos-dw-mshc: Add support for ARTPEC-8 Mårten Lindahl
@ 2021-12-07  9:40   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2021-12-07  9:40 UTC (permalink / raw)
  To: Mårten Lindahl, Ulf Hansson, Rob Herring, Jaehoon Chung
  Cc: Doug Anderson, kernel, linux-mmc, devicetree, linux-arm-kernel,
	linux-samsung-soc

On 06/12/2021 15:29, Mårten Lindahl wrote:
> The ARTPEC-8 SoC has a DWMMC controller that is compatible with the
> Exynos 7 version v2.70a. The main differences from Exynos 7 is that it
> does not support HS400 and has extended data read timeout.
> 
> Add compatibility string "axis,artpec8-dw-mshc" for ARTPEC-8.
> 
> Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
> ---
> 
> v2:
>  - Change compatible string vendor prefix
> 
>  Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
> index 0419a63f73a0..753e9d7d8956 100644
> --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
> +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
> @@ -22,6 +22,8 @@ Required Properties:
>  	  specific extensions.
>  	- "samsung,exynos7-dw-mshc-smu": for controllers with Samsung Exynos7
>  	  specific extensions having an SMU.
> +	- "axis,artpec8-dw-mshc": for controllers with ARTPEC-8 specific
> +	  extensions.
>  
>  * samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface
>    unit (ciu) clock. This property is applicable only for Exynos5 SoC's and
> 


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

Best regards,
Krzysztof

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v2 2/4] mmc: dw_mmc-exynos: Add support for ARTPEC-8
  2021-12-06 14:29 ` [PATCH v2 2/4] mmc: dw_mmc-exynos: " Mårten Lindahl
@ 2021-12-07  9:40   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2021-12-07  9:40 UTC (permalink / raw)
  To: Mårten Lindahl, Ulf Hansson, Rob Herring, Jaehoon Chung
  Cc: Doug Anderson, kernel, linux-mmc, devicetree, linux-arm-kernel,
	linux-samsung-soc

On 06/12/2021 15:29, Mårten Lindahl wrote:
> The ARTPEC-8 SoC has a DWMMC controller that is compatible with the
> Exynos 7 version v2.70a. The main differences from Exynos 7 is that it
> does not support HS400 and has extended data read timeout.
> 
> This patch adds compatibility string "axis,artpec8-dw-mshc" for
> ARTPEC-8, and DW_MCI_TYPE_ARTPEC8 is added to the dw_mci_exynos_type.
> 
> Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
> ---
> 
> v2:
>  - Change compatible string vendor prefix
> 
>  drivers/mmc/host/dw_mmc-exynos.c | 47 ++++++++++++++++++++++++--------
>  1 file changed, 36 insertions(+), 11 deletions(-)
> 


Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>


Best regards,
Krzysztof

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v2 3/4] mmc: dw_mmc: Add quirk for extended data read timeout
  2021-12-06 14:29 ` [PATCH v2 3/4] mmc: dw_mmc: Add quirk for extended data read timeout Mårten Lindahl
@ 2021-12-07  9:41   ` Krzysztof Kozlowski
  2021-12-08 14:41   ` Ulf Hansson
  1 sibling, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2021-12-07  9:41 UTC (permalink / raw)
  To: Mårten Lindahl, Ulf Hansson, Rob Herring, Jaehoon Chung
  Cc: Doug Anderson, kernel, linux-mmc, devicetree, linux-arm-kernel,
	linux-samsung-soc

On 06/12/2021 15:29, Mårten Lindahl wrote:
> Current dw_mci driver supports a TMOUT register which consists of a 24
> bit field (TMOUT[31:8]) for the DATA_TIMEOUT. The maximum value of this
> field is 0xFFFFFF, which with a 200MHz clock will give a full DRTO of:
> 
> 0xFFFFFF / 200000000 => ~84 ms
> 
> However, the ARTPEC-8 SoC DWMMC IP version has a TMOUT register with an
> extended DATA_TIMEOUT field, which supports longer timers for the DRTO.
> In this version the DATA_TIMEOUT field is split into two, which with the
> same 200MHz clock as above will allow a maximum timeout of:
> 
> ((TMOUT[10:8] -1) * 0xFFFFFF + TMOUT[31:11] * 8) / 200000000 => ~587 ms
> 
> Add a quirk to support this. The quirk is enabled for ARTPEC-8 SoCs.
> 
> Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
> ---
> 
> v2:
>  - Removed unnecessary comment
>  - Change 1<<0 to BIT(0)
> 
>  drivers/mmc/host/dw_mmc-exynos.c |  5 +++++
>  drivers/mmc/host/dw_mmc.c        | 33 ++++++++++++++++++++++++++++----
>  drivers/mmc/host/dw_mmc.h        |  6 ++++++
>  3 files changed, 40 insertions(+), 4 deletions(-)
> 


Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>


Best regards,
Krzysztof

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v2 3/4] mmc: dw_mmc: Add quirk for extended data read timeout
  2021-12-06 14:29 ` [PATCH v2 3/4] mmc: dw_mmc: Add quirk for extended data read timeout Mårten Lindahl
  2021-12-07  9:41   ` Krzysztof Kozlowski
@ 2021-12-08 14:41   ` Ulf Hansson
  2021-12-08 21:04     ` Marten Lindahl
  1 sibling, 1 reply; 12+ messages in thread
From: Ulf Hansson @ 2021-12-08 14:41 UTC (permalink / raw)
  To: Mårten Lindahl
  Cc: Rob Herring, Krzysztof Kozlowski, Jaehoon Chung, Doug Anderson,
	kernel, linux-mmc, devicetree, linux-arm-kernel,
	linux-samsung-soc

On Mon, 6 Dec 2021 at 15:29, Mårten Lindahl <marten.lindahl@axis.com> wrote:
>
> Current dw_mci driver supports a TMOUT register which consists of a 24
> bit field (TMOUT[31:8]) for the DATA_TIMEOUT. The maximum value of this
> field is 0xFFFFFF, which with a 200MHz clock will give a full DRTO of:
>
> 0xFFFFFF / 200000000 => ~84 ms
>
> However, the ARTPEC-8 SoC DWMMC IP version has a TMOUT register with an
> extended DATA_TIMEOUT field, which supports longer timers for the DRTO.
> In this version the DATA_TIMEOUT field is split into two, which with the
> same 200MHz clock as above will allow a maximum timeout of:
>
> ((TMOUT[10:8] -1) * 0xFFFFFF + TMOUT[31:11] * 8) / 200000000 => ~587 ms
>
> Add a quirk to support this. The quirk is enabled for ARTPEC-8 SoCs.
>
> Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
> ---
>
> v2:
>  - Removed unnecessary comment
>  - Change 1<<0 to BIT(0)
>
>  drivers/mmc/host/dw_mmc-exynos.c |  5 +++++
>  drivers/mmc/host/dw_mmc.c        | 33 ++++++++++++++++++++++++++++----
>  drivers/mmc/host/dw_mmc.h        |  6 ++++++
>  3 files changed, 40 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
> index 86486e6659de..1b625642c5b4 100644
> --- a/drivers/mmc/host/dw_mmc-exynos.c
> +++ b/drivers/mmc/host/dw_mmc-exynos.c
> @@ -127,6 +127,11 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
>                                 DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
>         }
>
> +       if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) {
> +               /* Quirk needed for ARTPEC-8 SoCs */
> +               host->quirks |= DW_MMC_QUIRK_EXTENDED_TMOUT;
> +       }
> +
>         host->bus_hz /= (priv->ciu_div + 1);
>
>         return 0;
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index f2a14a434bef..45ea9fd97a6a 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -1289,6 +1289,7 @@ static void dw_mci_set_data_timeout(struct dw_mci *host,
>  {
>         u32 clk_div, tmout;
>         u64 tmp;
> +       unsigned int tmp2;
>
>         clk_div = (mci_readl(host, CLKDIV) & 0xFF) * 2;
>         if (clk_div == 0)
> @@ -1301,10 +1302,28 @@ static void dw_mci_set_data_timeout(struct dw_mci *host,
>         tmout = 0xFF; /* Set maximum */
>
>         /* TMOUT[31:8] (DATA_TIMEOUT) */
> -       if (!tmp || tmp > 0xFFFFFF)
> -               tmout |= (0xFFFFFF << 8);
> -       else
> -               tmout |= (tmp & 0xFFFFFF) << 8;
> +       if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT) {

Adding an option for dealing with quirks, should be avoided if
possible. That's because we want to avoid sprinkling common dw_mmc
code with variant specific code, as it will sooner or later turn into
a nightmare to maintain.

In this case, I suggest you look into extending the struct
dw_mci_drv_data with some new callback (perhaps ->set_data_timeout())
and then implement it for your variant.
If that callback is present, it should take precedence over the
generic dw_mci_set_data_timeout(), if you get what I mean.

Moreover, if some common dw_mmc code needs to be called from your
callback, I suggest we make that code available through exported
dw_mmc library functions instead.

> +               /*
> +                * Extended HW timer (max = 0x6FFFFF2):
> +                * ((TMOUT[10:8] - 1) * 0xFFFFFF + TMOUT[31:11] * 8)
> +                */
> +               if (!tmp || tmp > 0x6FFFFF2)
> +                       tmout |= (0xFFFFFF << 8);
> +               else {
> +                       /* TMOUT[10:8] */
> +                       tmp2 = (((unsigned int)tmp / 0xFFFFFF) + 1) & 0x7;
> +                       tmout |= tmp2 << 8;
> +
> +                       /* TMOUT[31:11] */
> +                       tmp = tmp - ((tmp2 - 1) * 0xFFFFFF);
> +                       tmout |= (tmp & 0xFFFFF8) << 8;
> +               }
> +       } else {
> +               if (!tmp || tmp > 0xFFFFFF)
> +                       tmout |= (0xFFFFFF << 8);
> +               else
> +                       tmout |= (tmp & 0xFFFFFF) << 8;
> +       }
>
>         mci_writel(host, TMOUT, tmout);
>         dev_dbg(host->dev, "timeout_ns: %u => TMOUT[31:8]: 0x%#08x",
> @@ -2005,9 +2024,15 @@ static void dw_mci_set_drto(struct dw_mci *host)
>         if (drto_div == 0)
>                 drto_div = 1;
>
> +       if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
> +               drto_clks = (((drto_clks & 0x7) - 1) * 0xFFFFFF) +
> +                       ((drto_clks & 0xFFFFF8));
> +
>         drto_ms = DIV_ROUND_UP_ULL((u64)MSEC_PER_SEC * drto_clks * drto_div,
>                                    host->bus_hz);
>
> +       dev_dbg(host->dev, "drto_ms: %u\n", drto_ms);
> +
>         /* add a bit spare time */
>         drto_ms += 10;
>
> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> index 771d5afa3136..3b6510d4a684 100644
> --- a/drivers/mmc/host/dw_mmc.h
> +++ b/drivers/mmc/host/dw_mmc.h
> @@ -118,6 +118,7 @@ struct dw_mci_dma_slave {
>   * @part_buf: Simple buffer for partial fifo reads/writes.
>   * @push_data: Pointer to FIFO push function.
>   * @pull_data: Pointer to FIFO pull function.
> + * @quirks: Set of quirks that apply to specific versions of the IP.
>   * @vqmmc_enabled: Status of vqmmc, should be true or false.
>   * @irq_flags: The flags to be passed to request_irq.
>   * @irq: The irq value to be passed to request_irq.
> @@ -223,6 +224,8 @@ struct dw_mci {
>         void (*push_data)(struct dw_mci *host, void *buf, int cnt);
>         void (*pull_data)(struct dw_mci *host, void *buf, int cnt);
>
> +       u32                     quirks;
> +
>         bool                    vqmmc_enabled;
>         unsigned long           irq_flags; /* IRQ flags */
>         int                     irq;
> @@ -274,6 +277,9 @@ struct dw_mci_board {
>         struct dma_pdata *data;
>  };
>
> +/* Support for longer data read timeout */
> +#define DW_MMC_QUIRK_EXTENDED_TMOUT            BIT(0)
> +
>  #define DW_MMC_240A            0x240a
>  #define DW_MMC_280A            0x280a
>

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v2 4/4] mmc: dw_mmc: Do not wait for DTO in case of error
  2021-12-06 14:29 ` [PATCH v2 4/4] mmc: dw_mmc: Do not wait for DTO in case of error Mårten Lindahl
@ 2021-12-08 14:53   ` Ulf Hansson
  2021-12-08 22:01     ` Marten Lindahl
  0 siblings, 1 reply; 12+ messages in thread
From: Ulf Hansson @ 2021-12-08 14:53 UTC (permalink / raw)
  To: Mårten Lindahl
  Cc: Rob Herring, Krzysztof Kozlowski, Jaehoon Chung, Doug Anderson,
	kernel, linux-mmc, devicetree, linux-arm-kernel,
	linux-samsung-soc

On Mon, 6 Dec 2021 at 15:29, Mårten Lindahl <marten.lindahl@axis.com> wrote:
>
> When running the ARTPEC-8 DWMMC IP version, and a data error interrupt
> comes during a data read transfer, there is no guarantee for the data
> transfer over interrupt (DTO) to come within the specified data timeout.
> This case is handled by the dto_timer handler which will complete the
> request with the comment:
>
>  /*
>   * If DTO interrupt does NOT come in sending data state,
>   * we should notify the driver to terminate current transfer
>   * and report a data timeout to the core.
>   */
>
> But since the ARTPEC-8 DWMMC IP version, supports an extended TMOUT
> register which allows longer timeouts than the non ARTPEC-8 version
> does, waiting for the dto_timer to complete the request in error cases
> may cause the request to take significantly longer time than necessary.
> This is specifically true for the failing steps during tuning of a
> device.
>
> Fix this by completing the request when the error interrupt comes.
>
> Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>

Okay, this change looks a bit inconvenient to move into variant
specific callbacks. So, maybe the "quirks" flag makes sense, after
all. However, I would still look at using callbacks and library
functions, for the part implemented in patch3.

When it comes to the order of the patches in the series, I suggest
flipping things around and making patch2 the final piece. Otherwise
the support for the artpec variant will be broken between patch2 and
patch4, right?

Kind regards
Uffe

> ---
>  drivers/mmc/host/dw_mmc.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 45ea9fd97a6a..d6b76f47b1a2 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -2777,11 +2777,19 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
>                 if (pending & DW_MCI_DATA_ERROR_FLAGS) {
>                         spin_lock(&host->irq_lock);
>
> +                       if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
> +                               del_timer(&host->dto_timer);
> +
>                         /* if there is an error report DATA_ERROR */
>                         mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
>                         host->data_status = pending;
>                         smp_wmb(); /* drain writebuffer */
>                         set_bit(EVENT_DATA_ERROR, &host->pending_events);
> +
> +                       if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
> +                               /* In case of error, we cannot expect a DTO */
> +                               set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
> +
>                         tasklet_schedule(&host->tasklet);
>
>                         spin_unlock(&host->irq_lock);
> --
> 2.20.1
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v2 3/4] mmc: dw_mmc: Add quirk for extended data read timeout
  2021-12-08 14:41   ` Ulf Hansson
@ 2021-12-08 21:04     ` Marten Lindahl
  0 siblings, 0 replies; 12+ messages in thread
From: Marten Lindahl @ 2021-12-08 21:04 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mårten Lindahl, Rob Herring, Krzysztof Kozlowski,
	Jaehoon Chung, Doug Anderson, kernel, linux-mmc, devicetree,
	linux-arm-kernel, linux-samsung-soc

On Wed, Dec 08, 2021 at 03:41:24PM +0100, Ulf Hansson wrote:
> On Mon, 6 Dec 2021 at 15:29, Mårten Lindahl <marten.lindahl@axis.com> wrote:
> >
> > Current dw_mci driver supports a TMOUT register which consists of a 24
> > bit field (TMOUT[31:8]) for the DATA_TIMEOUT. The maximum value of this
> > field is 0xFFFFFF, which with a 200MHz clock will give a full DRTO of:
> >
> > 0xFFFFFF / 200000000 => ~84 ms
> >
> > However, the ARTPEC-8 SoC DWMMC IP version has a TMOUT register with an
> > extended DATA_TIMEOUT field, which supports longer timers for the DRTO.
> > In this version the DATA_TIMEOUT field is split into two, which with the
> > same 200MHz clock as above will allow a maximum timeout of:
> >
> > ((TMOUT[10:8] -1) * 0xFFFFFF + TMOUT[31:11] * 8) / 200000000 => ~587 ms
> >
> > Add a quirk to support this. The quirk is enabled for ARTPEC-8 SoCs.
> >
> > Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
> > ---
> >
> > v2:
> >  - Removed unnecessary comment
> >  - Change 1<<0 to BIT(0)
> >
> >  drivers/mmc/host/dw_mmc-exynos.c |  5 +++++
> >  drivers/mmc/host/dw_mmc.c        | 33 ++++++++++++++++++++++++++++----
> >  drivers/mmc/host/dw_mmc.h        |  6 ++++++
> >  3 files changed, 40 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
> > index 86486e6659de..1b625642c5b4 100644
> > --- a/drivers/mmc/host/dw_mmc-exynos.c
> > +++ b/drivers/mmc/host/dw_mmc-exynos.c
> > @@ -127,6 +127,11 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
> >                                 DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
> >         }
> >
> > +       if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) {
> > +               /* Quirk needed for ARTPEC-8 SoCs */
> > +               host->quirks |= DW_MMC_QUIRK_EXTENDED_TMOUT;
> > +       }
> > +
> >         host->bus_hz /= (priv->ciu_div + 1);
> >
> >         return 0;
> > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > index f2a14a434bef..45ea9fd97a6a 100644
> > --- a/drivers/mmc/host/dw_mmc.c
> > +++ b/drivers/mmc/host/dw_mmc.c
> > @@ -1289,6 +1289,7 @@ static void dw_mci_set_data_timeout(struct dw_mci *host,
> >  {
> >         u32 clk_div, tmout;
> >         u64 tmp;
> > +       unsigned int tmp2;
> >
> >         clk_div = (mci_readl(host, CLKDIV) & 0xFF) * 2;
> >         if (clk_div == 0)
> > @@ -1301,10 +1302,28 @@ static void dw_mci_set_data_timeout(struct dw_mci *host,
> >         tmout = 0xFF; /* Set maximum */
> >
> >         /* TMOUT[31:8] (DATA_TIMEOUT) */
> > -       if (!tmp || tmp > 0xFFFFFF)
> > -               tmout |= (0xFFFFFF << 8);
> > -       else
> > -               tmout |= (tmp & 0xFFFFFF) << 8;
> > +       if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT) {
> 
> Adding an option for dealing with quirks, should be avoided if
> possible. That's because we want to avoid sprinkling common dw_mmc
> code with variant specific code, as it will sooner or later turn into
> a nightmare to maintain.
> 
> In this case, I suggest you look into extending the struct
> dw_mci_drv_data with some new callback (perhaps ->set_data_timeout())
> and then implement it for your variant.
> If that callback is present, it should take precedence over the
> generic dw_mci_set_data_timeout(), if you get what I mean.

Hi Ulf!

Thanks! That's a good idea. I will implement the callback approach
instead of a quirk for this patch. It will be two callbacks; one for the
set_data_timeout(), and one for the set_drto().

> 
> Moreover, if some common dw_mmc code needs to be called from your
> callback, I suggest we make that code available through exported
> dw_mmc library functions instead.
> 
I don't think I need to export anything for this patch.

Kind regards
Mårten

> > +               /*
> > +                * Extended HW timer (max = 0x6FFFFF2):
> > +                * ((TMOUT[10:8] - 1) * 0xFFFFFF + TMOUT[31:11] * 8)
> > +                */
> > +               if (!tmp || tmp > 0x6FFFFF2)
> > +                       tmout |= (0xFFFFFF << 8);
> > +               else {
> > +                       /* TMOUT[10:8] */
> > +                       tmp2 = (((unsigned int)tmp / 0xFFFFFF) + 1) & 0x7;
> > +                       tmout |= tmp2 << 8;
> > +
> > +                       /* TMOUT[31:11] */
> > +                       tmp = tmp - ((tmp2 - 1) * 0xFFFFFF);
> > +                       tmout |= (tmp & 0xFFFFF8) << 8;
> > +               }
> > +       } else {
> > +               if (!tmp || tmp > 0xFFFFFF)
> > +                       tmout |= (0xFFFFFF << 8);
> > +               else
> > +                       tmout |= (tmp & 0xFFFFFF) << 8;
> > +       }
> >
> >         mci_writel(host, TMOUT, tmout);
> >         dev_dbg(host->dev, "timeout_ns: %u => TMOUT[31:8]: 0x%#08x",
> > @@ -2005,9 +2024,15 @@ static void dw_mci_set_drto(struct dw_mci *host)
> >         if (drto_div == 0)
> >                 drto_div = 1;
> >
> > +       if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
> > +               drto_clks = (((drto_clks & 0x7) - 1) * 0xFFFFFF) +
> > +                       ((drto_clks & 0xFFFFF8));
> > +
> >         drto_ms = DIV_ROUND_UP_ULL((u64)MSEC_PER_SEC * drto_clks * drto_div,
> >                                    host->bus_hz);
> >
> > +       dev_dbg(host->dev, "drto_ms: %u\n", drto_ms);
> > +
> >         /* add a bit spare time */
> >         drto_ms += 10;
> >
> > diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> > index 771d5afa3136..3b6510d4a684 100644
> > --- a/drivers/mmc/host/dw_mmc.h
> > +++ b/drivers/mmc/host/dw_mmc.h
> > @@ -118,6 +118,7 @@ struct dw_mci_dma_slave {
> >   * @part_buf: Simple buffer for partial fifo reads/writes.
> >   * @push_data: Pointer to FIFO push function.
> >   * @pull_data: Pointer to FIFO pull function.
> > + * @quirks: Set of quirks that apply to specific versions of the IP.
> >   * @vqmmc_enabled: Status of vqmmc, should be true or false.
> >   * @irq_flags: The flags to be passed to request_irq.
> >   * @irq: The irq value to be passed to request_irq.
> > @@ -223,6 +224,8 @@ struct dw_mci {
> >         void (*push_data)(struct dw_mci *host, void *buf, int cnt);
> >         void (*pull_data)(struct dw_mci *host, void *buf, int cnt);
> >
> > +       u32                     quirks;
> > +
> >         bool                    vqmmc_enabled;
> >         unsigned long           irq_flags; /* IRQ flags */
> >         int                     irq;
> > @@ -274,6 +277,9 @@ struct dw_mci_board {
> >         struct dma_pdata *data;
> >  };
> >
> > +/* Support for longer data read timeout */
> > +#define DW_MMC_QUIRK_EXTENDED_TMOUT            BIT(0)
> > +
> >  #define DW_MMC_240A            0x240a
> >  #define DW_MMC_280A            0x280a
> >
> 
> Kind regards
> Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v2 4/4] mmc: dw_mmc: Do not wait for DTO in case of error
  2021-12-08 14:53   ` Ulf Hansson
@ 2021-12-08 22:01     ` Marten Lindahl
  0 siblings, 0 replies; 12+ messages in thread
From: Marten Lindahl @ 2021-12-08 22:01 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mårten Lindahl, Rob Herring, Krzysztof Kozlowski,
	Jaehoon Chung, Doug Anderson, kernel, linux-mmc, devicetree,
	linux-arm-kernel, linux-samsung-soc

On Wed, Dec 08, 2021 at 03:53:54PM +0100, Ulf Hansson wrote:
> On Mon, 6 Dec 2021 at 15:29, Mårten Lindahl <marten.lindahl@axis.com> wrote:
> >
> > When running the ARTPEC-8 DWMMC IP version, and a data error interrupt
> > comes during a data read transfer, there is no guarantee for the data
> > transfer over interrupt (DTO) to come within the specified data timeout.
> > This case is handled by the dto_timer handler which will complete the
> > request with the comment:
> >
> >  /*
> >   * If DTO interrupt does NOT come in sending data state,
> >   * we should notify the driver to terminate current transfer
> >   * and report a data timeout to the core.
> >   */
> >
> > But since the ARTPEC-8 DWMMC IP version, supports an extended TMOUT
> > register which allows longer timeouts than the non ARTPEC-8 version
> > does, waiting for the dto_timer to complete the request in error cases
> > may cause the request to take significantly longer time than necessary.
> > This is specifically true for the failing steps during tuning of a
> > device.
> >
> > Fix this by completing the request when the error interrupt comes.
> >
> > Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
> 

Hi Ulf!

> Okay, this change looks a bit inconvenient to move into variant
> specific callbacks. So, maybe the "quirks" flag makes sense, after
> all. However, I would still look at using callbacks and library
> functions, for the part implemented in patch3.

Yes, I don't see how this patch can be easily made with callbacks, but
definitely for patch3. So then I move the definition of the quirk from
patch3 to this patch.

> 
> When it comes to the order of the patches in the series, I suggest
> flipping things around and making patch2 the final piece. Otherwise
> the support for the artpec variant will be broken between patch2 and
> patch4, right?

Ok, you mean there may be a risk that the ARTPEC-8 dw_mmc does not work
if the support is enabled in patch2, but patch3 and patch4 is not in
place? That is a good point, but it actually does work quite fine (most
of the time) without the extended timeout function. But it does not use
the full function of the data timeout, and the HW timeout is most often
set to full timeout (0xFFFFFF => 587ms with 200MHz), but the SW timer is
limited to a lower value (0xFFFFFF => 84 + 10 ms with 200MHz).

My reasoning is:
patch1 - dtbindings for ARTPEC-8
patch2 - adding ARTPEC-8 to dw_mmc-exynos
patch3 - implement ARTPEC-8 specific function for data timeout
patch4 - add quirk to abort the extended timeout in case of errors, used
by ARTPEC-8

so, this means patch3 and patch4 depends on patch2, and patch4 depends
on patch3.

Kind regards
Mårten

> 
> Kind regards
> Uffe
> 
> > ---
> >  drivers/mmc/host/dw_mmc.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > index 45ea9fd97a6a..d6b76f47b1a2 100644
> > --- a/drivers/mmc/host/dw_mmc.c
> > +++ b/drivers/mmc/host/dw_mmc.c
> > @@ -2777,11 +2777,19 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
> >                 if (pending & DW_MCI_DATA_ERROR_FLAGS) {
> >                         spin_lock(&host->irq_lock);
> >
> > +                       if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
> > +                               del_timer(&host->dto_timer);
> > +
> >                         /* if there is an error report DATA_ERROR */
> >                         mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
> >                         host->data_status = pending;
> >                         smp_wmb(); /* drain writebuffer */
> >                         set_bit(EVENT_DATA_ERROR, &host->pending_events);
> > +
> > +                       if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
> > +                               /* In case of error, we cannot expect a DTO */
> > +                               set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
> > +
> >                         tasklet_schedule(&host->tasklet);
> >
> >                         spin_unlock(&host->irq_lock);
> > --
> > 2.20.1
> >

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2021-12-08 22:04 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-06 14:29 [PATCH v2 0/4] Add ARTPEC-8 support to DWMMC controller Mårten Lindahl
2021-12-06 14:29 ` [PATCH v2 1/4] dt-bindings: mmc: exynos-dw-mshc: Add support for ARTPEC-8 Mårten Lindahl
2021-12-07  9:40   ` Krzysztof Kozlowski
2021-12-06 14:29 ` [PATCH v2 2/4] mmc: dw_mmc-exynos: " Mårten Lindahl
2021-12-07  9:40   ` Krzysztof Kozlowski
2021-12-06 14:29 ` [PATCH v2 3/4] mmc: dw_mmc: Add quirk for extended data read timeout Mårten Lindahl
2021-12-07  9:41   ` Krzysztof Kozlowski
2021-12-08 14:41   ` Ulf Hansson
2021-12-08 21:04     ` Marten Lindahl
2021-12-06 14:29 ` [PATCH v2 4/4] mmc: dw_mmc: Do not wait for DTO in case of error Mårten Lindahl
2021-12-08 14:53   ` Ulf Hansson
2021-12-08 22:01     ` Marten Lindahl

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).