git: 8bb448b66e9d - stable/13 - sdhci_xenon: add UHS support

From: Marcin Wojtas <mw_at_FreeBSD.org>
Date: Mon, 07 Mar 2022 16:00:09 UTC
The branch stable/13 has been updated by mw:

URL: https://cgit.FreeBSD.org/src/commit/?id=8bb448b66e9d5e162b9960291851550baa3083c1

commit 8bb448b66e9d5e162b9960291851550baa3083c1
Author:     Marcin Wojtas <mw@FreeBSD.org>
AuthorDate: 2021-05-04 23:47:37 +0000
Commit:     Marcin Wojtas <mw@FreeBSD.org>
CommitDate: 2022-03-07 15:59:51 +0000

    sdhci_xenon: add UHS support
    
    This patch adds the necessary methods resolution to the sdhci_xenon
    driver which are required to configure UHS modes for SD/MMC devices.
    Apart from the two generic routines, the custom sdhci_xenon_set_uhs_timing
    function is responsible for setting the SDHCI_HOST_CONTROL2 register
    with appropriate mode select values - in case of HS200 and HS400
    they are non-standard.
    
    Reviewed by: manu
    Obtained from: Semihalf
    Sponsored by: Marvell
    Differential Revision: https://reviews.freebsd.org/D30565
    MFC after: 2 weeks
    
    (cherry picked from commit 4fa977f854e27c93c22acfa6a3ba38f5c4959e15)
---
 sys/dev/sdhci/sdhci_xenon.c | 40 ++++++++++++++++++++++++++++++++++++++++
 sys/dev/sdhci/sdhci_xenon.h |  4 ++++
 2 files changed, 44 insertions(+)

diff --git a/sys/dev/sdhci/sdhci_xenon.c b/sys/dev/sdhci/sdhci_xenon.c
index 42f36b619b36..3f312921154f 100644
--- a/sys/dev/sdhci/sdhci_xenon.c
+++ b/sys/dev/sdhci/sdhci_xenon.c
@@ -197,6 +197,43 @@ sdhci_xenon_get_card_present(device_t dev, struct sdhci_slot *slot)
 	return (sdhci_fdt_gpio_get_present(sc->gpio));
 }
 
+static void
+sdhci_xenon_set_uhs_timing(device_t brdev, struct sdhci_slot *slot)
+{
+	const struct mmc_ios *ios;
+	uint16_t hostctrl2;
+
+	if (slot->version < SDHCI_SPEC_300)
+		return;
+
+	mtx_assert(&slot->mtx, MA_OWNED);
+	ios = &slot->host.ios;
+
+	/* Update timing parameteres in SDHCI_HOST_CONTROL2 register. */
+	hostctrl2 = sdhci_xenon_read_2(brdev, slot, SDHCI_HOST_CONTROL2);
+	hostctrl2 &= ~SDHCI_CTRL2_UHS_MASK;
+	if (ios->clock > SD_SDR50_MAX) {
+		if (ios->timing == bus_timing_mmc_hs400 ||
+		    ios->timing == bus_timing_mmc_hs400es)
+			hostctrl2 |= XENON_CTRL2_MMC_HS400;
+		else if (ios->timing == bus_timing_mmc_hs200)
+			hostctrl2 |= XENON_CTRL2_MMC_HS200;
+		else
+			hostctrl2 |= SDHCI_CTRL2_UHS_SDR104;
+	}
+	else if (ios->clock > SD_SDR25_MAX)
+		hostctrl2 |= SDHCI_CTRL2_UHS_SDR50;
+	else if (ios->clock > SD_SDR12_MAX) {
+		if (ios->timing == bus_timing_uhs_ddr50 ||
+		    ios->timing == bus_timing_mmc_ddr52)
+			hostctrl2 |= SDHCI_CTRL2_UHS_DDR50;
+		else
+			hostctrl2 |= SDHCI_CTRL2_UHS_SDR25;
+	} else if (ios->clock > SD_MMC_CARD_ID_FREQUENCY)
+		hostctrl2 |= SDHCI_CTRL2_UHS_SDR12;
+	sdhci_xenon_write_2(brdev, slot, SDHCI_HOST_CONTROL2, hostctrl2);
+}
+
 static int
 sdhci_xenon_phy_init(device_t brdev, struct mmc_ios *ios)
 {
@@ -663,6 +700,8 @@ static device_method_t sdhci_xenon_methods[] = {
 	DEVMETHOD(mmcbr_acquire_host,	sdhci_generic_acquire_host),
 	DEVMETHOD(mmcbr_release_host,	sdhci_generic_release_host),
 	DEVMETHOD(mmcbr_switch_vccq,	sdhci_xenon_switch_vccq),
+	DEVMETHOD(mmcbr_tune,		sdhci_generic_tune),
+	DEVMETHOD(mmcbr_retune,		sdhci_generic_retune),
 
 	/* SDHCI registers accessors */
 	DEVMETHOD(sdhci_read_1,		sdhci_xenon_read_1),
@@ -674,6 +713,7 @@ static device_method_t sdhci_xenon_methods[] = {
 	DEVMETHOD(sdhci_write_4,	sdhci_xenon_write_4),
 	DEVMETHOD(sdhci_write_multi_4,	sdhci_xenon_write_multi_4),
 	DEVMETHOD(sdhci_get_card_present,	sdhci_xenon_get_card_present),
+	DEVMETHOD(sdhci_set_uhs_timing, sdhci_xenon_set_uhs_timing),
 
 	DEVMETHOD_END
 };
diff --git a/sys/dev/sdhci/sdhci_xenon.h b/sys/dev/sdhci/sdhci_xenon.h
index b79dab6bab55..07ed99339b8d 100644
--- a/sys/dev/sdhci/sdhci_xenon.h
+++ b/sys/dev/sdhci/sdhci_xenon.h
@@ -46,6 +46,10 @@
 #define	 XENON_ENABLE_DATA_STROBE		(1 << 24)
 #define	 XENON_ENABLE_RESP_STROBE		(1 << 25)
 
+/* Custom HS200 / HS400 Mode Select values in SDHCI_HOST_CONTROL2 register. */
+#define	XENON_CTRL2_MMC_HS200			0x5
+#define	XENON_CTRL2_MMC_HS400			0x6
+
 /* eMMC PHY */
 #define	XENON_EMMC_PHY_REG_BASE			0x170