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