Skip to content

Commit

Permalink
rockchip: Add an MMC driver
Browse files Browse the repository at this point in the history
Add an MMC driver which supports RK3288, but may also support other SoCs.
It uses the Designware MMC device.

Signed-off-by: Simon Glass <[email protected]>
  • Loading branch information
sjg20 committed Sep 3, 2015
1 parent 5ff093a commit a8cb4fb
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 0 deletions.
9 changes: 9 additions & 0 deletions drivers/mmc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/mmc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
98 changes: 98 additions & 0 deletions drivers/mmc/rockchip_dw_mmc.c
Original file line number Diff line number Diff line change
@@ -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([email protected]): 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),
};

0 comments on commit a8cb4fb

Please sign in to comment.