From 426fdd69757119e942bca031a7cc533f9ff4dd4c Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 29 Oct 2020 09:57:16 +0800 Subject: [PATCH] mmc: brcmstb: add support for BCM2712 BCM2712 has an SD Express capable SDHCI implementation and uses the SDIO CFG register block present on other STB chips. Add plumbing for SD Express handover and BCM2712-specific functions. Due to the common bus infrastructure between BCM2711 and BCM2712, the driver also needs to implement 32-bit IO accessors. mmc: brcmstb: override card presence if broken-cd is set Not just if the card is declared as nonremovable. sdhci: brcmstb: align SD express switchover with SD spec v8.00 Part 1 of the Physical specification, figure 3-24, details the switch sequence for cards initially probed as SD. Add a missing check for DAT2 level after switching VDD2 on. sdhci: brcmstb: clean up SD Express probe and error handling Refactor to avoid spurious error messages in dmesg if the requisite SD Express DT nodes aren't present. Signed-off-by: Jonathan Bell 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 mmc: sdhci-brcmstb: remove 32-bit accessors for BCM2712 The reason for adding these are lost to the mists of time (and for a previous chip revision). Removing these accessors appears to have no ill effect on production chips, so get rid of the unnecessary RMW cycles. Signed-off-by: Jonathan Bell 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 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 --- drivers/mmc/host/Kconfig | 1 + drivers/mmc/host/sdhci-brcmstb.c | 235 +++++++++++++++++++++++++++++-- 2 files changed, 227 insertions(+), 9 deletions(-) --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -1070,6 +1070,7 @@ config MMC_SDHCI_BRCMSTB depends on ARCH_BRCMSTB || ARCH_BCM2835 || BMIPS_GENERIC || COMPILE_TEST depends on MMC_SDHCI_PLTFM select MMC_CQHCI + select OF_DYNAMIC default ARCH_BRCMSTB || BMIPS_GENERIC help This selects support for the SDIO/SD/MMC Host Controller on --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include "sdhci-cqhci.h" #include "sdhci-pltfm.h" @@ -28,29 +30,38 @@ #define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0) #define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1) +#define BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS BIT(2) #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200 #define SDIO_CFG_CQ_CAPABILITY 0x4c -#define SDIO_CFG_CQ_CAPABILITY_FMUL GENMASK(13, 12) +#define SDIO_CFG_CQ_CAPABILITY_FMUL_SHIFT 12 #define SDIO_CFG_CTRL 0x0 #define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31) #define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30) +#define SDIO_CFG_SD_PIN_SEL 0x44 +#define SDIO_CFG_SD_PIN_SEL_MASK 0x3 +#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) #define SDIO_CFG_MAX_50MHZ_MODE_ENABLE BIT(0) -#define MMC_CAP_HSE_MASK (MMC_CAP2_HSX00_1_2V | MMC_CAP2_HSX00_1_8V) -/* Select all SD UHS type I SDR speed above 50MB/s */ -#define MMC_CAP_UHS_I_SDR_MASK (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104) - struct sdhci_brcmstb_priv { void __iomem *cfg_regs; unsigned int flags; struct clk *base_clk; u32 base_freq_hz; + struct regulator *sde_1v8; + struct device_node *sde_pcie; + void *__iomem sde_ioaddr; + void *__iomem sde_ioaddr2; + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_sdex; }; struct brcmstb_match_priv { @@ -141,6 +152,42 @@ static void sdhci_brcmstb_hs400es(struct 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; @@ -156,6 +203,17 @@ static void sdhci_brcmstb_set_clock(stru sdhci_enable_clk(host, clk); } +static void sdhci_brcmstb_set_power(struct sdhci_host *host, unsigned char mode, + unsigned short vdd) +{ + if (!IS_ERR(host->mmc->supply.vmmc)) { + struct mmc_host *mmc = host->mmc; + + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); + } + sdhci_set_power_noreg(host, mode, vdd); +} + static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host, unsigned int timing) { @@ -190,12 +248,16 @@ static void sdhci_brcmstb_cfginit_2712(s struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host); u32 reg; + 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 base_clk_mhz; /* * If we support a speed that requires tuning, * then select the delay line PHY as the clock source. */ - if ((host->mmc->caps & MMC_CAP_UHS_I_SDR_MASK) || (host->mmc->caps2 & MMC_CAP_HSE_MASK)) { + 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; @@ -210,6 +272,109 @@ static void sdhci_brcmstb_cfginit_2712(s reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN; writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CTRL); } + + /* Guesstimate the timer frequency (controller base clock) */ + base_clk_mhz = max_t(u32, clk_get_rate(pltfm_host->clk) / (1000 * 1000), 1); + reg = (3 << SDIO_CFG_CQ_CAPABILITY_FMUL_SHIFT) | base_clk_mhz; + writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CQ_CAPABILITY); +} + +static int bcm2712_init_sd_express(struct sdhci_host *host, struct mmc_ios *ios) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host); + struct device *dev = host->mmc->parent; + u32 ctrl_val; + u32 present_state; + int ret; + + if (!brcmstb_priv->sde_ioaddr || !brcmstb_priv->sde_ioaddr2) + return -EINVAL; + + if (!brcmstb_priv->pinctrl) + return -EINVAL; + + /* Turn off the SD clock first */ + sdhci_set_clock(host, 0); + + /* Disable SD DAT0-3 pulls */ + pinctrl_select_state(brcmstb_priv->pinctrl, brcmstb_priv->pins_sdex); + + ctrl_val = readl(brcmstb_priv->sde_ioaddr); + dev_dbg(dev, "ctrl_val 1 %08x\n", ctrl_val); + + /* Tri-state the SD pins */ + ctrl_val |= 0x1ff8; + writel(ctrl_val, brcmstb_priv->sde_ioaddr); + dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr)); + /* Let voltages settle */ + udelay(100); + + /* Enable the PCIe sideband pins */ + ctrl_val &= ~0x6000; + writel(ctrl_val, brcmstb_priv->sde_ioaddr); + dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr)); + /* Let voltages settle */ + udelay(100); + + /* Turn on the 1v8 VDD2 regulator */ + ret = regulator_enable(brcmstb_priv->sde_1v8); + if (ret) + return ret; + + /* Wait for Tpvcrl */ + msleep(1); + + /* Sample DAT2 (CLKREQ#) - if low, card is in PCIe mode */ + present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); + present_state = (present_state & SDHCI_DATA_LVL_MASK) >> SDHCI_DATA_LVL_SHIFT; + dev_dbg(dev, "state = 0x%08x\n", present_state); + + if (present_state & BIT(2)) { + dev_err(dev, "DAT2 still high, abandoning SDex switch\n"); + return -ENODEV; + } + + /* Turn on the LCPLL PTEST mux */ + ctrl_val = readl(brcmstb_priv->sde_ioaddr2 + 20); // misc5 + ctrl_val &= ~(0x7 << 7); + ctrl_val |= 3 << 7; + writel(ctrl_val, brcmstb_priv->sde_ioaddr2 + 20); + dev_dbg(dev, "misc 5->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2 + 20)); + + /* PTEST diff driver enable */ + ctrl_val = readl(brcmstb_priv->sde_ioaddr2); + ctrl_val |= BIT(21); + writel(ctrl_val, brcmstb_priv->sde_ioaddr2); + + dev_dbg(dev, "misc 0->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2)); + + /* Wait for more than the minimum Tpvpgl time */ + msleep(100); + + if (brcmstb_priv->sde_pcie) { + struct of_changeset changeset; + static struct property okay_property = { + .name = "status", + .value = "okay", + .length = 5, + }; + + /* Enable the pcie controller */ + of_changeset_init(&changeset); + ret = of_changeset_update_property(&changeset, + brcmstb_priv->sde_pcie, + &okay_property); + if (ret) { + dev_err(dev, "%s: failed to update property - %d\n", __func__, + ret); + return -ENODEV; + } + ret = of_changeset_apply(&changeset); + } + + dev_dbg(dev, "%s -> %d\n", __func__, ret); + return ret; } static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc) @@ -245,11 +410,12 @@ static struct sdhci_ops sdhci_brcmstb_op }; static struct sdhci_ops sdhci_brcmstb_ops_2712 = { - .set_clock = sdhci_set_clock, - .set_power = sdhci_set_power_and_bus_voltage, + .set_clock = sdhci_bcm2712_set_clock, + .set_power = sdhci_brcmstb_set_power, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, + .init_sd_express = bcm2712_init_sd_express, }; static struct sdhci_ops sdhci_brcmstb_ops_7216 = { @@ -267,6 +433,8 @@ static struct sdhci_ops sdhci_brcmstb_op }; static const struct brcmstb_match_priv match_priv_2712 = { + .flags = BRCMSTB_MATCH_FLAGS_USE_CARD_BUSY, + .hs400es = sdhci_brcmstb_hs400es, .cfginit = sdhci_brcmstb_cfginit_2712, .ops = &sdhci_brcmstb_ops_2712, }; @@ -372,6 +540,8 @@ static int sdhci_brcmstb_probe(struct pl struct sdhci_brcmstb_priv *priv; u32 actual_clock_mhz; struct sdhci_host *host; + struct resource *iomem; + bool no_pinctrl = false; struct clk *clk; struct clk *base_clk = NULL; int res; @@ -394,12 +564,19 @@ static int sdhci_brcmstb_probe(struct pl return PTR_ERR(host); pltfm_host = sdhci_priv(host); + pltfm_host->clk = clk; + priv = sdhci_pltfm_priv(pltfm_host); if (device_property_read_bool(&pdev->dev, "supports-cqe")) { priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_CQE; match_priv->ops->irq = sdhci_brcmstb_cqhci_irq; } + priv->sde_pcie = of_parse_phandle(pdev->dev.of_node, + "sde-pcie", 0); + if (priv->sde_pcie) + priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS; + /* Map in the non-standard CFG registers */ priv->cfg_regs = devm_platform_get_and_ioremap_resource(pdev, 1, NULL); if (IS_ERR(priv->cfg_regs)) { @@ -412,6 +589,43 @@ static int sdhci_brcmstb_probe(struct pl if (res) goto err; + priv->sde_1v8 = devm_regulator_get_optional(&pdev->dev, "sde-1v8"); + if (IS_ERR(priv->sde_1v8)) + priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS; + + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (iomem) { + priv->sde_ioaddr = devm_ioremap_resource(&pdev->dev, iomem); + if (IS_ERR(priv->sde_ioaddr)) + priv->sde_ioaddr = NULL; + } + + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 3); + if (iomem) { + priv->sde_ioaddr2 = devm_ioremap_resource(&pdev->dev, iomem); + if (IS_ERR(priv->sde_ioaddr2)) + priv->sde_ioaddr = NULL; + } + + priv->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(priv->pinctrl)) { + no_pinctrl = true; + } + priv->pins_default = pinctrl_lookup_state(priv->pinctrl, "default"); + if (IS_ERR(priv->pins_default)) { + dev_dbg(&pdev->dev, "No pinctrl default state\n"); + no_pinctrl = true; + } + priv->pins_sdex = pinctrl_lookup_state(priv->pinctrl, "sd-express"); + if (IS_ERR(priv->pins_sdex)) { + dev_dbg(&pdev->dev, "No pinctrl sd-express state\n"); + no_pinctrl = true; + } + if (no_pinctrl || !priv->sde_ioaddr || !priv->sde_ioaddr2) { + priv->pinctrl = NULL; + priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS; + } + /* * Automatic clock gating does not work for SD cards that may * voltage switch so only enable it for non-removable devices. @@ -428,6 +642,10 @@ static int sdhci_brcmstb_probe(struct pl (host->mmc->caps2 & MMC_CAP2_HS400_ES)) host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es; + if (host->ops->init_sd_express && + (priv->flags & BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS)) + host->mmc->caps2 |= MMC_CAP2_SD_EXP; + if (match_priv->cfginit) match_priv->cfginit(host); @@ -481,7 +699,6 @@ add_host: if (res) goto err; - pltfm_host->clk = clk; return res; err: