xref: /openbmc/u-boot/drivers/mmc/tangier_sdhci.c (revision a821c4af79e4f5ce9b629b20473863397bbe9b10)
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