Commit fe86da36 authored by Kamal Dasu's avatar Kamal Dasu Committed by Ulf Hansson
Browse files

mmc: sdhci-brcmstb: add new sdhci reset sequence for brcm 74165b0



74165b0 shall use a new sdio controller core version which
requires a different reset sequence. For core reset we use
sdhci_reset. For CMD and/or DATA reset added a new function
to also enable SDHCI clocks SDHCI_CLOCK_CARD_EN
SDHCI_CLOCK_INT_EN along with the SDHCI_RESET_CMD and/or
SDHCI_RESET_DATA fields.

Signed-off-by: default avatarKamal Dasu <kdasu@broadcom.com>
Acked-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Link: https://lore.kernel.org/r/20240103222338.31447-3-kamal.dasu@broadcom.com


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 0a8d397c
Loading
Loading
Loading
Loading
+64 −5
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
 */

#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/mmc/host.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -44,8 +45,13 @@ struct brcmstb_match_priv {

static inline void enable_clock_gating(struct sdhci_host *host)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
	u32 reg;

	if (!(priv->flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK))
		return;

	reg = sdhci_readl(host, SDHCI_VENDOR);
	reg |= SDHCI_VENDOR_GATE_SDCLK_EN;
	sdhci_writel(host, reg, SDHCI_VENDOR);
@@ -53,13 +59,52 @@ static inline void enable_clock_gating(struct sdhci_host *host)

static void brcmstb_reset(struct sdhci_host *host, u8 mask)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);

	sdhci_and_cqhci_reset(host, mask);

	/* Reset will clear this, so re-enable it */
	if (priv->flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK)
	enable_clock_gating(host);
}

static void brcmstb_sdhci_reset_cmd_data(struct sdhci_host *host, u8 mask)
{
	u32 new_mask = (mask &  (SDHCI_RESET_CMD | SDHCI_RESET_DATA)) << 24;
	int ret;
	u32 reg;

	/*
	 * SDHCI_CLOCK_CONTROL register CARD_EN and CLOCK_INT_EN bits shall
	 * be set along with SOFTWARE_RESET register RESET_CMD or RESET_DATA
	 * bits, hence access SDHCI_CLOCK_CONTROL register as 32-bit register
	 */
	new_mask |= SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN;
	reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
	sdhci_writel(host, reg | new_mask, SDHCI_CLOCK_CONTROL);

	reg = sdhci_readb(host, SDHCI_SOFTWARE_RESET);

	ret = read_poll_timeout_atomic(sdhci_readb, reg, !(reg & mask),
				       10, 10000, false,
				       host, SDHCI_SOFTWARE_RESET);

	if (ret) {
		pr_err("%s: Reset 0x%x never completed.\n",
		       mmc_hostname(host->mmc), (int)mask);
		sdhci_err_stats_inc(host, CTRL_TIMEOUT);
		sdhci_dumpregs(host);
	}
}

static void brcmstb_reset_74165b0(struct sdhci_host *host, u8 mask)
{
	/* take care of RESET_ALL as usual */
	if (mask & SDHCI_RESET_ALL)
		sdhci_and_cqhci_reset(host, SDHCI_RESET_ALL);

	/* cmd and/or data treated differently on this core */
	if (mask & (SDHCI_RESET_CMD | SDHCI_RESET_DATA))
		brcmstb_sdhci_reset_cmd_data(host, mask);

	/* Reset will clear this, so re-enable it */
	enable_clock_gating(host);
}

@@ -162,6 +207,13 @@ static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
	.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
};

static struct sdhci_ops sdhci_brcmstb_ops_74165b0 = {
	.set_clock = sdhci_brcmstb_set_clock,
	.set_bus_width = sdhci_set_bus_width,
	.reset = brcmstb_reset_74165b0,
	.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
};

static struct brcmstb_match_priv match_priv_7425 = {
	.flags = BRCMSTB_MATCH_FLAGS_NO_64BIT |
	BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT,
@@ -179,10 +231,17 @@ static const struct brcmstb_match_priv match_priv_7216 = {
	.ops = &sdhci_brcmstb_ops_7216,
};

static struct brcmstb_match_priv match_priv_74165b0 = {
	.flags = BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE,
	.hs400es = sdhci_brcmstb_hs400es,
	.ops = &sdhci_brcmstb_ops_74165b0,
};

static const struct of_device_id __maybe_unused 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 },
	{ .compatible = "brcm,bcm74165b0-sdhci", .data = &match_priv_74165b0 },
	{},
};