git: 36b80dba1742 - main - sdhci_fsl_fdt: Add full support for software reset
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 05 Nov 2021 09:19:20 UTC
The branch main has been updated by wma: URL: https://cgit.FreeBSD.org/src/commit/?id=36b80dba1742acfeecfe8c26516c5cf16fd1346d commit 36b80dba1742acfeecfe8c26516c5cf16fd1346d Author: Artur Rojek <ar@semihalf.com> AuthorDate: 2021-11-05 09:16:30 +0000 Commit: Wojciech Macek <wma@FreeBSD.org> CommitDate: 2021-11-05 09:18:57 +0000 sdhci_fsl_fdt: Add full support for software reset When performing software reset, this controller does not clear all the required hw registers. In particular, tuning block is left in enabled state, inhibiting operation of some eMMC cards. The existing solution was to disable the ability to call SDHCI_RESET_ALL. As this issue is now better understood, enable the SDHCI_RESET_ALL flag, provide a custom reset devmethod and clear selected registers by hand. Obtained from: Semihalf Sponsored by: Alstom Group Differential revision: https://reviews.freebsd.org/D32705 --- sys/dev/sdhci/sdhci_fsl_fdt.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/sys/dev/sdhci/sdhci_fsl_fdt.c b/sys/dev/sdhci/sdhci_fsl_fdt.c index 5aec394b9192..77af367c5366 100644 --- a/sys/dev/sdhci/sdhci_fsl_fdt.c +++ b/sys/dev/sdhci/sdhci_fsl_fdt.c @@ -86,6 +86,9 @@ __FBSDID("$FreeBSD$"); #define SDHCI_FSL_HOST_VERSION 0xfc #define SDHCI_FSL_CAPABILITIES2 0x114 +#define SDHCI_FSL_TBCTL 0x120 +#define SDHCI_FSL_TBCTL_TBEN (1 << 2) + #define SDHCI_FSL_ESDHC_CTRL 0x40c #define SDHCI_FSL_ESDHC_CTRL_SNOOP (1 << 6) #define SDHCI_FSL_ESDHC_CTRL_CLK_DIV2 (1 << 19) @@ -347,9 +350,6 @@ sdhci_fsl_fdt_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off, return; case SDHCI_POWER_CONTROL: return; - case SDHCI_SOFTWARE_RESET: - val &= ~SDHCI_RESET_ALL; - /* FALLTHROUGH. */ default: val32 = RD4(sc, off & ~3); val32 &= ~(UINT8_MAX << (off & 3) * 8); @@ -803,6 +803,27 @@ sdhci_fsl_fdt_read_ivar(device_t bus, device_t child, int which, return (sdhci_generic_read_ivar(bus, child, which, result)); } +static void +sdhci_fsl_fdt_reset(device_t dev, struct sdhci_slot *slot, uint8_t mask) +{ + struct sdhci_fsl_fdt_softc *sc; + uint32_t val; + + sdhci_generic_reset(dev, slot, mask); + + if (!(mask & SDHCI_RESET_ALL)) + return; + + sc = device_get_softc(dev); + + /* Some registers have to be cleared by hand. */ + if (slot->version >= SDHCI_SPEC_300) { + val = RD4(sc, SDHCI_FSL_TBCTL); + val &= ~SDHCI_FSL_TBCTL_TBEN; + WR4(sc, SDHCI_FSL_TBCTL, val); + } +} + static const device_method_t sdhci_fsl_fdt_methods[] = { /* Device interface. */ DEVMETHOD(device_probe, sdhci_fsl_fdt_probe), @@ -831,6 +852,7 @@ static const device_method_t sdhci_fsl_fdt_methods[] = { DEVMETHOD(sdhci_write_4, sdhci_fsl_fdt_write_4), DEVMETHOD(sdhci_write_multi_4, sdhci_fsl_fdt_write_multi_4), DEVMETHOD(sdhci_get_card_present, sdhci_fsl_fdt_get_card_present), + DEVMETHOD(sdhci_reset, sdhci_fsl_fdt_reset), DEVMETHOD_END };