3030
3131#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
3232
33+ #define SDIO_CFG_CQ_CAPABILITY 0x4c
34+ #define SDIO_CFG_CQ_CAPABILITY_FMUL GENMASK(13, 12)
35+
36+ #define SDIO_CFG_CTRL 0x0
37+ #define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31)
38+ #define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30)
39+
40+ #define SDIO_CFG_MAX_50MHZ_MODE 0x1ac
41+ #define SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE BIT(31)
42+ #define SDIO_CFG_MAX_50MHZ_MODE_ENABLE BIT(0)
43+
44+ #define MMC_CAP_HSE_MASK (MMC_CAP2_HSX00_1_2V | MMC_CAP2_HSX00_1_8V)
45+ /* Select all SD UHS type I SDR speed above 50MB/s */
46+ #define MMC_CAP_UHS_I_SDR_MASK (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104)
47+
3348struct sdhci_brcmstb_priv {
3449 void __iomem * cfg_regs ;
3550 unsigned int flags ;
@@ -38,6 +53,7 @@ struct sdhci_brcmstb_priv {
3853};
3954
4055struct brcmstb_match_priv {
56+ void (* cfginit )(struct sdhci_host * host );
4157 void (* hs400es )(struct mmc_host * mmc , struct mmc_ios * ios );
4258 struct sdhci_ops * ops ;
4359 const unsigned int flags ;
@@ -168,6 +184,33 @@ static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
168184 sdhci_writew (host , ctrl_2 , SDHCI_HOST_CONTROL2 );
169185}
170186
187+ static void sdhci_brcmstb_cfginit_2712 (struct sdhci_host * host )
188+ {
189+ struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
190+ struct sdhci_brcmstb_priv * brcmstb_priv = sdhci_pltfm_priv (pltfm_host );
191+ u32 reg ;
192+
193+ /*
194+ * If we support a speed that requires tuning,
195+ * then select the delay line PHY as the clock source.
196+ */
197+ if ((host -> mmc -> caps & MMC_CAP_UHS_I_SDR_MASK ) || (host -> mmc -> caps2 & MMC_CAP_HSE_MASK )) {
198+ reg = readl (brcmstb_priv -> cfg_regs + SDIO_CFG_MAX_50MHZ_MODE );
199+ reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE ;
200+ reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE ;
201+ writel (reg , brcmstb_priv -> cfg_regs + SDIO_CFG_MAX_50MHZ_MODE );
202+ }
203+
204+ if ((host -> mmc -> caps & MMC_CAP_NONREMOVABLE ) ||
205+ (host -> mmc -> caps & MMC_CAP_NEEDS_POLL )) {
206+ /* Force presence */
207+ reg = readl (brcmstb_priv -> cfg_regs + SDIO_CFG_CTRL );
208+ reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV ;
209+ reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN ;
210+ writel (reg , brcmstb_priv -> cfg_regs + SDIO_CFG_CTRL );
211+ }
212+ }
213+
171214static void sdhci_brcmstb_dumpregs (struct mmc_host * mmc )
172215{
173216 sdhci_dumpregs (mmc_priv (mmc ));
@@ -200,6 +243,14 @@ static struct sdhci_ops sdhci_brcmstb_ops = {
200243 .set_uhs_signaling = sdhci_set_uhs_signaling ,
201244};
202245
246+ static struct sdhci_ops sdhci_brcmstb_ops_2712 = {
247+ .set_clock = sdhci_set_clock ,
248+ .set_power = sdhci_set_power_and_bus_voltage ,
249+ .set_bus_width = sdhci_set_bus_width ,
250+ .reset = sdhci_reset ,
251+ .set_uhs_signaling = sdhci_set_uhs_signaling ,
252+ };
253+
203254static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
204255 .set_clock = sdhci_brcmstb_set_clock ,
205256 .set_bus_width = sdhci_set_bus_width ,
@@ -214,6 +265,11 @@ static struct sdhci_ops sdhci_brcmstb_ops_74165b0 = {
214265 .set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling ,
215266};
216267
268+ static const struct brcmstb_match_priv match_priv_2712 = {
269+ .cfginit = sdhci_brcmstb_cfginit_2712 ,
270+ .ops = & sdhci_brcmstb_ops_2712 ,
271+ };
272+
217273static struct brcmstb_match_priv match_priv_7425 = {
218274 .flags = BRCMSTB_MATCH_FLAGS_NO_64BIT |
219275 BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT ,
@@ -238,6 +294,7 @@ static struct brcmstb_match_priv match_priv_74165b0 = {
238294};
239295
240296static const struct of_device_id __maybe_unused sdhci_brcm_of_match [] = {
297+ { .compatible = "brcm,bcm2712-sdhci" , .data = & match_priv_2712 },
241298 { .compatible = "brcm,bcm7425-sdhci" , .data = & match_priv_7425 },
242299 { .compatible = "brcm,bcm7445-sdhci" , .data = & match_priv_7445 },
243300 { .compatible = "brcm,bcm7216-sdhci" , .data = & match_priv_7216 },
@@ -370,6 +427,9 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
370427 (host -> mmc -> caps2 & MMC_CAP2_HS400_ES ))
371428 host -> mmc_host_ops .hs400_enhanced_strobe = match_priv -> hs400es ;
372429
430+ if (match_priv -> cfginit )
431+ match_priv -> cfginit (host );
432+
373433 /*
374434 * Supply the existing CAPS, but clear the UHS modes. This
375435 * will allow these modes to be specified by device tree
0 commit comments