183b3248eSFelipe Balbi /* 283b3248eSFelipe Balbi * Copyright (c) 2017 Intel Corporation 383b3248eSFelipe Balbi * 483b3248eSFelipe Balbi * SPDX-License-Identifier: GPL-2.0+ 583b3248eSFelipe Balbi */ 683b3248eSFelipe Balbi #include <common.h> 783b3248eSFelipe Balbi #include <dm.h> 883b3248eSFelipe Balbi #include <dm/device.h> 983b3248eSFelipe Balbi #include <linux/io.h> 1083b3248eSFelipe Balbi #include <linux/sizes.h> 1183b3248eSFelipe Balbi #include <malloc.h> 1283b3248eSFelipe Balbi #include <mmc.h> 1383b3248eSFelipe Balbi #include <sdhci.h> 1483b3248eSFelipe Balbi 1583b3248eSFelipe Balbi #define SDHCI_TANGIER_FMAX 200000000 1683b3248eSFelipe Balbi #define SDHCI_TANGIER_FMIN 400000 1783b3248eSFelipe Balbi 1883b3248eSFelipe Balbi struct sdhci_tangier_plat { 1983b3248eSFelipe Balbi struct mmc_config cfg; 2083b3248eSFelipe Balbi struct mmc mmc; 2183b3248eSFelipe Balbi void __iomem *ioaddr; 2283b3248eSFelipe Balbi }; 2383b3248eSFelipe Balbi 2483b3248eSFelipe Balbi static int sdhci_tangier_bind(struct udevice *dev) 2583b3248eSFelipe Balbi { 2683b3248eSFelipe Balbi struct sdhci_tangier_plat *plat = dev_get_platdata(dev); 2783b3248eSFelipe Balbi 2883b3248eSFelipe Balbi return sdhci_bind(dev, &plat->mmc, &plat->cfg); 2983b3248eSFelipe Balbi } 3083b3248eSFelipe Balbi 3183b3248eSFelipe Balbi static int sdhci_tangier_probe(struct udevice *dev) 3283b3248eSFelipe Balbi { 3383b3248eSFelipe Balbi struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 3483b3248eSFelipe Balbi struct sdhci_tangier_plat *plat = dev_get_platdata(dev); 3583b3248eSFelipe Balbi struct sdhci_host *host = dev_get_priv(dev); 3683b3248eSFelipe Balbi fdt_addr_t base; 3783b3248eSFelipe Balbi int ret; 3883b3248eSFelipe Balbi 39*a821c4afSSimon Glass base = devfdt_get_addr(dev); 4083b3248eSFelipe Balbi if (base == FDT_ADDR_T_NONE) 4183b3248eSFelipe Balbi return -EINVAL; 4283b3248eSFelipe Balbi 4383b3248eSFelipe Balbi plat->ioaddr = devm_ioremap(dev, base, SZ_1K); 4483b3248eSFelipe Balbi if (!plat->ioaddr) 4583b3248eSFelipe Balbi return -ENOMEM; 4683b3248eSFelipe Balbi 4783b3248eSFelipe Balbi host->name = dev->name; 4883b3248eSFelipe Balbi host->ioaddr = plat->ioaddr; 4983b3248eSFelipe Balbi host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE | 5083b3248eSFelipe Balbi SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD; 5183b3248eSFelipe Balbi 5283b3248eSFelipe Balbi /* MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195 */ 5383b3248eSFelipe Balbi host->voltages = MMC_VDD_165_195; 5483b3248eSFelipe Balbi 5583b3248eSFelipe Balbi ret = sdhci_setup_cfg(&plat->cfg, host, SDHCI_TANGIER_FMAX, 5683b3248eSFelipe Balbi SDHCI_TANGIER_FMIN); 5783b3248eSFelipe Balbi if (ret) 5883b3248eSFelipe Balbi return ret; 5983b3248eSFelipe Balbi 6083b3248eSFelipe Balbi upriv->mmc = &plat->mmc; 6183b3248eSFelipe Balbi host->mmc = &plat->mmc; 6283b3248eSFelipe Balbi host->mmc->priv = host; 6383b3248eSFelipe Balbi 6483b3248eSFelipe Balbi return sdhci_probe(dev); 6583b3248eSFelipe Balbi } 6683b3248eSFelipe Balbi 6783b3248eSFelipe Balbi static const struct udevice_id sdhci_tangier_match[] = { 6883b3248eSFelipe Balbi { .compatible = "intel,sdhci-tangier" }, 6983b3248eSFelipe Balbi { /* sentinel */ } 7083b3248eSFelipe Balbi }; 7183b3248eSFelipe Balbi 7283b3248eSFelipe Balbi U_BOOT_DRIVER(sdhci_tangier) = { 7383b3248eSFelipe Balbi .name = "sdhci-tangier", 7483b3248eSFelipe Balbi .id = UCLASS_MMC, 7583b3248eSFelipe Balbi .of_match = sdhci_tangier_match, 7683b3248eSFelipe Balbi .bind = sdhci_tangier_bind, 7783b3248eSFelipe Balbi .probe = sdhci_tangier_probe, 7883b3248eSFelipe Balbi .ops = &sdhci_ops, 7983b3248eSFelipe Balbi .priv_auto_alloc_size = sizeof(struct sdhci_host), 8083b3248eSFelipe Balbi .platdata_auto_alloc_size = sizeof(struct sdhci_tangier_plat), 8183b3248eSFelipe Balbi }; 82