Skip to content

Commit 6bcc55f

Browse files
alcooperUlf Hansson
authored andcommitted
mmc: sdhci-brcmstb: Enable Clock Gating to save power
Enabling this feature will allow the controller to stop the bus clock when the bus is idle. The feature is not part of the standard and is unique to newer Arasan cores and is enabled with a bit in a vendor specific register. This feature will only be enabled for non-removable devices because they don't switch the voltage and clock gating breaks SD Card volatge switching. Signed-off-by: Al Cooper <alcooperx@gmail.com> Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com> Acked-by: Florian Fainelli <f.fainelli@gmail.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> Link: https://lore.kernel.org/r/20220427180853.35970-3-kdasu.kdev@gmail.com Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent f3a70f9 commit 6bcc55f

1 file changed

Lines changed: 34 additions & 1 deletion

File tree

drivers/mmc/host/sdhci-brcmstb.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@
1717

1818
#define SDHCI_VENDOR 0x78
1919
#define SDHCI_VENDOR_ENHANCED_STRB 0x1
20+
#define SDHCI_VENDOR_GATE_SDCLK_EN 0x2
2021

2122
#define BRCMSTB_MATCH_FLAGS_NO_64BIT BIT(0)
2223
#define BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT BIT(1)
24+
#define BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE BIT(2)
2325

2426
#define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0)
27+
#define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1)
2528

2629
#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
2730

@@ -36,6 +39,27 @@ struct brcmstb_match_priv {
3639
const unsigned int flags;
3740
};
3841

42+
static inline void enable_clock_gating(struct sdhci_host *host)
43+
{
44+
u32 reg;
45+
46+
reg = sdhci_readl(host, SDHCI_VENDOR);
47+
reg |= SDHCI_VENDOR_GATE_SDCLK_EN;
48+
sdhci_writel(host, reg, SDHCI_VENDOR);
49+
}
50+
51+
void brcmstb_reset(struct sdhci_host *host, u8 mask)
52+
{
53+
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
54+
struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
55+
56+
sdhci_reset(host, mask);
57+
58+
/* Reset will clear this, so re-enable it */
59+
if (priv->flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK)
60+
enable_clock_gating(host);
61+
}
62+
3963
static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
4064
{
4165
struct sdhci_host *host = mmc_priv(mmc);
@@ -131,7 +155,7 @@ static struct sdhci_ops sdhci_brcmstb_ops = {
131155
static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
132156
.set_clock = sdhci_brcmstb_set_clock,
133157
.set_bus_width = sdhci_set_bus_width,
134-
.reset = sdhci_reset,
158+
.reset = brcmstb_reset,
135159
.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
136160
};
137161

@@ -147,6 +171,7 @@ static struct brcmstb_match_priv match_priv_7445 = {
147171
};
148172

149173
static const struct brcmstb_match_priv match_priv_7216 = {
174+
.flags = BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE,
150175
.hs400es = sdhci_brcmstb_hs400es,
151176
.ops = &sdhci_brcmstb_ops_7216,
152177
};
@@ -273,6 +298,14 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
273298
if (res)
274299
goto err;
275300

301+
/*
302+
* Automatic clock gating does not work for SD cards that may
303+
* voltage switch so only enable it for non-removable devices.
304+
*/
305+
if ((match_priv->flags & BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE) &&
306+
(host->mmc->caps & MMC_CAP_NONREMOVABLE))
307+
priv->flags |= BRCMSTB_PRIV_FLAGS_GATE_CLOCK;
308+
276309
/*
277310
* If the chip has enhanced strobe and it's enabled, add
278311
* callback

0 commit comments

Comments
 (0)