Hi Andre, On 29 November 2017 at 18:25, Andre Przywara <andre.przyw...@arm.com> wrote: > From: Amit Singh Tomar <amittome...@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 <amittome...@gmail.com> > Signed-off-by: Andre Przywara <andre.przyw...@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 <amittome...@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot