// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright 2022 - Analog Devices, Inc. * * Written and/or maintained by Timesys Corporation * * Contact: Nathan Barrett-Morrison * Contact: Greg Malysa * * Based on Rockchip's sdhci.c file */ #include #include #include #include #include /* 400KHz is max freq for card ID etc. Use that as min */ #define EMMC_MIN_FREQ 400000 /* Check if an operation crossed a boundary of size ADMA_BOUNDARY_ALIGN */ #define ADMA_BOUNDARY_ALGN SZ_128M #define BOUNDARY_OK(addr, len) \ (((addr) | (ADMA_BOUNDARY_ALGN - 1)) == (((addr) + (len) - 1) | \ (ADMA_BOUNDARY_ALGN - 1))) /* We split a descriptor for every crossing of the ADMA alignment boundary, * so we need an additional descriptor for every expected crossing. * As I understand it, the max expected transaction size is: * CONFIG_SYS_MMC_MAX_BLK_COUNT * MMC_MAX_BLOCK_LEN * * With the way the SDHCI-ADMA driver is implemented, if ADMA_MAX_LEN was a * clean power of two, we'd only ever need +1 descriptor as the first * descriptor that got split would then bring the remaining DMA * destination addresses into alignment. Unfortunately, it's currently * hardcoded to a non-power-of-two value. * * If that ever becomes parameterized, ADMA max length can be set to * 0x10000, and set this to 1. */ #define ADMA_POTENTIAL_CROSSINGS \ DIV_ROUND_UP((CONFIG_SYS_MMC_MAX_BLK_COUNT * MMC_MAX_BLOCK_LEN), \ ADMA_BOUNDARY_ALGN) /* +1 descriptor for each crossing. */ #define ADMA_TABLE_EXTRA_SZ (ADMA_POTENTIAL_CROSSINGS * ADMA_DESC_LEN) struct adi_sdhc_plat { struct mmc_config cfg; struct mmc mmc; }; void adi_dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc, dma_addr_t addr, int len, bool end) { int tmplen, offset; if (likely(!len || BOUNDARY_OK(addr, len))) { sdhci_adma_write_desc(host, desc, addr, len, end); return; } offset = addr & (ADMA_BOUNDARY_ALGN - 1); tmplen = ADMA_BOUNDARY_ALGN - offset; sdhci_adma_write_desc(host, desc, addr, tmplen, false); addr += tmplen; len -= tmplen; sdhci_adma_write_desc(host, desc, addr, len, end); } struct sdhci_ops adi_dwcmshc_sdhci_ops = { .adma_write_desc = adi_dwcmshc_adma_write_desc, }; static int adi_dwcmshc_sdhci_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct adi_sdhc_plat *plat = dev_get_plat(dev); struct sdhci_host *host = dev_get_priv(dev); int max_frequency, ret; struct clk clk; max_frequency = dev_read_u32_default(dev, "max-frequency", 0); ret = clk_get_by_index(dev, 0, &clk); host->quirks = 0; host->max_clk = max_frequency; /* * The sdhci-driver only supports 4bit and 8bit, as sdhci_setup_cfg * doesn't allow us to clear MMC_MODE_4BIT. Consequently, we don't * check for other bus-width values. */ if (host->bus_width == 8) host->host_caps |= MMC_MODE_8BIT; host->mmc = &plat->mmc; host->mmc->priv = host; host->mmc->dev = dev; upriv->mmc = host->mmc; host->ops = &adi_dwcmshc_sdhci_ops; host->adma_desc_table = memalign(ARCH_DMA_MINALIGN, ADMA_TABLE_SZ + ADMA_TABLE_EXTRA_SZ); host->adma_addr = virt_to_phys(host->adma_desc_table); ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ); if (ret) return ret; return sdhci_probe(dev); } static int adi_dwcmshc_sdhci_of_to_plat(struct udevice *dev) { struct sdhci_host *host = dev_get_priv(dev); host->name = dev->name; host->ioaddr = dev_read_addr_ptr(dev); host->bus_width = dev_read_u32_default(dev, "bus-width", 4); return 0; } static int adi_sdhci_bind(struct udevice *dev) { struct adi_sdhc_plat *plat = dev_get_plat(dev); return sdhci_bind(dev, &plat->mmc, &plat->cfg); } static const struct udevice_id adi_dwcmshc_sdhci_ids[] = { { .compatible = "adi,dwc-sdhci" }, { } }; U_BOOT_DRIVER(adi_dwcmshc_sdhci_drv) = { .name = "adi_sdhci", .id = UCLASS_MMC, .of_match = adi_dwcmshc_sdhci_ids, .of_to_plat = adi_dwcmshc_sdhci_of_to_plat, .ops = &sdhci_ops, .bind = adi_sdhci_bind, .probe = adi_dwcmshc_sdhci_probe, .priv_auto = sizeof(struct sdhci_host), .plat_auto = sizeof(struct adi_sdhc_plat), };