diff options
-rw-r--r-- | drivers/mmc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/mmc/Makefile | 1 | ||||
-rw-r--r-- | drivers/mmc/rockchip_dw_mmc.c | 98 |
3 files changed, 108 insertions, 0 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 3e835f7bca..6277f92ef5 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -10,6 +10,15 @@ config DM_MMC appear as block devices in U-Boot and can support filesystems such as EXT4 and FAT. +config ROCKCHIP_DWMMC + bool "Rockchip SD/MMC controller support" + depends on DM_MMC && OF_CONTROL + help + This enables support for the Rockchip SD/MMM controller, which is + based on Designware IP. The device is compatible with at least + SD 3.0, SDIO 3.0 and MMC 4.5 and supports common eMMC chips as well + as removeable SD and micro-SD cards. + config SH_SDHI bool "SuperH/Renesas ARM SoCs on-chip SDHI host controller support" depends on RMOBILE diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index cae207c303..99d02954ed 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_MXS_MMC) += mxsmmc.o obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o obj-$(CONFIG_X86) += pci_mmc.o obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o +obj-$(CONFIG_ROCKCHIP_DWMMC) += rockchip_dw_mmc.o obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o obj-$(CONFIG_S3C_SDI) += s3c_sdi.o obj-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c new file mode 100644 index 0000000000..f11c8e0039 --- /dev/null +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <dwmmc.h> +#include <errno.h> +#include <syscon.h> +#include <asm/arch/clock.h> +#include <asm/arch/periph.h> +#include <linux/err.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct rockchip_dwmmc_priv { + struct udevice *clk; + struct rk3288_grf *grf; + struct dwmci_host host; +}; + +static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq) +{ + struct udevice *dev = host->priv; + struct rockchip_dwmmc_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_set_periph_rate(priv->clk, PERIPH_ID_SDMMC0 + host->dev_index, + freq); + if (ret < 0) { + debug("%s: err=%d\n", __func__, ret); + return ret; + } + + return freq; +} + +static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev) +{ + struct rockchip_dwmmc_priv *priv = dev_get_priv(dev); + struct dwmci_host *host = &priv->host; + + host->name = dev->name; + host->ioaddr = (void *)dev_get_addr(dev); + host->buswidth = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "bus-width", 4); + host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk; + host->priv = dev; + + /* TODO(sjg@chromium.org): Remove the need for this hack */ + host->dev_index = (ulong)host->ioaddr == 0xff0f0000 ? 0 : 1; + + return 0; +} + +static int rockchip_dwmmc_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct rockchip_dwmmc_priv *priv = dev_get_priv(dev); + struct dwmci_host *host = &priv->host; + u32 minmax[2]; + int ret; + + priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + if (IS_ERR(priv->grf)) + return PTR_ERR(priv->grf); + ret = uclass_get_device(UCLASS_CLK, CLK_GENERAL, &priv->clk); + if (ret) + return ret; + + ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, + "clock-freq-min-max", minmax, 2); + if (!ret) + ret = add_dwmci(host, minmax[1], minmax[0]); + if (ret) + return ret; + + upriv->mmc = host->mmc; + + return 0; +} + +static const struct udevice_id rockchip_dwmmc_ids[] = { + { .compatible = "rockchip,rk3288-dw-mshc" }, + { } +}; + +U_BOOT_DRIVER(rockchip_dwmmc_drv) = { + .name = "rockchip_dwmmc", + .id = UCLASS_MMC, + .of_match = rockchip_dwmmc_ids, + .ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata, + .probe = rockchip_dwmmc_probe, + .priv_auto_alloc_size = sizeof(struct rockchip_dwmmc_priv), +}; |