linux-mmc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates
@ 2020-01-13 21:07 Al Cooper
  2020-01-13 21:07 ` [PATCH 1/6] dt-bindings: mmc: brcm,sdhci-brcmstb: Add support for 7216b0 Al Cooper
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Al Cooper @ 2020-01-13 21:07 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Adrian Hunter, Andrew Jeffery,
	bcm-kernel-feedback-list, devicetree, Enrico Weigelt,
	metux IT consult, Faiz Abbas, Florian Fainelli, linux-arm-kernel,
	linux-mmc, Manivannan Sadhasivam, Mark Rutland, Rob Herring,
	Sowjanya Komatineni, Takao Orito, Ulf Hansson, YueHaibing

The latest BRCMSTB SoC's now use a new Arasan controller along
with a custom Broadcom PHY that supports HS200, HS400, SDR104,
HS400E-ES and CQE. This series of commits adds support for these
new features along with a few bug fixes. The 7216 is the first
SoC to have this new hardware.

Al Cooper (6):
  dt-bindings: mmc: brcm,sdhci-brcmstb: Add support for 7216b0
  mmc: sdhci-brcmstb: Add ability to use HS400ES transfer mode
  mmc: sdhci-brcmstb: Fix driver to defer on clk_get defer
  mmc: sdhci-brcmstb: Add shutdown callback
  mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)
  mmc: sdhci-brcmstb: Fix incorrect switch to HS mode

 .../bindings/mmc/brcm,sdhci-brcmstb.txt       |  41 ++-
 drivers/mmc/host/Kconfig                      |   1 +
 drivers/mmc/host/sdhci-brcmstb.c              | 270 +++++++++++++++++-
 3 files changed, 284 insertions(+), 28 deletions(-)

-- 
2.17.1


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

* [PATCH 1/6] dt-bindings: mmc: brcm,sdhci-brcmstb: Add support for 7216b0
  2020-01-13 21:07 [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Al Cooper
@ 2020-01-13 21:07 ` Al Cooper
  2020-01-13 21:07 ` [PATCH 2/6] mmc: sdhci-brcmstb: Add ability to use HS400ES transfer mode Al Cooper
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Al Cooper @ 2020-01-13 21:07 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Adrian Hunter, Andrew Jeffery,
	bcm-kernel-feedback-list, devicetree, Enrico Weigelt,
	metux IT consult, Faiz Abbas, Florian Fainelli, linux-arm-kernel,
	linux-mmc, Manivannan Sadhasivam, Mark Rutland, Rob Herring,
	Sowjanya Komatineni, Takao Orito, Ulf Hansson, YueHaibing

Add 7216b0 with supports CQE, HS400, HS400-ES and SDR104.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 .../bindings/mmc/brcm,sdhci-brcmstb.txt       | 41 +++++++++++++------
 1 file changed, 28 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.txt b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.txt
index 733b64a4d8eb..ae2074184528 100644
--- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.txt
+++ b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.txt
@@ -11,28 +11,43 @@ Required properties:
 - compatible: should be one of the following
   - "brcm,bcm7425-sdhci"
   - "brcm,bcm7445-sdhci"
+  - "brcm,bcm7216-sdhci"
 
 Refer to clocks/clock-bindings.txt for generic clock consumer properties.
 
 Example:
 
-	sdhci@f03e0100 {
-		compatible = "brcm,bcm7425-sdhci";
-		reg = <0xf03e0000 0x100>;
-		interrupts = <0x0 0x26 0x0>;
-		sdhci,auto-cmd12;
-		clocks = <&sw_sdio>;
+	sdhci@84b0000 {
 		sd-uhs-sdr50;
 		sd-uhs-ddr50;
+		sd-uhs-sdr104;
+		sdhci,auto-cmd12;
+		compatible = "brcm,bcm7216-sdhci",
+			   "brcm,bcm7445-sdhci",
+			   "brcm,sdhci-brcmstb";
+		reg = <0x84b0000 0x260 0x84b0300 0x200>;
+		reg-names = "host", "cfg";
+		interrupts = <0x0 0x26 0x4>;
+		interrupt-names = "sdio0_0";
+		clocks = <&scmi_clk 245>;
+		clock-names = "sw_sdio";
 	};
 
-	sdhci@f03e0300 {
+	sdhci@84b1000 {
+		mmc-ddr-1_8v;
+		mmc-hs200-1_8v;
+		mmc-hs400-1_8v;
+		mmc-hs400-enhanced-strobe;
+		supports-cqe;
 		non-removable;
 		bus-width = <0x8>;
-		compatible = "brcm,bcm7425-sdhci";
-		reg = <0xf03e0200 0x100>;
-		interrupts = <0x0 0x27 0x0>;
-		sdhci,auto-cmd12;
-		clocks = <sw_sdio>;
-		mmc-hs200-1_8v;
+		compatible = "brcm,bcm7216-sdhci",
+			   "brcm,bcm7445-sdhci",
+			   "brcm,sdhci-brcmstb";
+		reg = <0x84b1000 0x260 0x84b1300 0x200>;
+		reg-names = "host", "cfg";
+		interrupts = <0x0 0x27 0x4>;
+		interrupt-names = "sdio1_0";
+		clocks = <&scmi_clk 245>;
+		clock-names = "sw_sdio";
 	};
-- 
2.17.1


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

* [PATCH 2/6] mmc: sdhci-brcmstb: Add ability to use HS400ES transfer mode
  2020-01-13 21:07 [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Al Cooper
  2020-01-13 21:07 ` [PATCH 1/6] dt-bindings: mmc: brcm,sdhci-brcmstb: Add support for 7216b0 Al Cooper
@ 2020-01-13 21:07 ` Al Cooper
  2020-01-13 21:07 ` [PATCH 3/6] mmc: sdhci-brcmstb: Fix driver to defer on clk_get defer Al Cooper
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Al Cooper @ 2020-01-13 21:07 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Adrian Hunter, Andrew Jeffery,
	bcm-kernel-feedback-list, devicetree, Enrico Weigelt,
	metux IT consult, Faiz Abbas, Florian Fainelli, linux-arm-kernel,
	linux-mmc, Manivannan Sadhasivam, Mark Rutland, Rob Herring,
	Sowjanya Komatineni, Takao Orito, Ulf Hansson, YueHaibing

The latest eMMC JEDEC specification version 5.1 added a new
transfer mode, HS400 with enhanced strobe (HS400ES). This mode
will be selected if both the host controller and eMMC device
support it. The latest Arasan 5.1 controller in the 7216a0
supports this mode. The "Host Controller Specification" has
not been updated so the controller register bit used to enable
this mode is not specified and varies the with controller vendor.
The Linux SDHCI driver supplies a callback for enabling HS400ES
mode and that callback will be used to supply a routine that
will set the proper bit in the Arasan Vendor register.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/mmc/host/sdhci-brcmstb.c | 97 ++++++++++++++++++++++++++++----
 1 file changed, 86 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 73bb440aaf93..daa89ca232a2 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -9,9 +9,41 @@
 #include <linux/mmc/host.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/bitops.h>
 
 #include "sdhci-pltfm.h"
 
+#define SDHCI_VENDOR 0x78
+#define  SDHCI_VENDOR_ENHANCED_STRB 0x1
+
+#define BRCMSTB_PRIV_FLAGS_NO_64BIT		BIT(0)
+#define BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT	BIT(1)
+
+struct sdhci_brcmstb_priv {
+	void __iomem *cfg_regs;
+};
+
+struct brcmstb_match_priv {
+	void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
+	unsigned int flags;
+};
+
+static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	u32 reg;
+
+	dev_dbg(mmc_dev(mmc), "%s(): Setting HS400-Enhanced-Strobe mode\n",
+		__func__);
+	reg = readl(host->ioaddr + SDHCI_VENDOR);
+	if (ios->enhanced_strobe)
+		reg |= SDHCI_VENDOR_ENHANCED_STRB;
+	else
+		reg &= ~SDHCI_VENDOR_ENHANCED_STRB;
+	writel(reg, host->ioaddr + SDHCI_VENDOR);
+}
+
 static const struct sdhci_ops sdhci_brcmstb_ops = {
 	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
@@ -23,13 +55,40 @@ static const struct sdhci_pltfm_data sdhci_brcmstb_pdata = {
 	.ops = &sdhci_brcmstb_ops,
 };
 
+static const struct brcmstb_match_priv match_priv_7425 = {
+	.flags = BRCMSTB_PRIV_FLAGS_NO_64BIT |
+	BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT,
+};
+
+static const struct brcmstb_match_priv match_priv_7445 = {
+	.flags = BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT,
+};
+
+static const struct brcmstb_match_priv match_priv_7216 = {
+	.hs400es = sdhci_brcmstb_hs400es,
+};
+
+static const struct of_device_id sdhci_brcm_of_match[] = {
+	{ .compatible = "brcm,bcm7425-sdhci", .data = &match_priv_7425 },
+	{ .compatible = "brcm,bcm7445-sdhci", .data = &match_priv_7445 },
+	{ .compatible = "brcm,bcm7216-sdhci", .data = &match_priv_7216 },
+	{},
+};
+
 static int sdhci_brcmstb_probe(struct platform_device *pdev)
 {
-	struct sdhci_host *host;
+	const struct brcmstb_match_priv *match_priv;
 	struct sdhci_pltfm_host *pltfm_host;
+	const struct of_device_id *match;
+	struct sdhci_brcmstb_priv *priv;
+	struct sdhci_host *host;
+	struct resource *iomem;
 	struct clk *clk;
 	int res;
 
+	match = of_match_node(sdhci_brcm_of_match, pdev->dev.of_node);
+	match_priv = match->data;
+
 	clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
@@ -39,36 +98,57 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
 	if (res)
 		return res;
 
-	host = sdhci_pltfm_init(pdev, &sdhci_brcmstb_pdata, 0);
+	host = sdhci_pltfm_init(pdev, &sdhci_brcmstb_pdata,
+				sizeof(struct sdhci_brcmstb_priv));
 	if (IS_ERR(host)) {
 		res = PTR_ERR(host);
 		goto err_clk;
 	}
 
+	pltfm_host = sdhci_priv(host);
+	priv = sdhci_pltfm_priv(pltfm_host);
+
+	/* Map in the non-standard CFG registers */
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	priv->cfg_regs = devm_ioremap_resource(&pdev->dev, iomem);
+	if (IS_ERR(priv->cfg_regs)) {
+		res = PTR_ERR(priv->cfg_regs);
+		goto err;
+	}
+
 	sdhci_get_of_property(pdev);
 	res = mmc_of_parse(host->mmc);
 	if (res)
 		goto err;
 
+	/*
+	 * If the chip has enhanced strobe and it's enabled, add
+	 * callback
+	 */
+	if (match_priv->hs400es &&
+	    (host->mmc->caps2 & MMC_CAP2_HS400_ES))
+		host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es;
+
 	/*
 	 * Supply the existing CAPS, but clear the UHS modes. This
 	 * will allow these modes to be specified by device tree
 	 * properties through mmc_of_parse().
 	 */
 	host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
-	if (of_device_is_compatible(pdev->dev.of_node, "brcm,bcm7425-sdhci"))
+	if (match_priv->flags & BRCMSTB_PRIV_FLAGS_NO_64BIT)
 		host->caps &= ~SDHCI_CAN_64BIT;
 	host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
 	host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
 			SDHCI_SUPPORT_DDR50);
-	host->quirks |= SDHCI_QUIRK_MISSING_CAPS |
-		SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+	host->quirks |= SDHCI_QUIRK_MISSING_CAPS;
+
+	if (match_priv->flags & BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT)
+		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
 	res = sdhci_add_host(host);
 	if (res)
 		goto err;
 
-	pltfm_host = sdhci_priv(host);
 	pltfm_host->clk = clk;
 	return res;
 
@@ -79,11 +159,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
 	return res;
 }
 
-static const struct of_device_id sdhci_brcm_of_match[] = {
-	{ .compatible = "brcm,bcm7425-sdhci" },
-	{ .compatible = "brcm,bcm7445-sdhci" },
-	{},
-};
 MODULE_DEVICE_TABLE(of, sdhci_brcm_of_match);
 
 static struct platform_driver sdhci_brcmstb_driver = {
-- 
2.17.1


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

* [PATCH 3/6] mmc: sdhci-brcmstb: Fix driver to defer on clk_get defer
  2020-01-13 21:07 [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Al Cooper
  2020-01-13 21:07 ` [PATCH 1/6] dt-bindings: mmc: brcm,sdhci-brcmstb: Add support for 7216b0 Al Cooper
  2020-01-13 21:07 ` [PATCH 2/6] mmc: sdhci-brcmstb: Add ability to use HS400ES transfer mode Al Cooper
@ 2020-01-13 21:07 ` Al Cooper
  2020-01-13 21:07 ` [PATCH 4/6] mmc: sdhci-brcmstb: Add shutdown callback Al Cooper
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Al Cooper @ 2020-01-13 21:07 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Adrian Hunter, Andrew Jeffery,
	bcm-kernel-feedback-list, devicetree, Enrico Weigelt,
	metux IT consult, Faiz Abbas, Florian Fainelli, linux-arm-kernel,
	linux-mmc, Manivannan Sadhasivam, Mark Rutland, Rob Herring,
	Sowjanya Komatineni, Takao Orito, Ulf Hansson, YueHaibing

The new SCMI clock protocol driver does not get probed that early in
boot. Brcmstb drivers typically have the following code when getting
a clock:

        priv->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(priv->clk)) {
                dev_err(&pdev->dev, "Clock not found in Device Tree\n");
                priv->clk = NULL;
        }

This commit changes the driver to do what is below.

        priv->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(priv->clk)) {
                if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
                        return -EPROBE_DEFER;
                dev_err(&pdev->dev, "Clock not found in Device Tree\n");
                priv->clk = NULL;
        }

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/mmc/host/sdhci-brcmstb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index daa89ca232a2..218176b79b6a 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -91,6 +91,8 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
 
 	clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
+		if (PTR_ERR(clk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
 		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
 		clk = NULL;
 	}
-- 
2.17.1


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

* [PATCH 4/6] mmc: sdhci-brcmstb: Add shutdown callback
  2020-01-13 21:07 [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Al Cooper
                   ` (2 preceding siblings ...)
  2020-01-13 21:07 ` [PATCH 3/6] mmc: sdhci-brcmstb: Fix driver to defer on clk_get defer Al Cooper
@ 2020-01-13 21:07 ` Al Cooper
  2020-01-13 21:07 ` [PATCH 5/6] mmc: sdhci-brcmstb: Add support for Command Queuing (CQE) Al Cooper
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Al Cooper @ 2020-01-13 21:07 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Adrian Hunter, Andrew Jeffery,
	bcm-kernel-feedback-list, devicetree, Enrico Weigelt,
	metux IT consult, Faiz Abbas, Florian Fainelli, linux-arm-kernel,
	linux-mmc, Manivannan Sadhasivam, Mark Rutland, Rob Herring,
	Sowjanya Komatineni, Takao Orito, Ulf Hansson, YueHaibing

Shutdown controller and disable it's clocks to insure max power
savings in S5 on systems that leave power on.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/mmc/host/sdhci-brcmstb.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 218176b79b6a..7ea426ba5cbc 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -161,6 +161,15 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
 	return res;
 }
 
+static void sdhci_brcmstb_shutdown(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = sdhci_pltfm_unregister(pdev);
+	if (ret)
+		dev_err(&pdev->dev, "failed to shutdown\n");
+}
+
 MODULE_DEVICE_TABLE(of, sdhci_brcm_of_match);
 
 static struct platform_driver sdhci_brcmstb_driver = {
@@ -171,6 +180,7 @@ static struct platform_driver sdhci_brcmstb_driver = {
 	},
 	.probe		= sdhci_brcmstb_probe,
 	.remove		= sdhci_pltfm_unregister,
+	.shutdown	= sdhci_brcmstb_shutdown,
 };
 
 module_platform_driver(sdhci_brcmstb_driver);
-- 
2.17.1


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

* [PATCH 5/6] mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)
  2020-01-13 21:07 [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Al Cooper
                   ` (3 preceding siblings ...)
  2020-01-13 21:07 ` [PATCH 4/6] mmc: sdhci-brcmstb: Add shutdown callback Al Cooper
@ 2020-01-13 21:07 ` Al Cooper
  2020-01-13 21:07 ` [PATCH 6/6] mmc: sdhci-brcmstb: Fix incorrect switch to HS mode Al Cooper
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Al Cooper @ 2020-01-13 21:07 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Adrian Hunter, Andrew Jeffery,
	bcm-kernel-feedback-list, devicetree, Enrico Weigelt,
	metux IT consult, Faiz Abbas, Florian Fainelli, linux-arm-kernel,
	linux-mmc, Manivannan Sadhasivam, Mark Rutland, Rob Herring,
	Sowjanya Komatineni, Takao Orito, Ulf Hansson, YueHaibing

The latest Arasan controller first used in the 7216 now supports
CQE so enable this feature.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/mmc/host/Kconfig         |   1 +
 drivers/mmc/host/sdhci-brcmstb.c | 140 +++++++++++++++++++++++++++++--
 2 files changed, 133 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index d06b2dfe3c95..8897de30959a 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -990,6 +990,7 @@ config MMC_SDHCI_BRCMSTB
 	tristate "Broadcom SDIO/SD/MMC support"
 	depends on ARCH_BRCMSTB || BMIPS_GENERIC
 	depends on MMC_SDHCI_PLTFM
+	select MMC_CQHCI
 	default y
 	help
 	  This selects support for the SDIO/SD/MMC Host Controller on
diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 7ea426ba5cbc..2c4b6e7e3d9a 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -10,8 +10,10 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 
 #include "sdhci-pltfm.h"
+#include "cqhci.h"
 
 #define SDHCI_VENDOR 0x78
 #define  SDHCI_VENDOR_ENHANCED_STRB 0x1
@@ -19,12 +21,16 @@
 #define BRCMSTB_PRIV_FLAGS_NO_64BIT		BIT(0)
 #define BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT	BIT(1)
 
+#define SDHCI_ARASAN_CQE_BASE_ADDR		0x200
+
 struct sdhci_brcmstb_priv {
 	void __iomem *cfg_regs;
+	bool has_cqe;
 };
 
 struct brcmstb_match_priv {
 	void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
+	struct sdhci_ops *ops;
 	unsigned int flags;
 };
 
@@ -44,28 +50,74 @@ static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
 	writel(reg, host->ioaddr + SDHCI_VENDOR);
 }
 
-static const struct sdhci_ops sdhci_brcmstb_ops = {
+static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	u16 clk;
+
+	host->mmc->actual_clock = 0;
+
+	clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+	if (clock == 0)
+		return;
+
+	sdhci_enable_clk(host, clk);
+}
+
+static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc)
+{
+	sdhci_dumpregs(mmc_priv(mmc));
+}
+
+static void sdhci_brcmstb_cqe_enable(struct mmc_host *mmc)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	u32 reg;
+
+	reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
+	while (reg & SDHCI_DATA_AVAILABLE) {
+		sdhci_readl(host, SDHCI_BUFFER);
+		reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
+	}
+
+	sdhci_cqe_enable(mmc);
+}
+
+static const struct cqhci_host_ops sdhci_brcmstb_cqhci_ops = {
+	.enable         = sdhci_brcmstb_cqe_enable,
+	.disable        = sdhci_cqe_disable,
+	.dumpregs       = sdhci_brcmstb_dumpregs,
+};
+
+static struct sdhci_ops sdhci_brcmstb_ops = {
 	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
-static const struct sdhci_pltfm_data sdhci_brcmstb_pdata = {
-	.ops = &sdhci_brcmstb_ops,
+static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
+	.set_clock = sdhci_brcmstb_set_clock,
+	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
-static const struct brcmstb_match_priv match_priv_7425 = {
+static struct brcmstb_match_priv match_priv_7425 = {
 	.flags = BRCMSTB_PRIV_FLAGS_NO_64BIT |
 	BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT,
+	.ops = &sdhci_brcmstb_ops,
 };
 
-static const struct brcmstb_match_priv match_priv_7445 = {
+static struct brcmstb_match_priv match_priv_7445 = {
 	.flags = BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT,
+	.ops = &sdhci_brcmstb_ops,
 };
 
 static const struct brcmstb_match_priv match_priv_7216 = {
 	.hs400es = sdhci_brcmstb_hs400es,
+	.ops = &sdhci_brcmstb_ops_7216,
 };
 
 static const struct of_device_id sdhci_brcm_of_match[] = {
@@ -75,20 +127,85 @@ static const struct of_device_id sdhci_brcm_of_match[] = {
 	{},
 };
 
+static u32 sdhci_brcmstb_cqhci_irq(struct sdhci_host *host, u32 intmask)
+{
+	int cmd_error = 0;
+	int data_error = 0;
+
+	if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
+		return intmask;
+
+	cqhci_irq(host->mmc, intmask, cmd_error, data_error);
+
+	return 0;
+}
+
+static int sdhci_brcmstb_add_host(struct sdhci_host *host,
+				  struct sdhci_brcmstb_priv *priv)
+{
+	struct cqhci_host *cq_host;
+	bool dma64;
+	int ret;
+
+	if (!priv->has_cqe)
+		return sdhci_add_host(host);
+
+	dev_dbg(mmc_dev(host->mmc), "CQE is enabled\n");
+	host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
+	ret = sdhci_setup_host(host);
+	if (ret)
+		return ret;
+
+	cq_host = devm_kzalloc(mmc_dev(host->mmc),
+			       sizeof(*cq_host), GFP_KERNEL);
+	if (!cq_host) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	cq_host->mmio = host->ioaddr + SDHCI_ARASAN_CQE_BASE_ADDR;
+	cq_host->ops = &sdhci_brcmstb_cqhci_ops;
+
+	dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
+	if (dma64) {
+		dev_dbg(mmc_dev(host->mmc), "Using 64 bit DMA\n");
+		cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
+		cq_host->quirks |= CQHCI_QUIRK_SHORT_TXFR_DESC_SZ;
+	}
+
+	ret = cqhci_init(cq_host, host->mmc, dma64);
+	if (ret)
+		goto cleanup;
+
+	ret = __sdhci_add_host(host);
+	if (ret)
+		goto cleanup;
+
+	return 0;
+
+cleanup:
+	sdhci_cleanup_host(host);
+	return ret;
+}
+
 static int sdhci_brcmstb_probe(struct platform_device *pdev)
 {
 	const struct brcmstb_match_priv *match_priv;
+	struct sdhci_pltfm_data brcmstb_pdata;
 	struct sdhci_pltfm_host *pltfm_host;
 	const struct of_device_id *match;
 	struct sdhci_brcmstb_priv *priv;
 	struct sdhci_host *host;
 	struct resource *iomem;
+	bool has_cqe = false;
 	struct clk *clk;
 	int res;
 
 	match = of_match_node(sdhci_brcm_of_match, pdev->dev.of_node);
 	match_priv = match->data;
 
+	dev_dbg(&pdev->dev, "Probe found match for %s\n",  match->compatible);
+
 	clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
 		if (PTR_ERR(clk) == -EPROBE_DEFER)
@@ -100,7 +217,13 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
 	if (res)
 		return res;
 
-	host = sdhci_pltfm_init(pdev, &sdhci_brcmstb_pdata,
+	memset(&brcmstb_pdata, 0, sizeof(brcmstb_pdata));
+	if (device_property_read_bool(&pdev->dev, "supports-cqe")) {
+		has_cqe = true;
+		match_priv->ops->irq = sdhci_brcmstb_cqhci_irq;
+	}
+	brcmstb_pdata.ops = match_priv->ops;
+	host = sdhci_pltfm_init(pdev, &brcmstb_pdata,
 				sizeof(struct sdhci_brcmstb_priv));
 	if (IS_ERR(host)) {
 		res = PTR_ERR(host);
@@ -109,6 +232,7 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
 
 	pltfm_host = sdhci_priv(host);
 	priv = sdhci_pltfm_priv(pltfm_host);
+	priv->has_cqe = has_cqe;
 
 	/* Map in the non-standard CFG registers */
 	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -141,13 +265,13 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
 		host->caps &= ~SDHCI_CAN_64BIT;
 	host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
 	host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
-			SDHCI_SUPPORT_DDR50);
+			 SDHCI_SUPPORT_DDR50);
 	host->quirks |= SDHCI_QUIRK_MISSING_CAPS;
 
 	if (match_priv->flags & BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT)
 		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
-	res = sdhci_add_host(host);
+	res = sdhci_brcmstb_add_host(host, priv);
 	if (res)
 		goto err;
 
-- 
2.17.1


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

* [PATCH 6/6] mmc: sdhci-brcmstb: Fix incorrect switch to HS mode
  2020-01-13 21:07 [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Al Cooper
                   ` (4 preceding siblings ...)
  2020-01-13 21:07 ` [PATCH 5/6] mmc: sdhci-brcmstb: Add support for Command Queuing (CQE) Al Cooper
@ 2020-01-13 21:07 ` Al Cooper
  2020-01-20  8:26 ` [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Adrian Hunter
  2020-01-20 11:25 ` Ulf Hansson
  7 siblings, 0 replies; 9+ messages in thread
From: Al Cooper @ 2020-01-13 21:07 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Adrian Hunter, Andrew Jeffery,
	bcm-kernel-feedback-list, devicetree, Enrico Weigelt,
	metux IT consult, Faiz Abbas, Florian Fainelli, linux-arm-kernel,
	linux-mmc, Manivannan Sadhasivam, Mark Rutland, Rob Herring,
	Sowjanya Komatineni, Takao Orito, Ulf Hansson, YueHaibing

When switching from any MMC speed mode that requires 1.8v
(HS200, HS400 and HS400ES) to High Speed (HS) mode, the system
ends up configured for SDR12 with a 50MHz clock which is an illegal
mode.

This happens because the SDHCI_CTRL_VDD_180 bit in the
SDHCI_HOST_CONTROL2 register is left set and when this bit is
set, the speed mode is controlled by the SDHCI_CTRL_UHS field
in the SDHCI_HOST_CONTROL2 register. The SDHCI_CTRL_UHS field
will end up being set to 0 (SDR12) by sdhci_set_uhs_signaling()
because there is no UHS mode being set.

The fix is to change sdhci_set_uhs_signaling() to set the
SDHCI_CTRL_UHS field to SDR25 (which is the same as HS) for
any switch to HS mode.

This was found on a new eMMC controller that does strict checking
of the speed mode and the corresponding clock rate. It caused the
switch to HS400 mode to fail because part of the sequence to switch
to HS400 requires a switch from HS200 to HS before going to HS400.

This issue was previously fixed by commit c894e33ddc191 ("mmc: sdhci:
Fix incorrect switch to HS mode") and later removed by commit
07bcc411567c ("Revert \"mmc: sdhci: Fix incorrect switch to HS mode\"")
because it caused failures with some SD cards on AM65X systems. The
fix will now be done in a platform specific callback instead of
common sdhci code.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
Suggested-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/mmc/host/sdhci-brcmstb.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 2c4b6e7e3d9a..ad01f6451a95 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -65,6 +65,35 @@ static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
 	sdhci_enable_clk(host, clk);
 }
 
+static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
+					    unsigned int timing)
+{
+	u16 ctrl_2;
+
+	dev_dbg(mmc_dev(host->mmc), "%s: Setting UHS signaling for %d timing\n",
+		__func__, timing);
+	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	/* Select Bus Speed Mode for host */
+	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+	if ((timing == MMC_TIMING_MMC_HS200) ||
+	    (timing == MMC_TIMING_UHS_SDR104))
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
+	else if (timing == MMC_TIMING_UHS_SDR12)
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
+	else if (timing == MMC_TIMING_SD_HS ||
+		 timing == MMC_TIMING_MMC_HS ||
+		 timing == MMC_TIMING_UHS_SDR25)
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
+	else if (timing == MMC_TIMING_UHS_SDR50)
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
+	else if ((timing == MMC_TIMING_UHS_DDR50) ||
+		 (timing == MMC_TIMING_MMC_DDR52))
+		ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
+	else if (timing == MMC_TIMING_MMC_HS400)
+		ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */
+	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+}
+
 static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc)
 {
 	sdhci_dumpregs(mmc_priv(mmc));
@@ -101,7 +130,7 @@ static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
 	.set_clock = sdhci_brcmstb_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
-	.set_uhs_signaling = sdhci_set_uhs_signaling,
+	.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
 };
 
 static struct brcmstb_match_priv match_priv_7425 = {
-- 
2.17.1


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

* Re: [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates
  2020-01-13 21:07 [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Al Cooper
                   ` (5 preceding siblings ...)
  2020-01-13 21:07 ` [PATCH 6/6] mmc: sdhci-brcmstb: Fix incorrect switch to HS mode Al Cooper
@ 2020-01-20  8:26 ` Adrian Hunter
  2020-01-20 11:25 ` Ulf Hansson
  7 siblings, 0 replies; 9+ messages in thread
From: Adrian Hunter @ 2020-01-20  8:26 UTC (permalink / raw)
  To: Al Cooper, linux-kernel
  Cc: Andrew Jeffery, bcm-kernel-feedback-list, devicetree,
	Enrico Weigelt, metux IT consult, Faiz Abbas, Florian Fainelli,
	linux-arm-kernel, linux-mmc, Manivannan Sadhasivam, Mark Rutland,
	Rob Herring, Sowjanya Komatineni, Takao Orito, Ulf Hansson,
	YueHaibing

On 13/01/20 11:07 pm, Al Cooper wrote:
> The latest BRCMSTB SoC's now use a new Arasan controller along
> with a custom Broadcom PHY that supports HS200, HS400, SDR104,
> HS400E-ES and CQE. This series of commits adds support for these
> new features along with a few bug fixes. The 7216 is the first
> SoC to have this new hardware.
> 
> Al Cooper (6):
>   dt-bindings: mmc: brcm,sdhci-brcmstb: Add support for 7216b0
>   mmc: sdhci-brcmstb: Add ability to use HS400ES transfer mode
>   mmc: sdhci-brcmstb: Fix driver to defer on clk_get defer
>   mmc: sdhci-brcmstb: Add shutdown callback
>   mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)
>   mmc: sdhci-brcmstb: Fix incorrect switch to HS mode

For patches 2-5

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

> 
>  .../bindings/mmc/brcm,sdhci-brcmstb.txt       |  41 ++-
>  drivers/mmc/host/Kconfig                      |   1 +
>  drivers/mmc/host/sdhci-brcmstb.c              | 270 +++++++++++++++++-
>  3 files changed, 284 insertions(+), 28 deletions(-)
> 


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

* Re: [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates
  2020-01-13 21:07 [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Al Cooper
                   ` (6 preceding siblings ...)
  2020-01-20  8:26 ` [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Adrian Hunter
@ 2020-01-20 11:25 ` Ulf Hansson
  7 siblings, 0 replies; 9+ messages in thread
From: Ulf Hansson @ 2020-01-20 11:25 UTC (permalink / raw)
  To: Al Cooper
  Cc: Linux Kernel Mailing List, Adrian Hunter, Andrew Jeffery,
	BCM Kernel Feedback, DTML, Enrico Weigelt, metux IT consult,
	Faiz Abbas, Florian Fainelli, Linux ARM, linux-mmc,
	Manivannan Sadhasivam, Mark Rutland, Rob Herring,
	Sowjanya Komatineni, Takao Orito, YueHaibing

On Mon, 13 Jan 2020 at 22:07, Al Cooper <alcooperx@gmail.com> wrote:
>
> The latest BRCMSTB SoC's now use a new Arasan controller along
> with a custom Broadcom PHY that supports HS200, HS400, SDR104,
> HS400E-ES and CQE. This series of commits adds support for these
> new features along with a few bug fixes. The 7216 is the first
> SoC to have this new hardware.
>
> Al Cooper (6):
>   dt-bindings: mmc: brcm,sdhci-brcmstb: Add support for 7216b0
>   mmc: sdhci-brcmstb: Add ability to use HS400ES transfer mode
>   mmc: sdhci-brcmstb: Fix driver to defer on clk_get defer
>   mmc: sdhci-brcmstb: Add shutdown callback
>   mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)
>   mmc: sdhci-brcmstb: Fix incorrect switch to HS mode
>
>  .../bindings/mmc/brcm,sdhci-brcmstb.txt       |  41 ++-
>  drivers/mmc/host/Kconfig                      |   1 +
>  drivers/mmc/host/sdhci-brcmstb.c              | 270 +++++++++++++++++-
>  3 files changed, 284 insertions(+), 28 deletions(-)
>
> --
> 2.17.1
>

Applied for next, thanks!

Kind regards
Uffe

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

end of thread, other threads:[~2020-01-20 11:26 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-13 21:07 [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Al Cooper
2020-01-13 21:07 ` [PATCH 1/6] dt-bindings: mmc: brcm,sdhci-brcmstb: Add support for 7216b0 Al Cooper
2020-01-13 21:07 ` [PATCH 2/6] mmc: sdhci-brcmstb: Add ability to use HS400ES transfer mode Al Cooper
2020-01-13 21:07 ` [PATCH 3/6] mmc: sdhci-brcmstb: Fix driver to defer on clk_get defer Al Cooper
2020-01-13 21:07 ` [PATCH 4/6] mmc: sdhci-brcmstb: Add shutdown callback Al Cooper
2020-01-13 21:07 ` [PATCH 5/6] mmc: sdhci-brcmstb: Add support for Command Queuing (CQE) Al Cooper
2020-01-13 21:07 ` [PATCH 6/6] mmc: sdhci-brcmstb: Fix incorrect switch to HS mode Al Cooper
2020-01-20  8:26 ` [PATCH 0/6] mmc: sdhci-brcmstb: Driver updates Adrian Hunter
2020-01-20 11:25 ` 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).