Skip to content

SDHCI vs EMMC on Pi 5 #5937

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions arch/arm/boot/dts/broadcom/bcm2712-rpi-5-b.dts
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { };
sd-uhs-sdr50;
sd-uhs-ddr50;
sd-uhs-sdr104;
//broken-cd;
cd-gpios = <&gio_aon 5 GPIO_ACTIVE_LOW>;
//no-1-8-v;
status = "okay";
};
Expand Down Expand Up @@ -396,7 +396,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { };
};

emmc_sd_pulls: emmc_sd_pulls {
function = "emmc_dat0", "emmc_dat1", "emmc_dat2", "emmc_dat3";
pins = "emmc_cmd", "emmc_dat0", "emmc_dat1", "emmc_dat2", "emmc_dat3";
bias-pull-up;
};
};
Expand Down
61 changes: 43 additions & 18 deletions drivers/mmc/host/sdhci-brcmstb.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@

#define SDIO_CFG_SD_PIN_SEL 0x44
#define SDIO_CFG_SD_PIN_SEL_MASK 0x3
#define SDIO_CFG_SD_PIN_SEL_CARD BIT(1)
#define SDIO_CFG_SD_PIN_SEL_SD BIT(1)
#define SDIO_CFG_SD_PIN_SEL_MMC BIT(0)

#define SDIO_CFG_MAX_50MHZ_MODE 0x1ac
#define SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE BIT(31)
Expand Down Expand Up @@ -102,6 +103,42 @@ static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
writel(reg, host->ioaddr + SDHCI_VENDOR);
}

static void sdhci_bcm2712_set_clock(struct sdhci_host *host, unsigned int clock)
{
u16 clk;
u32 reg;
bool is_emmc_rate = false;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);

host->mmc->actual_clock = 0;

sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);

switch (host->mmc->ios.timing) {
case MMC_TIMING_MMC_HS400:
case MMC_TIMING_MMC_HS200:
case MMC_TIMING_MMC_DDR52:
case MMC_TIMING_MMC_HS:
is_emmc_rate = true;
break;
}

reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
reg &= ~SDIO_CFG_SD_PIN_SEL_MASK;
if (is_emmc_rate)
reg |= SDIO_CFG_SD_PIN_SEL_MMC;
else
reg |= SDIO_CFG_SD_PIN_SEL_SD;
writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);

if (clock == 0)
return;

clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
sdhci_enable_clk(host, clk);
}

static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
{
u16 clk;
Expand Down Expand Up @@ -161,22 +198,16 @@ static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
bool want_dll = false;
u32 uhs_mask = (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104);
u32 hsemmc_mask = (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS200_1_2V_SDR |
MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V);
u32 reg;

if (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)) {
if((host->mmc->caps & uhs_mask) || (host->mmc->caps2 & hsemmc_mask))
want_dll = true;
}

/*
* If we want a speed that requires tuning,
* then select the delay line PHY as the clock source.
*/
if (want_dll) {
* If we support a speed that requires tuning,
* then select the delay line PHY as the clock source.
*/
if ((host->mmc->caps & uhs_mask) || (host->mmc->caps2 & hsemmc_mask)) {
reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE;
reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE;
Expand All @@ -190,12 +221,6 @@ static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV;
reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN;
writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
} else {
/* Enable card detection line */
reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
reg &= ~SDIO_CFG_SD_PIN_SEL_MASK;
reg |= SDIO_CFG_SD_PIN_SEL_CARD;
writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
}
}

Expand Down Expand Up @@ -330,7 +355,7 @@ static struct sdhci_ops sdhci_brcmstb_ops = {
};

static struct sdhci_ops sdhci_brcmstb_ops_2712 = {
.set_clock = sdhci_set_clock,
.set_clock = sdhci_bcm2712_set_clock,
.set_power = sdhci_brcmstb_set_power,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
Expand Down
22 changes: 22 additions & 0 deletions drivers/pinctrl/bcm/pinctrl-bcm2712.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,17 @@ static const struct pin_regs bcm2712_d0_gpio_pin_regs[] = {
GPIO_REGS(33, 3, 1, 6, 0),
GPIO_REGS(34, 3, 2, 6, 1),
GPIO_REGS(35, 3, 3, 6, 2),
EMMC_REGS(36, 6, 3), /* EMMC_CMD */
EMMC_REGS(37, 6, 4), /* EMMC_DS */
EMMC_REGS(38, 6, 5), /* EMMC_CLK */
EMMC_REGS(39, 6, 6), /* EMMC_DAT0 */
EMMC_REGS(40, 6, 7), /* EMMC_DAT1 */
EMMC_REGS(41, 6, 8), /* EMMC_DAT2 */
EMMC_REGS(42, 6, 9), /* EMMC_DAT3 */
EMMC_REGS(43, 6, 10), /* EMMC_DAT4 */
EMMC_REGS(44, 6, 11), /* EMMC_DAT5 */
EMMC_REGS(45, 6, 12), /* EMMC_DAT6 */
EMMC_REGS(46, 6, 13), /* EMMC_DAT7 */
};

static struct pin_regs bcm2712_d0_aon_gpio_pin_regs[] = {
Expand Down Expand Up @@ -468,6 +479,17 @@ static const struct pinctrl_pin_desc bcm2712_d0_gpio_pins[] = {
GPIO_PIN(33),
GPIO_PIN(34),
GPIO_PIN(35),
PINCTRL_PIN(36, "emmc_cmd"),
PINCTRL_PIN(37, "emmc_ds"),
PINCTRL_PIN(38, "emmc_clk"),
PINCTRL_PIN(39, "emmc_dat0"),
PINCTRL_PIN(40, "emmc_dat1"),
PINCTRL_PIN(41, "emmc_dat2"),
PINCTRL_PIN(42, "emmc_dat3"),
PINCTRL_PIN(43, "emmc_dat4"),
PINCTRL_PIN(44, "emmc_dat5"),
PINCTRL_PIN(45, "emmc_dat6"),
PINCTRL_PIN(46, "emmc_dat7"),
};

static struct pinctrl_pin_desc bcm2712_d0_aon_gpio_pins[] = {
Expand Down