Skip to content

Commit 40f16f0

Browse files
storulfpelwell
authored andcommitted
mmc: brcmstb: add support for BCM2712
BCM2712 uses the SDIO CFG register block present on other STB chips. Add plumbing for the BCM2712-specific functions. mmc: brcmstb: override card presence if broken-cd is set Not just if the card is declared as nonremovable. mmc: sdhci-brcmstb: only use the delay line PHY for tuneable speeds The MMC core has a 200MHz core clock which allows the use of DDR50 and below without incremental phase tuning. SDR50/SDR104 and the EMMC HS200 speeds require tuning. Signed-off-by: Jonathan Bell <[email protected]> drivers: mmc: sdhci-brcmstb: fix usage of SD_PIN_SEL on BCM2712 The SDIO_CFG register SD_PIN_SEL conflates two settings - whether eMMC HS or SD UHS timings are applied to the interface, and whether or not the card-detect line is functional. SD_PIN_SEL can only be changed when the SD clock isn't running, so add a bcm2712-specific clock setup. Toggling SD_PIN_SEL at runtime means the integrated card-detect feature can't be used, so this controller needs a cd-gpios property. Also fix conditionals for usage of the delay-line PHY - no-1-8-v will imply no bits set in hsemmc_mask or uhs_mask, so remove it. Signed-off-by: Jonathan Bell <[email protected]> drivers: sdhci-brcmstb: set CQE timer clock frequency CQHCI keeps track of tags in flight with internal timers, so the clock frequency driving the timer needs to be specified. The config registers default to 0 (100kHz) which means timeouts will be significantly shorter than they should be. Assume the timer clock comes from the controller base clock. Signed-off-by: Jonathan Bell <[email protected]>
1 parent 85a3b63 commit 40f16f0

File tree

1 file changed

+67
-4
lines changed

1 file changed

+67
-4
lines changed

drivers/mmc/host/sdhci-brcmstb.c

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@
3838
#define SDIO_CFG_OP_DLY_DEFAULT 0x80000003
3939
#define SDIO_CFG_CQ_CAPABILITY 0x4c
4040
#define SDIO_CFG_CQ_CAPABILITY_FMUL GENMASK(13, 12)
41+
#define SDIO_CFG_CQ_CAPABILITY_FMUL_SHIFT 12
4142
#define SDIO_CFG_SD_PIN_SEL 0x44
43+
#define SDIO_CFG_SD_PIN_SEL_MASK 0x3
44+
#define SDIO_CFG_SD_PIN_SEL_SD BIT(1)
45+
#define SDIO_CFG_SD_PIN_SEL_MMC BIT(0)
4246
#define SDIO_CFG_V1_SD_PIN_SEL 0x54
4347
#define SDIO_CFG_PHY_SW_MODE_0_RX_CTRL 0x7C
4448
#define SDIO_CFG_MAX_50MHZ_MODE 0x1ac
@@ -222,6 +226,42 @@ static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
222226
writel(reg, host->ioaddr + SDHCI_VENDOR);
223227
}
224228

229+
static void sdhci_bcm2712_set_clock(struct sdhci_host *host, unsigned int clock)
230+
{
231+
u16 clk;
232+
u32 reg;
233+
bool is_emmc_rate = false;
234+
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
235+
struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
236+
237+
host->mmc->actual_clock = 0;
238+
239+
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
240+
241+
switch (host->mmc->ios.timing) {
242+
case MMC_TIMING_MMC_HS400:
243+
case MMC_TIMING_MMC_HS200:
244+
case MMC_TIMING_MMC_DDR52:
245+
case MMC_TIMING_MMC_HS:
246+
is_emmc_rate = true;
247+
break;
248+
}
249+
250+
reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
251+
reg &= ~SDIO_CFG_SD_PIN_SEL_MASK;
252+
if (is_emmc_rate)
253+
reg |= SDIO_CFG_SD_PIN_SEL_MMC;
254+
else
255+
reg |= SDIO_CFG_SD_PIN_SEL_SD;
256+
writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
257+
258+
if (clock == 0)
259+
return;
260+
261+
clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
262+
sdhci_enable_clk(host, clk);
263+
}
264+
225265
static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
226266
{
227267
u16 clk;
@@ -237,6 +277,17 @@ static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
237277
sdhci_enable_clk(host, clk);
238278
}
239279

280+
static void sdhci_brcmstb_set_power(struct sdhci_host *host, unsigned char mode,
281+
unsigned short vdd)
282+
{
283+
if (!IS_ERR(host->mmc->supply.vmmc)) {
284+
struct mmc_host *mmc = host->mmc;
285+
286+
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
287+
}
288+
sdhci_set_power_noreg(host, mode, vdd);
289+
}
290+
240291
static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
241292
unsigned int timing)
242293
{
@@ -285,12 +336,16 @@ static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
285336
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
286337
struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
287338
u32 reg;
339+
u32 uhs_mask = (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104);
340+
u32 hsemmc_mask = (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS200_1_2V_SDR |
341+
MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V);
342+
u32 base_clk_mhz;
288343

289344
/*
290345
* If we support a speed that requires tuning,
291346
* then select the delay line PHY as the clock source.
292347
*/
293-
if ((host->mmc->caps & MMC_CAP_UHS_I_SDR_MASK) || (host->mmc->caps2 & MMC_CAP_HSE_MASK)) {
348+
if ((host->mmc->caps & uhs_mask) || (host->mmc->caps2 & hsemmc_mask)) {
294349
reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
295350
reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE;
296351
reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE;
@@ -307,6 +362,11 @@ static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
307362
reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN;
308363
writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
309364
}
365+
366+
/* Guesstimate the timer frequency (controller base clock) */
367+
base_clk_mhz = max_t(u32, clk_get_rate(pltfm_host->clk) / (1000 * 1000), 1);
368+
reg = (3 << SDIO_CFG_CQ_CAPABILITY_FMUL_SHIFT) | base_clk_mhz;
369+
writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CQ_CAPABILITY);
310370
}
311371

312372
static void sdhci_brcmstb_set_72116_uhs_signaling(struct sdhci_host *host, unsigned int timing)
@@ -374,8 +434,8 @@ static struct sdhci_ops sdhci_brcmstb_ops = {
374434
};
375435

376436
static struct sdhci_ops sdhci_brcmstb_ops_2712 = {
377-
.set_clock = sdhci_set_clock,
378-
.set_power = sdhci_set_power_and_bus_voltage,
437+
.set_clock = sdhci_bcm2712_set_clock,
438+
.set_power = sdhci_brcmstb_set_power,
379439
.set_bus_width = sdhci_set_bus_width,
380440
.reset = brcmstb_reset,
381441
.set_uhs_signaling = sdhci_set_uhs_signaling,
@@ -403,6 +463,8 @@ static struct sdhci_ops sdhci_brcmstb_ops_74165b0 = {
403463
};
404464

405465
static const struct brcmstb_match_priv match_priv_2712 = {
466+
.flags = BRCMSTB_MATCH_FLAGS_USE_CARD_BUSY,
467+
.hs400es = sdhci_brcmstb_hs400es,
406468
.cfginit = sdhci_brcmstb_cfginit_2712,
407469
.ops = &sdhci_brcmstb_ops_2712,
408470
};
@@ -546,6 +608,8 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
546608
return PTR_ERR(host);
547609

548610
pltfm_host = sdhci_priv(host);
611+
pltfm_host->clk = clk;
612+
549613
priv = sdhci_pltfm_priv(pltfm_host);
550614
priv->match_priv = match->data;
551615
cqe = 0;
@@ -643,7 +707,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
643707
if (res)
644708
goto err;
645709

646-
pltfm_host->clk = clk;
647710
return res;
648711

649712
err:

0 commit comments

Comments
 (0)