[U-Boot] [RFC PATCH 05/13] mmc: add MMC (glue) driver for Nexell SoCs

Simon Glass sjg at chromium.org
Sat Dec 2 03:30:42 UTC 2017


Hi Andre,

On 29 November 2017 at 18:25, Andre Przywara <andre.przywara at arm.com> wrote:
> From: Amit Singh Tomar <amittomer25 at gmail.com>
>
> The Nexell SoCs contain multiple MMC devices, which can be driven by
> U-Boot's DesignWare MMC driver, if supported by the required glue driver
> file.
> Provide that file along with the Makefile/Kconfig changes.
>
> Signed-off-by: Amit Singh Tomar <amittomer25 at gmail.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  drivers/mmc/Kconfig         |   8 +++
>  drivers/mmc/Makefile        |   1 +
>  drivers/mmc/nexell_dw_mmc.c | 159 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 168 insertions(+)
>  create mode 100644 drivers/mmc/nexell_dw_mmc.c
>
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
> index 62ce0af7d3..243878aa65 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -91,6 +91,14 @@ config MMC_DW_K3
>           Synopsys DesignWare Memory Card Interface driver. Select this option
>           for platforms based on Hisilicon K3 SoC's.
>
> +config MMC_DW_NEXELL
> +        bool "NEXELL SD/MMC controller support"
> +        depends on ARCH_NEXELL && DM_MMC && OF_CONTROL
> +        depends on MMC_DW
> +        help
> +          This enables support for the Nexell SD/MMM controller, which is
> +          based on Designware IP.
> +
>  config MMC_DW_ROCKCHIP
>         bool "Rockchip SD/MMC controller support"
>         depends on DM_MMC && OF_CONTROL
> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
> index d505f37f01..0fb6eb7803 100644
> --- a/drivers/mmc/Makefile
> +++ b/drivers/mmc/Makefile
> @@ -26,6 +26,7 @@ obj-$(CONFIG_MMC_DAVINCI)             += davinci_mmc.o
>  obj-$(CONFIG_MMC_DW)                   += dw_mmc.o
>  obj-$(CONFIG_MMC_DW_EXYNOS)            += exynos_dw_mmc.o
>  obj-$(CONFIG_MMC_DW_K3)                        += hi6220_dw_mmc.o
> +obj-$(CONFIG_MMC_DW_NEXELL)            += nexell_dw_mmc.o
>  obj-$(CONFIG_MMC_DW_ROCKCHIP)          += rockchip_dw_mmc.o
>  obj-$(CONFIG_MMC_DW_SOCFPGA)           += socfpga_dw_mmc.o
>  obj-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
> diff --git a/drivers/mmc/nexell_dw_mmc.c b/drivers/mmc/nexell_dw_mmc.c
> new file mode 100644
> index 0000000000..e96395cdaf
> --- /dev/null
> +++ b/drivers/mmc/nexell_dw_mmc.c
> @@ -0,0 +1,159 @@
> +/*
> + * Copyright (C) 2017 Amit Singh Tomar <amittomer25 at gmail.com>
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dt-structs.h>
> +#include <dwmmc.h>
> +#include <errno.h>
> +#include <mapmem.h>
> +#include <linux/err.h>
> +#include <reset.h>
> +#include <asm/arch/clk.h>
> +
> +#define SDMMCCLKENB 0xC00C5000
> +#define SDMMCCLKGEN0L 0xC00C5004
> +#define PLL_SEL_MASK GENMASK(4, 2)
> +#define CLK_DIV_MASK GENMASK(12, 5)
> +#define PLLSEL_SHIFT 0x2
> +#define PLL0_SEL 0
> +#define PLL1_SEL 1
> +#define PLL2_SEL 2
> +#define SDMMC_CLK_ENB 0xc /* Magic bit to enable/generate SDMMC clock */
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct nexell_mmc_plat {
> +       struct mmc_config cfg;
> +       struct mmc mmc;
> +};
> +
> +struct nexell_dwmmc_priv {
> +       struct clk clk;
> +       struct dwmci_host host;
> +       struct reset_ctl reset_ctl;
> +       int fifo_depth;
> +       bool fifo_mode;

comments

> +};
> +
> +/* Should this be done from CCF ? */
> +static void nexell_dwmci_clksel(struct dwmci_host *host)
> +{
> +       u32 val;
> +
> +       /* Enable SDMMC clock */
> +       val = readl(SDMMCCLKENB);
> +       val |= SDMMC_CLK_ENB;
> +       writel(val, SDMMCCLKENB);

How about using setbits_le32() ?

> +
> +       /* Select PLL1 as clock source */
> +       val = readl(SDMMCCLKGEN0L);
> +       val = val & ~(PLL_SEL_MASK);
> +       val |= (PLL1_SEL << PLLSEL_SHIFT) & PLL_SEL_MASK;
> +       writel(val, SDMMCCLKGEN0L);

clrsetbits_le32

> +}
> +
> +static int nexell_dwmmc_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
> +       struct dwmci_host *host = &priv->host;
> +       int fifo_depth, ret;
> +
> +       ret = reset_get_by_name(dev, "mmc", &priv->reset_ctl);
> +       if (ret) {
> +               printf("reset_get_by_name(rst) failed: %d", ret);

debug() ? And below

> +               return ret;
> +       }
> +
> +       fifo_depth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
> +                                   "fifo-depth", 0);

dev_read_...()

and below

> +       if (fifo_depth < 0) {
> +               printf("DWMMC: Can't get FIFO depth\n");
> +               return -EINVAL;
> +       }
> +
> +       host->name = dev->name;
> +       host->ioaddr = (void *)devfdt_get_addr(dev);
> +       host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
> +                                       "bus-width", 4);
> +
> +       ret = reset_assert(&priv->reset_ctl);
> +       if (ret)
> +               return ret;
> +
> +       host->clksel = nexell_dwmci_clksel;
> +
> +       ret = reset_deassert(&priv->reset_ctl);
> +       if (ret)
> +               return ret;
> +
> +       host->dev_index = 0;
> +       host->bus_hz = get_mmc_clk(host->dev_index);
> +       host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_depth / 2 - 1) |
> +                          TX_WMARK(fifo_depth / 2);
> +       host->priv = priv;
> +
> +       return 0;
> +}
> +
> +static int nexell_dwmmc_probe(struct udevice *dev)
> +{
> +#ifdef CONFIG_BLK

Do we need to support non-BLK? It is going away in March anyway.

> +       struct nexell_mmc_plat *plat = dev_get_platdata(dev);
> +#endif
> +       struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
> +       struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
> +       struct dwmci_host *host = &priv->host;
> +
> +#ifdef CONFIG_BLK
> +       dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000);
> +       host->mmc = &plat->mmc;
> +#else
> +       int ret;
> +
> +       ret = add_dwmci(host, host->bus_hz, 400000);
> +       if (ret)
> +               return ret;
> +#endif
> +
> +       host->mmc->priv = &priv->host;
> +       upriv->mmc = host->mmc;
> +       host->mmc->dev = dev;
> +
> +       return 0;
> +}
> +
> +static int nexell_dwmmc_bind(struct udevice *dev)
> +{
> +#ifdef CONFIG_BLK
> +       struct nexell_mmc_plat *plat = dev_get_platdata(dev);
> +       int ret;
> +
> +       ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
> +       if (ret)
> +               return ret;
> +#endif
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id nexell_dwmmc_ids[] = {
> +       { .compatible = "nexell,s5p6818-dw-mshc" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(nexell_dwmmc_drv) = {
> +       .name           = "nexell_s5p6818_dw_mshc",
> +       .id             = UCLASS_MMC,
> +       .of_match       = nexell_dwmmc_ids,
> +       .ops            = &dm_dwmci_ops,
> +       .ofdata_to_platdata = nexell_dwmmc_ofdata_to_platdata,
> +       .bind           = nexell_dwmmc_bind,
> +       .probe          = nexell_dwmmc_probe,
> +       .priv_auto_alloc_size = sizeof(struct nexell_dwmmc_priv),
> +       .platdata_auto_alloc_size = sizeof(struct nexell_mmc_plat),
> +};
> --
> 2.14.1
>

Regards,
Simon


More information about the U-Boot mailing list