1eee20f81SPatrice Chotard /* 2eee20f81SPatrice Chotard * Copyright (c) 2017 3eee20f81SPatrice Chotard * Patrice Chotard <patrice.chotard@st.com> 4eee20f81SPatrice Chotard * 5eee20f81SPatrice Chotard * SPDX-License-Identifier: GPL-2.0 6eee20f81SPatrice Chotard */ 7eee20f81SPatrice Chotard 8eee20f81SPatrice Chotard #include <common.h> 9eee20f81SPatrice Chotard #include <dm.h> 10eee20f81SPatrice Chotard #include <mmc.h> 11eee20f81SPatrice Chotard #include <sdhci.h> 12eee20f81SPatrice Chotard #include <asm/arch/sdhci.h> 13eee20f81SPatrice Chotard 14eee20f81SPatrice Chotard DECLARE_GLOBAL_DATA_PTR; 15eee20f81SPatrice Chotard 16eee20f81SPatrice Chotard struct sti_sdhci_plat { 17eee20f81SPatrice Chotard struct mmc_config cfg; 18eee20f81SPatrice Chotard struct mmc mmc; 19eee20f81SPatrice Chotard }; 20eee20f81SPatrice Chotard 21eee20f81SPatrice Chotard /* 22eee20f81SPatrice Chotard * used to get access to MMC1 reset, 23eee20f81SPatrice Chotard * will be removed when STi reset driver will be available 24eee20f81SPatrice Chotard */ 25eee20f81SPatrice Chotard #define STIH410_SYSCONF5_BASE 0x092b0000 26eee20f81SPatrice Chotard 27eee20f81SPatrice Chotard /** 28eee20f81SPatrice Chotard * sti_mmc_core_config: configure the Arasan HC 29eee20f81SPatrice Chotard * @regbase: base address 30eee20f81SPatrice Chotard * @mmc_instance: mmc instance id 31eee20f81SPatrice Chotard * Description: this function is to configure the Arasan MMC HC. 32eee20f81SPatrice Chotard * This should be called when the system starts in case of, on the SoC, 33eee20f81SPatrice Chotard * it is needed to configure the host controller. 34eee20f81SPatrice Chotard * This happens on some SoCs, i.e. StiH410, where the MMC0 inside the flashSS 35eee20f81SPatrice Chotard * needs to be configured as MMC 4.5 to have full capabilities. 36eee20f81SPatrice Chotard * W/o these settings the SDHCI could configure and use the embedded controller 37eee20f81SPatrice Chotard * with limited features. 38eee20f81SPatrice Chotard */ 39eee20f81SPatrice Chotard static void sti_mmc_core_config(const u32 regbase, int mmc_instance) 40eee20f81SPatrice Chotard { 41eee20f81SPatrice Chotard unsigned long *sysconf; 42eee20f81SPatrice Chotard 43eee20f81SPatrice Chotard /* only MMC1 has a reset line */ 44eee20f81SPatrice Chotard if (mmc_instance) { 45eee20f81SPatrice Chotard sysconf = (unsigned long *)(STIH410_SYSCONF5_BASE + 46eee20f81SPatrice Chotard ST_MMC_CCONFIG_REG_5); 47eee20f81SPatrice Chotard generic_set_bit(SYSCONF_MMC1_ENABLE_BIT, sysconf); 48eee20f81SPatrice Chotard } 49eee20f81SPatrice Chotard 50eee20f81SPatrice Chotard writel(STI_FLASHSS_MMC_CORE_CONFIG_1, 51eee20f81SPatrice Chotard regbase + FLASHSS_MMC_CORE_CONFIG_1); 52eee20f81SPatrice Chotard 53eee20f81SPatrice Chotard if (mmc_instance) { 54eee20f81SPatrice Chotard writel(STI_FLASHSS_MMC_CORE_CONFIG2, 55eee20f81SPatrice Chotard regbase + FLASHSS_MMC_CORE_CONFIG_2); 56eee20f81SPatrice Chotard writel(STI_FLASHSS_MMC_CORE_CONFIG3, 57eee20f81SPatrice Chotard regbase + FLASHSS_MMC_CORE_CONFIG_3); 58eee20f81SPatrice Chotard } else { 59eee20f81SPatrice Chotard writel(STI_FLASHSS_SDCARD_CORE_CONFIG2, 60eee20f81SPatrice Chotard regbase + FLASHSS_MMC_CORE_CONFIG_2); 61eee20f81SPatrice Chotard writel(STI_FLASHSS_SDCARD_CORE_CONFIG3, 62eee20f81SPatrice Chotard regbase + FLASHSS_MMC_CORE_CONFIG_3); 63eee20f81SPatrice Chotard } 64eee20f81SPatrice Chotard writel(STI_FLASHSS_MMC_CORE_CONFIG4, 65eee20f81SPatrice Chotard regbase + FLASHSS_MMC_CORE_CONFIG_4); 66eee20f81SPatrice Chotard } 67eee20f81SPatrice Chotard 68eee20f81SPatrice Chotard static int sti_sdhci_probe(struct udevice *dev) 69eee20f81SPatrice Chotard { 70eee20f81SPatrice Chotard struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 71eee20f81SPatrice Chotard struct sti_sdhci_plat *plat = dev_get_platdata(dev); 72eee20f81SPatrice Chotard struct sdhci_host *host = dev_get_priv(dev); 73eee20f81SPatrice Chotard int ret, mmc_instance; 74eee20f81SPatrice Chotard 75eee20f81SPatrice Chotard /* 76eee20f81SPatrice Chotard * identify current mmc instance, mmc1 has a reset, not mmc0 77eee20f81SPatrice Chotard * MMC0 is wired to the SD slot, 78eee20f81SPatrice Chotard * MMC1 is wired on the high speed connector 79eee20f81SPatrice Chotard */ 80eee20f81SPatrice Chotard 81eee20f81SPatrice Chotard if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) 82eee20f81SPatrice Chotard mmc_instance = 1; 83eee20f81SPatrice Chotard else 84eee20f81SPatrice Chotard mmc_instance = 0; 85eee20f81SPatrice Chotard 86eee20f81SPatrice Chotard sti_mmc_core_config((const u32) host->ioaddr, mmc_instance); 87eee20f81SPatrice Chotard 88eee20f81SPatrice Chotard host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | 89eee20f81SPatrice Chotard SDHCI_QUIRK_32BIT_DMA_ADDR | 90eee20f81SPatrice Chotard SDHCI_QUIRK_NO_HISPD_BIT; 91eee20f81SPatrice Chotard 92eee20f81SPatrice Chotard host->host_caps = MMC_MODE_DDR_52MHz; 93eee20f81SPatrice Chotard 94eee20f81SPatrice Chotard ret = sdhci_setup_cfg(&plat->cfg, host, 50000000, 400000); 95eee20f81SPatrice Chotard if (ret) 96eee20f81SPatrice Chotard return ret; 97eee20f81SPatrice Chotard 98eee20f81SPatrice Chotard host->mmc = &plat->mmc; 99eee20f81SPatrice Chotard host->mmc->priv = host; 100eee20f81SPatrice Chotard host->mmc->dev = dev; 101eee20f81SPatrice Chotard upriv->mmc = host->mmc; 102eee20f81SPatrice Chotard 103eee20f81SPatrice Chotard return sdhci_probe(dev); 104eee20f81SPatrice Chotard } 105eee20f81SPatrice Chotard 106eee20f81SPatrice Chotard static int sti_sdhci_ofdata_to_platdata(struct udevice *dev) 107eee20f81SPatrice Chotard { 108eee20f81SPatrice Chotard struct sdhci_host *host = dev_get_priv(dev); 109eee20f81SPatrice Chotard 110eee20f81SPatrice Chotard host->name = strdup(dev->name); 111*a821c4afSSimon Glass host->ioaddr = (void *)devfdt_get_addr(dev); 112eee20f81SPatrice Chotard 113eee20f81SPatrice Chotard host->bus_width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), 114eee20f81SPatrice Chotard "bus-width", 4); 115eee20f81SPatrice Chotard 116eee20f81SPatrice Chotard return 0; 117eee20f81SPatrice Chotard } 118eee20f81SPatrice Chotard 119eee20f81SPatrice Chotard static int sti_sdhci_bind(struct udevice *dev) 120eee20f81SPatrice Chotard { 121eee20f81SPatrice Chotard struct sti_sdhci_plat *plat = dev_get_platdata(dev); 122eee20f81SPatrice Chotard 123eee20f81SPatrice Chotard return sdhci_bind(dev, &plat->mmc, &plat->cfg); 124eee20f81SPatrice Chotard } 125eee20f81SPatrice Chotard 126eee20f81SPatrice Chotard static const struct udevice_id sti_sdhci_ids[] = { 127eee20f81SPatrice Chotard { .compatible = "st,sdhci" }, 128eee20f81SPatrice Chotard { } 129eee20f81SPatrice Chotard }; 130eee20f81SPatrice Chotard 131eee20f81SPatrice Chotard U_BOOT_DRIVER(sti_mmc) = { 132eee20f81SPatrice Chotard .name = "sti_sdhci", 133eee20f81SPatrice Chotard .id = UCLASS_MMC, 134eee20f81SPatrice Chotard .of_match = sti_sdhci_ids, 135eee20f81SPatrice Chotard .bind = sti_sdhci_bind, 136eee20f81SPatrice Chotard .ops = &sdhci_ops, 137eee20f81SPatrice Chotard .ofdata_to_platdata = sti_sdhci_ofdata_to_platdata, 138eee20f81SPatrice Chotard .probe = sti_sdhci_probe, 139eee20f81SPatrice Chotard .priv_auto_alloc_size = sizeof(struct sdhci_host), 140eee20f81SPatrice Chotard .platdata_auto_alloc_size = sizeof(struct sti_sdhci_plat), 141eee20f81SPatrice Chotard }; 142