179c83065SKever Yang /* 279c83065SKever Yang * (C) Copyright 2016 Fuzhou Rockchip Electronics Co., Ltd 379c83065SKever Yang * 479c83065SKever Yang * Rockchip SD Host Controller Interface 579c83065SKever Yang * 679c83065SKever Yang * SPDX-License-Identifier: GPL-2.0+ 779c83065SKever Yang */ 879c83065SKever Yang 979c83065SKever Yang #include <common.h> 1079c83065SKever Yang #include <dm.h> 11c2868212SKever Yang #include <dt-structs.h> 1279c83065SKever Yang #include <fdtdec.h> 1379c83065SKever Yang #include <libfdt.h> 1479c83065SKever Yang #include <malloc.h> 15c2868212SKever Yang #include <mapmem.h> 1679c83065SKever Yang #include <sdhci.h> 1739fbb56fSKever Yang #include <clk.h> 1879c83065SKever Yang 1939fbb56fSKever Yang DECLARE_GLOBAL_DATA_PTR; 2079c83065SKever Yang /* 400KHz is max freq for card ID etc. Use that as min */ 2179c83065SKever Yang #define EMMC_MIN_FREQ 400000 2279c83065SKever Yang 2379c83065SKever Yang struct rockchip_sdhc_plat { 24c2868212SKever Yang #if CONFIG_IS_ENABLED(OF_PLATDATA) 25c2868212SKever Yang struct dtd_rockchip_rk3399_sdhci_5_1 dtplat; 26c2868212SKever Yang #endif 2779c83065SKever Yang struct mmc_config cfg; 2879c83065SKever Yang struct mmc mmc; 2979c83065SKever Yang }; 3079c83065SKever Yang 3179c83065SKever Yang struct rockchip_sdhc { 3279c83065SKever Yang struct sdhci_host host; 3379c83065SKever Yang void *base; 3479c83065SKever Yang }; 3579c83065SKever Yang 3679c83065SKever Yang static int arasan_sdhci_probe(struct udevice *dev) 3779c83065SKever Yang { 3879c83065SKever Yang struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 3979c83065SKever Yang struct rockchip_sdhc_plat *plat = dev_get_platdata(dev); 4079c83065SKever Yang struct rockchip_sdhc *prv = dev_get_priv(dev); 4179c83065SKever Yang struct sdhci_host *host = &prv->host; 4239fbb56fSKever Yang int max_frequency, ret; 4339fbb56fSKever Yang struct clk clk; 4439fbb56fSKever Yang 45c2868212SKever Yang #if CONFIG_IS_ENABLED(OF_PLATDATA) 46c2868212SKever Yang struct dtd_rockchip_rk3399_sdhci_5_1 *dtplat = &plat->dtplat; 4739fbb56fSKever Yang 48c2868212SKever Yang host->name = dev->name; 49c2868212SKever Yang host->ioaddr = map_sysmem(dtplat->reg[1], dtplat->reg[3]); 50c2868212SKever Yang max_frequency = dtplat->max_frequency; 51c2868212SKever Yang ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &clk); 52c2868212SKever Yang #else 53*fd1bf8dfSPhilipp Tomsich max_frequency = dev_read_u32_default(dev, "max-frequency", 0); 5439fbb56fSKever Yang ret = clk_get_by_index(dev, 0, &clk); 55c2868212SKever Yang #endif 5639fbb56fSKever Yang if (!ret) { 5739fbb56fSKever Yang ret = clk_set_rate(&clk, max_frequency); 5839fbb56fSKever Yang if (IS_ERR_VALUE(ret)) 5939fbb56fSKever Yang printf("%s clk set rate fail!\n", __func__); 6039fbb56fSKever Yang } else { 6139fbb56fSKever Yang printf("%s fail to get clk\n", __func__); 6239fbb56fSKever Yang } 6379c83065SKever Yang 6479c83065SKever Yang host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD; 656d0e34bfSStefan Herbrechtsmeier host->max_clk = max_frequency; 6679c83065SKever Yang 676d0e34bfSStefan Herbrechtsmeier ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ); 6879c83065SKever Yang 6979c83065SKever Yang host->mmc = &plat->mmc; 7079c83065SKever Yang if (ret) 7179c83065SKever Yang return ret; 7279c83065SKever Yang host->mmc->priv = &prv->host; 7379c83065SKever Yang host->mmc->dev = dev; 7479c83065SKever Yang upriv->mmc = host->mmc; 7579c83065SKever Yang 7679c83065SKever Yang return sdhci_probe(dev); 7779c83065SKever Yang } 7879c83065SKever Yang 7979c83065SKever Yang static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) 8079c83065SKever Yang { 81c2868212SKever Yang #if !CONFIG_IS_ENABLED(OF_PLATDATA) 8279c83065SKever Yang struct sdhci_host *host = dev_get_priv(dev); 8379c83065SKever Yang 8479c83065SKever Yang host->name = dev->name; 85a821c4afSSimon Glass host->ioaddr = devfdt_get_addr_ptr(dev); 86c2868212SKever Yang #endif 8779c83065SKever Yang 8879c83065SKever Yang return 0; 8979c83065SKever Yang } 9079c83065SKever Yang 9179c83065SKever Yang static int rockchip_sdhci_bind(struct udevice *dev) 9279c83065SKever Yang { 9379c83065SKever Yang struct rockchip_sdhc_plat *plat = dev_get_platdata(dev); 9479c83065SKever Yang 9524f5aec3SMasahiro Yamada return sdhci_bind(dev, &plat->mmc, &plat->cfg); 9679c83065SKever Yang } 9779c83065SKever Yang 9879c83065SKever Yang static const struct udevice_id arasan_sdhci_ids[] = { 9979c83065SKever Yang { .compatible = "arasan,sdhci-5.1" }, 10079c83065SKever Yang { } 10179c83065SKever Yang }; 10279c83065SKever Yang 10379c83065SKever Yang U_BOOT_DRIVER(arasan_sdhci_drv) = { 104c2868212SKever Yang .name = "rockchip_rk3399_sdhci_5_1", 10579c83065SKever Yang .id = UCLASS_MMC, 10679c83065SKever Yang .of_match = arasan_sdhci_ids, 10779c83065SKever Yang .ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata, 10879c83065SKever Yang .ops = &sdhci_ops, 10979c83065SKever Yang .bind = rockchip_sdhci_bind, 11079c83065SKever Yang .probe = arasan_sdhci_probe, 11179c83065SKever Yang .priv_auto_alloc_size = sizeof(struct rockchip_sdhc), 11279c83065SKever Yang .platdata_auto_alloc_size = sizeof(struct rockchip_sdhc_plat), 11379c83065SKever Yang }; 114