devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168
@ 2023-01-16 19:43 Doug Brown
  2023-01-16 19:43 ` [PATCH v5 1/8] mmc: sdhci-pxav2: add initial support for PXA168 V1 controller Doug Brown
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Doug Brown @ 2023-01-16 19:43 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter
  Cc: Rob Herring, Krzysztof Kozlowski, linux-mmc, devicetree,
	Doug Brown

This is a revival of an earlier patch series from 2013 to add support
for the PXA168 SDHC controller, with an additional SDIO IRQ errata fix.
It also cleans up the clock naming to be consistent with the existing DT
schema shared with the pxav3 driver (in a backwards-compatible way).

Here is the original patch series this is based on:
https://lore.kernel.org/linux-mmc/1363544206-3671-1-git-send-email-tanmay.upadhyay@einfochips.com/

Note that I left out the platform_specific_completion and clock gating
changes from the original patches. They both seemed controversial, and
don't seem necessary based on my testing. I've been running this code on
a PXA168 for months without any issues.

Changes in v5:
- Fix missing assignment to ret in core clock patch found by test robot

Changes in v4:
- Rebase on latest mmc/next to fix conflict with DT binding

Changes in v3:
- Use OF match data rather than of_match_device and of_device_is_compatible
- Simplify some instances of pdev->dev that could have just been "dev"
- Handle EPROBE_DEFER when getting the clock
- Use devm_clk_get_optional_enabled for the core clock (it's simpler)
- Clear sdio_mrq before calling mmc_request_done
- Small tweaks to devicetree binding requested by Krzysztof

Changes in v2:
- Fix mistakes in devicetree binding
- Use cleaner code for pxav1_readw suggested by Adrian
- Switch to request_done() and irq() for SDIO workaround CMD0 handling

Doug Brown (8):
  mmc: sdhci-pxav2: add initial support for PXA168 V1 controller
  mmc: sdhci-pxav2: enable CONFIG_MMC_SDHCI_IO_ACCESSORS
  mmc: sdhci-pxav2: add register workaround for PXA168 silicon bug
  mmc: sdhci-pxav2: change clock name to match DT bindings
  mmc: sdhci-pxav2: add optional core clock
  mmc: sdhci-pxav2: add SDIO card IRQ workaround for PXA168 V1
    controller
  mmc: sdhci-pxav2: add optional pinctrl for SDIO IRQ workaround
  dt-bindings: mmc: sdhci-pxa: add pxav1

 .../devicetree/bindings/mmc/sdhci-pxa.yaml    |  19 ++-
 drivers/mmc/host/Kconfig                      |   1 +
 drivers/mmc/host/sdhci-pxav2.c                | 154 ++++++++++++++++--
 3 files changed, 160 insertions(+), 14 deletions(-)

-- 
2.34.1


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

* [PATCH v5 1/8] mmc: sdhci-pxav2: add initial support for PXA168 V1 controller
  2023-01-16 19:43 [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Doug Brown
@ 2023-01-16 19:43 ` Doug Brown
  2023-01-16 19:43 ` [PATCH v5 2/8] mmc: sdhci-pxav2: enable CONFIG_MMC_SDHCI_IO_ACCESSORS Doug Brown
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Doug Brown @ 2023-01-16 19:43 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter
  Cc: Rob Herring, Krzysztof Kozlowski, linux-mmc, devicetree,
	Doug Brown

Add a new compatible string for the version 1 controller used in the
PXA168, along with necessary quirks. Use a separate ops struct in
preparation for a silicon bug workaround only necessary on V1.

Signed-off-by: Doug Brown <doug@schmorgal.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/mmc/host/sdhci-pxav2.c | 40 +++++++++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index f18906b5575f..5707d597ecae 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -101,6 +101,24 @@ static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
 	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
 }
 
+struct sdhci_pxa_variant {
+	const struct sdhci_ops *ops;
+	unsigned int extra_quirks;
+};
+
+static const struct sdhci_ops pxav1_sdhci_ops = {
+	.set_clock     = sdhci_set_clock,
+	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
+	.set_bus_width = pxav2_mmc_set_bus_width,
+	.reset         = pxav2_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+static const struct sdhci_pxa_variant __maybe_unused pxav1_variant = {
+	.ops = &pxav1_sdhci_ops,
+	.extra_quirks = SDHCI_QUIRK_NO_BUSY_IRQ | SDHCI_QUIRK_32BIT_DMA_SIZE,
+};
+
 static const struct sdhci_ops pxav2_sdhci_ops = {
 	.set_clock     = sdhci_set_clock,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
@@ -109,11 +127,14 @@ static const struct sdhci_ops pxav2_sdhci_ops = {
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
+static const struct sdhci_pxa_variant pxav2_variant = {
+	.ops = &pxav2_sdhci_ops,
+};
+
 #ifdef CONFIG_OF
 static const struct of_device_id sdhci_pxav2_of_match[] = {
-	{
-		.compatible = "mrvl,pxav2-mmc",
-	},
+	{ .compatible = "mrvl,pxav1-mmc", .data = &pxav1_variant, },
+	{ .compatible = "mrvl,pxav2-mmc", .data = &pxav2_variant, },
 	{},
 };
 MODULE_DEVICE_TABLE(of, sdhci_pxav2_of_match);
@@ -157,7 +178,7 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
 	struct device *dev = &pdev->dev;
 	struct sdhci_host *host = NULL;
-	const struct of_device_id *match;
+	const struct sdhci_pxa_variant *variant;
 
 	int ret;
 	struct clk *clk;
@@ -185,10 +206,12 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 		| SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
 		| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
 
-	match = of_match_device(of_match_ptr(sdhci_pxav2_of_match), &pdev->dev);
-	if (match) {
+	variant = of_device_get_match_data(dev);
+	if (variant)
 		pdata = pxav2_get_mmc_pdata(dev);
-	}
+	else
+		variant = &pxav2_variant;
+
 	if (pdata) {
 		if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
 			/* on-chip device */
@@ -208,7 +231,8 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 			host->mmc->pm_caps |= pdata->pm_caps;
 	}
 
-	host->ops = &pxav2_sdhci_ops;
+	host->quirks |= variant->extra_quirks;
+	host->ops = variant->ops;
 
 	ret = sdhci_add_host(host);
 	if (ret)
-- 
2.34.1


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

* [PATCH v5 2/8] mmc: sdhci-pxav2: enable CONFIG_MMC_SDHCI_IO_ACCESSORS
  2023-01-16 19:43 [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Doug Brown
  2023-01-16 19:43 ` [PATCH v5 1/8] mmc: sdhci-pxav2: add initial support for PXA168 V1 controller Doug Brown
@ 2023-01-16 19:43 ` Doug Brown
  2023-01-16 19:43 ` [PATCH v5 3/8] mmc: sdhci-pxav2: add register workaround for PXA168 silicon bug Doug Brown
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Doug Brown @ 2023-01-16 19:43 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter
  Cc: Rob Herring, Krzysztof Kozlowski, linux-mmc, devicetree,
	Doug Brown

Enable CONFIG_MMC_SDHCI_IO_ACCESSORS for the pxav2 driver. The read_w
callback is needed for a silicon bug workaround in the PXA168.

Signed-off-by: Doug Brown <doug@schmorgal.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/mmc/host/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 5e19a961c34d..b9e9185c86a6 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -360,6 +360,7 @@ config MMC_SDHCI_PXAV2
 	depends on MMC_SDHCI_PLTFM
 	depends on ARCH_MMP || COMPILE_TEST
 	default CPU_PXA910
+	select MMC_SDHCI_IO_ACCESSORS
 	help
 	  This selects the Marvell(R) PXAV2 SD Host Controller.
 	  If you have a PXA9XX platform with SD Host Controller
-- 
2.34.1


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

* [PATCH v5 3/8] mmc: sdhci-pxav2: add register workaround for PXA168 silicon bug
  2023-01-16 19:43 [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Doug Brown
  2023-01-16 19:43 ` [PATCH v5 1/8] mmc: sdhci-pxav2: add initial support for PXA168 V1 controller Doug Brown
  2023-01-16 19:43 ` [PATCH v5 2/8] mmc: sdhci-pxav2: enable CONFIG_MMC_SDHCI_IO_ACCESSORS Doug Brown
@ 2023-01-16 19:43 ` Doug Brown
  2023-01-16 19:43 ` [PATCH v5 4/8] mmc: sdhci-pxav2: change clock name to match DT bindings Doug Brown
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Doug Brown @ 2023-01-16 19:43 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter
  Cc: Rob Herring, Krzysztof Kozlowski, linux-mmc, devicetree,
	Doug Brown

The PXA168 has a documented silicon bug that results in a data abort
exception when accessing the SDHCI_HOST_VERSION register on SDH2 and
SDH4 through a 16-bit read. Implement the workaround described in the
errata, which performs a 32-bit read from a lower address instead. This
is safe to use on all four SDH peripherals.

Signed-off-by: Doug Brown <doug@schmorgal.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/mmc/host/sdhci-pxav2.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 5707d597ecae..5e01dab94426 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -80,6 +80,15 @@ static void pxav2_reset(struct sdhci_host *host, u8 mask)
 	}
 }
 
+static u16 pxav1_readw(struct sdhci_host *host, int reg)
+{
+	/* Workaround for data abort exception on SDH2 and SDH4 on PXA168 */
+	if (reg == SDHCI_HOST_VERSION)
+		return readl(host->ioaddr + SDHCI_HOST_VERSION - 2) >> 16;
+
+	return readw(host->ioaddr + reg);
+}
+
 static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
 {
 	u8 ctrl;
@@ -107,6 +116,7 @@ struct sdhci_pxa_variant {
 };
 
 static const struct sdhci_ops pxav1_sdhci_ops = {
+	.read_w        = pxav1_readw,
 	.set_clock     = sdhci_set_clock,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.set_bus_width = pxav2_mmc_set_bus_width,
-- 
2.34.1


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

* [PATCH v5 4/8] mmc: sdhci-pxav2: change clock name to match DT bindings
  2023-01-16 19:43 [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Doug Brown
                   ` (2 preceding siblings ...)
  2023-01-16 19:43 ` [PATCH v5 3/8] mmc: sdhci-pxav2: add register workaround for PXA168 silicon bug Doug Brown
@ 2023-01-16 19:43 ` Doug Brown
  2023-01-16 19:43 ` [PATCH v5 5/8] mmc: sdhci-pxav2: add optional core clock Doug Brown
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Doug Brown @ 2023-01-16 19:43 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter
  Cc: Rob Herring, Krzysztof Kozlowski, linux-mmc, devicetree,
	Doug Brown

The devicetree bindings for this driver specify that the two allowed
clock names are io and core. Change this driver to look for io, but
allow any name if it fails for backwards compatibility. Follow the same
pattern used in sdhci-pxav3, but add support for EPROBE_DEFER.

Get rid of an unnecessary pdev->dev while we're at it.

Signed-off-by: Doug Brown <doug@schmorgal.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/mmc/host/sdhci-pxav2.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 5e01dab94426..f5c86e1ba734 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -199,16 +199,18 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 
 	pltfm_host = sdhci_priv(host);
 
-	clk = devm_clk_get(dev, "PXA-SDHCLK");
+	clk = devm_clk_get(dev, "io");
+	if (IS_ERR(clk) && PTR_ERR(clk) != -EPROBE_DEFER)
+		clk = devm_clk_get(dev, NULL);
 	if (IS_ERR(clk)) {
-		dev_err(dev, "failed to get io clock\n");
 		ret = PTR_ERR(clk);
+		dev_err_probe(dev, ret, "failed to get io clock\n");
 		goto free;
 	}
 	pltfm_host->clk = clk;
 	ret = clk_prepare_enable(clk);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to enable io clock\n");
+		dev_err(dev, "failed to enable io clock\n");
 		goto free;
 	}
 
-- 
2.34.1


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

* [PATCH v5 5/8] mmc: sdhci-pxav2: add optional core clock
  2023-01-16 19:43 [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Doug Brown
                   ` (3 preceding siblings ...)
  2023-01-16 19:43 ` [PATCH v5 4/8] mmc: sdhci-pxav2: change clock name to match DT bindings Doug Brown
@ 2023-01-16 19:43 ` Doug Brown
  2023-01-17  6:55   ` Adrian Hunter
  2023-01-16 19:43 ` [PATCH v5 6/8] mmc: sdhci-pxav2: add SDIO card IRQ workaround for PXA168 V1 controller Doug Brown
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 11+ messages in thread
From: Doug Brown @ 2023-01-16 19:43 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter
  Cc: Rob Herring, Krzysztof Kozlowski, linux-mmc, devicetree,
	Doug Brown, kernel test robot, Dan Carpenter

Add ability to have an optional core clock just like the pxav3 driver.
The PXA168 needs this because its SDHC controllers have separate core
and io clocks that both need to be enabled. This also correctly matches
the documented devicetree bindings for this driver.

Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: Doug Brown <doug@schmorgal.com>
---
The Reported-by tags above refer to a missing assignment to ret in an
earlier version of this patch. The kernel test robot caught it.

 drivers/mmc/host/sdhci-pxav2.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index f5c86e1ba734..3141901e1558 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -191,7 +191,7 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 	const struct sdhci_pxa_variant *variant;
 
 	int ret;
-	struct clk *clk;
+	struct clk *clk, *clk_core;
 
 	host = sdhci_pltfm_init(pdev, NULL, 0);
 	if (IS_ERR(host))
@@ -214,6 +214,13 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 		goto free;
 	}
 
+	clk_core = devm_clk_get_optional_enabled(dev, "core");
+	if (IS_ERR(clk_core)) {
+		ret = PTR_ERR(clk_core);
+		dev_err_probe(dev, ret, "failed to enable core clock\n");
+		goto disable_clk;
+	}
+
 	host->quirks = SDHCI_QUIRK_BROKEN_ADMA
 		| SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
 		| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
-- 
2.34.1


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

* [PATCH v5 6/8] mmc: sdhci-pxav2: add SDIO card IRQ workaround for PXA168 V1 controller
  2023-01-16 19:43 [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Doug Brown
                   ` (4 preceding siblings ...)
  2023-01-16 19:43 ` [PATCH v5 5/8] mmc: sdhci-pxav2: add optional core clock Doug Brown
@ 2023-01-16 19:43 ` Doug Brown
  2023-01-16 19:44 ` [PATCH v5 7/8] mmc: sdhci-pxav2: add optional pinctrl for SDIO IRQ workaround Doug Brown
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Doug Brown @ 2023-01-16 19:43 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter
  Cc: Rob Herring, Krzysztof Kozlowski, linux-mmc, devicetree,
	Doug Brown

The PXA168 has a documented silicon bug that causes SDIO card IRQs to be
missed. Implement the first half of the suggested workaround, which
involves resetting the data port logic and issuing a dummy CMD0 to
restart the clock.

Signed-off-by: Doug Brown <doug@schmorgal.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/mmc/host/sdhci-pxav2.c | 56 +++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 3141901e1558..3dafffaa0c6e 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -20,6 +20,8 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/mmc.h>
 
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
@@ -41,6 +43,10 @@
 #define MMC_CARD		0x1000
 #define MMC_WIDTH		0x0100
 
+struct sdhci_pxav2_host {
+	struct mmc_request *sdio_mrq;
+};
+
 static void pxav2_reset(struct sdhci_host *host, u8 mask)
 {
 	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
@@ -89,6 +95,52 @@ static u16 pxav1_readw(struct sdhci_host *host, int reg)
 	return readw(host->ioaddr + reg);
 }
 
+static u32 pxav1_irq(struct sdhci_host *host, u32 intmask)
+{
+	struct sdhci_pxav2_host *pxav2_host = sdhci_pltfm_priv(sdhci_priv(host));
+	struct mmc_request *sdio_mrq;
+
+	if (pxav2_host->sdio_mrq && (intmask & SDHCI_INT_CMD_MASK)) {
+		/* The dummy CMD0 for the SDIO workaround just completed */
+		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, SDHCI_INT_STATUS);
+		intmask &= ~SDHCI_INT_CMD_MASK;
+		sdio_mrq = pxav2_host->sdio_mrq;
+		pxav2_host->sdio_mrq = NULL;
+		mmc_request_done(host->mmc, sdio_mrq);
+	}
+
+	return intmask;
+}
+
+static void pxav1_request_done(struct sdhci_host *host, struct mmc_request *mrq)
+{
+	u16 tmp;
+	struct sdhci_pxav2_host *pxav2_host;
+
+	/* If this is an SDIO command, perform errata workaround for silicon bug */
+	if (mrq->cmd && !mrq->cmd->error &&
+	    (mrq->cmd->opcode == SD_IO_RW_DIRECT ||
+	     mrq->cmd->opcode == SD_IO_RW_EXTENDED)) {
+		/* Reset data port */
+		tmp = readw(host->ioaddr + SDHCI_TIMEOUT_CONTROL);
+		tmp |= 0x400;
+		writew(tmp, host->ioaddr + SDHCI_TIMEOUT_CONTROL);
+
+		/* Clock is now stopped, so restart it by sending a dummy CMD0 */
+		pxav2_host = sdhci_pltfm_priv(sdhci_priv(host));
+		pxav2_host->sdio_mrq = mrq;
+		sdhci_writel(host, 0, SDHCI_ARGUMENT);
+		sdhci_writew(host, 0, SDHCI_TRANSFER_MODE);
+		sdhci_writew(host, SDHCI_MAKE_CMD(MMC_GO_IDLE_STATE, SDHCI_CMD_RESP_NONE),
+			     SDHCI_COMMAND);
+
+		/* Don't finish this request until the dummy CMD0 finishes */
+		return;
+	}
+
+	mmc_request_done(host->mmc, mrq);
+}
+
 static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
 {
 	u8 ctrl;
@@ -118,10 +170,12 @@ struct sdhci_pxa_variant {
 static const struct sdhci_ops pxav1_sdhci_ops = {
 	.read_w        = pxav1_readw,
 	.set_clock     = sdhci_set_clock,
+	.irq           = pxav1_irq,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.set_bus_width = pxav2_mmc_set_bus_width,
 	.reset         = pxav2_reset,
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
+	.request_done  = pxav1_request_done,
 };
 
 static const struct sdhci_pxa_variant __maybe_unused pxav1_variant = {
@@ -193,7 +247,7 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 	int ret;
 	struct clk *clk, *clk_core;
 
-	host = sdhci_pltfm_init(pdev, NULL, 0);
+	host = sdhci_pltfm_init(pdev, NULL, sizeof(struct sdhci_pxav2_host));
 	if (IS_ERR(host))
 		return PTR_ERR(host);
 
-- 
2.34.1


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

* [PATCH v5 7/8] mmc: sdhci-pxav2: add optional pinctrl for SDIO IRQ workaround
  2023-01-16 19:43 [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Doug Brown
                   ` (5 preceding siblings ...)
  2023-01-16 19:43 ` [PATCH v5 6/8] mmc: sdhci-pxav2: add SDIO card IRQ workaround for PXA168 V1 controller Doug Brown
@ 2023-01-16 19:44 ` Doug Brown
  2023-01-16 19:44 ` [PATCH v5 8/8] dt-bindings: mmc: sdhci-pxa: add pxav1 Doug Brown
  2023-01-24 12:57 ` [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Ulf Hansson
  8 siblings, 0 replies; 11+ messages in thread
From: Doug Brown @ 2023-01-16 19:44 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter
  Cc: Rob Herring, Krzysztof Kozlowski, linux-mmc, devicetree,
	Doug Brown

The PXA168 errata recommends that the CMD signal should be detached from
the SD bus while performing the dummy CMD0 to restart the clock.
Implement this using pinctrl states.

Signed-off-by: Doug Brown <doug@schmorgal.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/mmc/host/sdhci-pxav2.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 3dafffaa0c6e..fc306eb1f845 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -22,6 +22,7 @@
 #include <linux/of_device.h>
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/mmc.h>
+#include <linux/pinctrl/consumer.h>
 
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
@@ -45,6 +46,9 @@
 
 struct sdhci_pxav2_host {
 	struct mmc_request *sdio_mrq;
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pins_default;
+	struct pinctrl_state *pins_cmd_gpio;
 };
 
 static void pxav2_reset(struct sdhci_host *host, u8 mask)
@@ -104,6 +108,11 @@ static u32 pxav1_irq(struct sdhci_host *host, u32 intmask)
 		/* The dummy CMD0 for the SDIO workaround just completed */
 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, SDHCI_INT_STATUS);
 		intmask &= ~SDHCI_INT_CMD_MASK;
+
+		/* Restore MMC function to CMD pin */
+		if (pxav2_host->pinctrl && pxav2_host->pins_default)
+			pinctrl_select_state(pxav2_host->pinctrl, pxav2_host->pins_default);
+
 		sdio_mrq = pxav2_host->sdio_mrq;
 		pxav2_host->sdio_mrq = NULL;
 		mmc_request_done(host->mmc, sdio_mrq);
@@ -129,6 +138,11 @@ static void pxav1_request_done(struct sdhci_host *host, struct mmc_request *mrq)
 		/* Clock is now stopped, so restart it by sending a dummy CMD0 */
 		pxav2_host = sdhci_pltfm_priv(sdhci_priv(host));
 		pxav2_host->sdio_mrq = mrq;
+
+		/* Set CMD as high output rather than MMC function while we do CMD0 */
+		if (pxav2_host->pinctrl && pxav2_host->pins_cmd_gpio)
+			pinctrl_select_state(pxav2_host->pinctrl, pxav2_host->pins_cmd_gpio);
+
 		sdhci_writel(host, 0, SDHCI_ARGUMENT);
 		sdhci_writew(host, 0, SDHCI_TRANSFER_MODE);
 		sdhci_writew(host, SDHCI_MAKE_CMD(MMC_GO_IDLE_STATE, SDHCI_CMD_RESP_NONE),
@@ -240,6 +254,7 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 {
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+	struct sdhci_pxav2_host *pxav2_host;
 	struct device *dev = &pdev->dev;
 	struct sdhci_host *host = NULL;
 	const struct sdhci_pxa_variant *variant;
@@ -247,11 +262,12 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 	int ret;
 	struct clk *clk, *clk_core;
 
-	host = sdhci_pltfm_init(pdev, NULL, sizeof(struct sdhci_pxav2_host));
+	host = sdhci_pltfm_init(pdev, NULL, sizeof(*pxav2_host));
 	if (IS_ERR(host))
 		return PTR_ERR(host);
 
 	pltfm_host = sdhci_priv(host);
+	pxav2_host = sdhci_pltfm_priv(pltfm_host);
 
 	clk = devm_clk_get(dev, "io");
 	if (IS_ERR(clk) && PTR_ERR(clk) != -EPROBE_DEFER)
@@ -307,6 +323,21 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 	host->quirks |= variant->extra_quirks;
 	host->ops = variant->ops;
 
+	/* Set up optional pinctrl for PXA168 SDIO IRQ fix */
+	pxav2_host->pinctrl = devm_pinctrl_get(dev);
+	if (!IS_ERR(pxav2_host->pinctrl)) {
+		pxav2_host->pins_cmd_gpio = pinctrl_lookup_state(pxav2_host->pinctrl,
+								 "state_cmd_gpio");
+		if (IS_ERR(pxav2_host->pins_cmd_gpio))
+			pxav2_host->pins_cmd_gpio = NULL;
+		pxav2_host->pins_default = pinctrl_lookup_state(pxav2_host->pinctrl,
+								"default");
+		if (IS_ERR(pxav2_host->pins_default))
+			pxav2_host->pins_default = NULL;
+	} else {
+		pxav2_host->pinctrl = NULL;
+	}
+
 	ret = sdhci_add_host(host);
 	if (ret)
 		goto disable_clk;
-- 
2.34.1


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

* [PATCH v5 8/8] dt-bindings: mmc: sdhci-pxa: add pxav1
  2023-01-16 19:43 [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Doug Brown
                   ` (6 preceding siblings ...)
  2023-01-16 19:44 ` [PATCH v5 7/8] mmc: sdhci-pxav2: add optional pinctrl for SDIO IRQ workaround Doug Brown
@ 2023-01-16 19:44 ` Doug Brown
  2023-01-24 12:57 ` [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Ulf Hansson
  8 siblings, 0 replies; 11+ messages in thread
From: Doug Brown @ 2023-01-16 19:44 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter
  Cc: Rob Herring, Krzysztof Kozlowski, linux-mmc, devicetree,
	Doug Brown, Krzysztof Kozlowski

Add a compatible for the pxav1 controller in the PXA168, along with
optional pinctrl properties to use for an errata workaround.

Signed-off-by: Doug Brown <doug@schmorgal.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 .../devicetree/bindings/mmc/sdhci-pxa.yaml    | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-pxa.yaml b/Documentation/devicetree/bindings/mmc/sdhci-pxa.yaml
index 3d46c2525787..09455f9fa8de 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-pxa.yaml
+++ b/Documentation/devicetree/bindings/mmc/sdhci-pxa.yaml
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/mmc/sdhci-pxa.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Marvell PXA SDHCI v2/v3
+title: Marvell PXA SDHCI v1/v2/v3
 
 maintainers:
   - Ulf Hansson <ulf.hansson@linaro.org>
@@ -34,6 +34,7 @@ allOf:
 properties:
   compatible:
     enum:
+      - mrvl,pxav1-mmc
       - mrvl,pxav2-mmc
       - mrvl,pxav3-mmc
       - marvell,armada-380-sdhci
@@ -61,6 +62,22 @@ properties:
       - const: io
       - const: core
 
+  pinctrl-names:
+    description:
+      Optional for supporting PXA168 SDIO IRQ errata to switch CMD pin between
+      SDIO CMD and GPIO mode.
+    items:
+      - const: default
+      - const: state_cmd_gpio
+
+  pinctrl-0:
+    description:
+      Should contain default pinctrl.
+
+  pinctrl-1:
+    description:
+      Should switch CMD pin to GPIO mode as a high output.
+
   mrvl,clk-delay-cycles:
     description: Specify a number of cycles to delay for tuning.
     $ref: /schemas/types.yaml#/definitions/uint32
-- 
2.34.1


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

* Re: [PATCH v5 5/8] mmc: sdhci-pxav2: add optional core clock
  2023-01-16 19:43 ` [PATCH v5 5/8] mmc: sdhci-pxav2: add optional core clock Doug Brown
@ 2023-01-17  6:55   ` Adrian Hunter
  0 siblings, 0 replies; 11+ messages in thread
From: Adrian Hunter @ 2023-01-17  6:55 UTC (permalink / raw)
  To: Doug Brown, Ulf Hansson
  Cc: Rob Herring, Krzysztof Kozlowski, linux-mmc, devicetree,
	kernel test robot, Dan Carpenter

On 16/01/23 21:43, Doug Brown wrote:
> Add ability to have an optional core clock just like the pxav3 driver.
> The PXA168 needs this because its SDHC controllers have separate core
> and io clocks that both need to be enabled. This also correctly matches
> the documented devicetree bindings for this driver.
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Reported-by: Dan Carpenter <error27@gmail.com>
> Signed-off-by: Doug Brown <doug@schmorgal.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
> The Reported-by tags above refer to a missing assignment to ret in an
> earlier version of this patch. The kernel test robot caught it.
> 
>  drivers/mmc/host/sdhci-pxav2.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
> index f5c86e1ba734..3141901e1558 100644
> --- a/drivers/mmc/host/sdhci-pxav2.c
> +++ b/drivers/mmc/host/sdhci-pxav2.c
> @@ -191,7 +191,7 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
>  	const struct sdhci_pxa_variant *variant;
>  
>  	int ret;
> -	struct clk *clk;
> +	struct clk *clk, *clk_core;
>  
>  	host = sdhci_pltfm_init(pdev, NULL, 0);
>  	if (IS_ERR(host))
> @@ -214,6 +214,13 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
>  		goto free;
>  	}
>  
> +	clk_core = devm_clk_get_optional_enabled(dev, "core");
> +	if (IS_ERR(clk_core)) {
> +		ret = PTR_ERR(clk_core);
> +		dev_err_probe(dev, ret, "failed to enable core clock\n");
> +		goto disable_clk;
> +	}
> +
>  	host->quirks = SDHCI_QUIRK_BROKEN_ADMA
>  		| SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
>  		| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;


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

* Re: [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168
  2023-01-16 19:43 [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Doug Brown
                   ` (7 preceding siblings ...)
  2023-01-16 19:44 ` [PATCH v5 8/8] dt-bindings: mmc: sdhci-pxa: add pxav1 Doug Brown
@ 2023-01-24 12:57 ` Ulf Hansson
  8 siblings, 0 replies; 11+ messages in thread
From: Ulf Hansson @ 2023-01-24 12:57 UTC (permalink / raw)
  To: Doug Brown
  Cc: Adrian Hunter, Rob Herring, Krzysztof Kozlowski, linux-mmc,
	devicetree

On Mon, 16 Jan 2023 at 20:44, Doug Brown <doug@schmorgal.com> wrote:
>
> This is a revival of an earlier patch series from 2013 to add support
> for the PXA168 SDHC controller, with an additional SDIO IRQ errata fix.
> It also cleans up the clock naming to be consistent with the existing DT
> schema shared with the pxav3 driver (in a backwards-compatible way).
>
> Here is the original patch series this is based on:
> https://lore.kernel.org/linux-mmc/1363544206-3671-1-git-send-email-tanmay.upadhyay@einfochips.com/
>
> Note that I left out the platform_specific_completion and clock gating
> changes from the original patches. They both seemed controversial, and
> don't seem necessary based on my testing. I've been running this code on
> a PXA168 for months without any issues.
>
> Changes in v5:
> - Fix missing assignment to ret in core clock patch found by test robot
>
> Changes in v4:
> - Rebase on latest mmc/next to fix conflict with DT binding
>
> Changes in v3:
> - Use OF match data rather than of_match_device and of_device_is_compatible
> - Simplify some instances of pdev->dev that could have just been "dev"
> - Handle EPROBE_DEFER when getting the clock
> - Use devm_clk_get_optional_enabled for the core clock (it's simpler)
> - Clear sdio_mrq before calling mmc_request_done
> - Small tweaks to devicetree binding requested by Krzysztof
>
> Changes in v2:
> - Fix mistakes in devicetree binding
> - Use cleaner code for pxav1_readw suggested by Adrian
> - Switch to request_done() and irq() for SDIO workaround CMD0 handling
>
> Doug Brown (8):
>   mmc: sdhci-pxav2: add initial support for PXA168 V1 controller
>   mmc: sdhci-pxav2: enable CONFIG_MMC_SDHCI_IO_ACCESSORS
>   mmc: sdhci-pxav2: add register workaround for PXA168 silicon bug
>   mmc: sdhci-pxav2: change clock name to match DT bindings
>   mmc: sdhci-pxav2: add optional core clock
>   mmc: sdhci-pxav2: add SDIO card IRQ workaround for PXA168 V1
>     controller
>   mmc: sdhci-pxav2: add optional pinctrl for SDIO IRQ workaround
>   dt-bindings: mmc: sdhci-pxa: add pxav1
>
>  .../devicetree/bindings/mmc/sdhci-pxa.yaml    |  19 ++-
>  drivers/mmc/host/Kconfig                      |   1 +
>  drivers/mmc/host/sdhci-pxav2.c                | 154 ++++++++++++++++--
>  3 files changed, 160 insertions(+), 14 deletions(-)
>

Applied for next, thanks!

Kind regards
Uffe

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

end of thread, other threads:[~2023-01-24 12:57 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-01-16 19:43 [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Doug Brown
2023-01-16 19:43 ` [PATCH v5 1/8] mmc: sdhci-pxav2: add initial support for PXA168 V1 controller Doug Brown
2023-01-16 19:43 ` [PATCH v5 2/8] mmc: sdhci-pxav2: enable CONFIG_MMC_SDHCI_IO_ACCESSORS Doug Brown
2023-01-16 19:43 ` [PATCH v5 3/8] mmc: sdhci-pxav2: add register workaround for PXA168 silicon bug Doug Brown
2023-01-16 19:43 ` [PATCH v5 4/8] mmc: sdhci-pxav2: change clock name to match DT bindings Doug Brown
2023-01-16 19:43 ` [PATCH v5 5/8] mmc: sdhci-pxav2: add optional core clock Doug Brown
2023-01-17  6:55   ` Adrian Hunter
2023-01-16 19:43 ` [PATCH v5 6/8] mmc: sdhci-pxav2: add SDIO card IRQ workaround for PXA168 V1 controller Doug Brown
2023-01-16 19:44 ` [PATCH v5 7/8] mmc: sdhci-pxav2: add optional pinctrl for SDIO IRQ workaround Doug Brown
2023-01-16 19:44 ` [PATCH v5 8/8] dt-bindings: mmc: sdhci-pxa: add pxav1 Doug Brown
2023-01-24 12:57 ` [PATCH v5 0/8] mmc: sdhci-pxav2: Add support for PXA168 Ulf Hansson

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