Hi Jaehoon, > Hi, Piotr. > > On 01/27/2014 11:15 PM, Piotr Wilczek wrote: > > This patch enables support for device tree for sdhci driver. > > Non DT case is still supported. > > > > Signed-off-by: Piotr Wilczek <p.wilc...@samsung.com> > > Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com> > > Cc: Minkyu Kang <mk7.k...@samsung.com> > > --- > > arch/arm/include/asm/arch-exynos/mmc.h | 7 ++ > > drivers/mmc/s5p_sdhci.c | 130 > +++++++++++++++++++++++++++++++- > > include/fdtdec.h | 1 + > > include/sdhci.h | 5 ++ > > lib/fdtdec.c | 1 + > > 5 files changed, 143 insertions(+), 1 deletion(-) > > > > diff --git a/arch/arm/include/asm/arch-exynos/mmc.h > > b/arch/arm/include/asm/arch-exynos/mmc.h > > index 98d6530..0fb6461 100644 > > --- a/arch/arm/include/asm/arch-exynos/mmc.h > > +++ b/arch/arm/include/asm/arch-exynos/mmc.h > > @@ -53,6 +53,8 @@ > > #define SDHCI_CTRL4_DRIVE_MASK(_x) ((_x) << 16) > > #define SDHCI_CTRL4_DRIVE_SHIFT (16) > > > > +#define SDHCI_MAX_HOSTS 4 > > + > > int s5p_sdhci_init(u32 regbase, int index, int bus_width); > > > > static inline int s5p_mmc_init(int index, int bus_width) @@ -62,4 > > +64,9 @@ static inline int s5p_mmc_init(int index, int bus_width) > > > > return s5p_sdhci_init(base, index, bus_width); } > > + > > +#ifdef CONFIG_OF_CONTROL > > +int exynos_mmc_init(const void *blob); #endif > > + > > #endif > > diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index > > 40ff873..7456ee0 100644 > > --- a/drivers/mmc/s5p_sdhci.c > > +++ b/drivers/mmc/s5p_sdhci.c > > @@ -8,9 +8,15 @@ > > #include <common.h> > > #include <malloc.h> > > #include <sdhci.h> > > +#include <fdtdec.h> > > +#include <libfdt.h> > > +#include <asm/gpio.h> > > #include <asm/arch/mmc.h> > > #include <asm/arch/clk.h> > > - > > +#include <errno.h> > > +#ifdef CONFIG_OF_CONTROL > > +#include <asm/arch/pinmux.h> > > +#endif > > static char *S5P_NAME = "SAMSUNG SDHCI"; static void > > s5p_sdhci_set_control_reg(struct sdhci_host *host) { @@ -86,3 > +92,125 > > @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width) > > > > return add_sdhci(host, 52000000, 400000); } > > + > > +#ifdef CONFIG_OF_CONTROL > > +struct sdhci_host sdhci_host[SDHCI_MAX_HOSTS]; > > + > > +static int do_sdhci_init(struct sdhci_host *host) { > > + int dev_id, flag; > > + int err = 0; > > + > > + flag = host->bus_width == 8 ? PINMUX_FLAG_8BIT_MODE : > PINMUX_FLAG_NONE; > > + dev_id = host->index + PERIPH_ID_SDMMC0; > > + > > + if (fdt_gpio_isvalid(&host->pwr_gpio)) { > > + gpio_direction_output(host->pwr_gpio.gpio, 1); > > what's pwr_gpio? Is it used for the both(eMMC and SD card)? pwr_gpio is used only for eMMC. cd_gpio is used for SD Card.
> > > + err = exynos_pinmux_config(dev_id, flag); > > + if (err) { > > + debug("MMC not configured\n"); > > + return err; > > + } > > + } > > + > > + if (fdt_gpio_isvalid(&host->cd_gpio)) { > > + gpio_direction_output(host->cd_gpio.gpio, 0xf); > > + if (gpio_get_value(host->cd_gpio.gpio)) > > + return -ENODEV; > > + > > + err = exynos_pinmux_config(dev_id, flag); > > + if (err) { > > + printf("external SD not configured\n"); > > + return err; > > + } > > + } > > + > > + host->name = S5P_NAME; > > + > > + host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | > SDHCI_QUIRK_BROKEN_VOLTAGE | > > + SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR | > > + SDHCI_QUIRK_WAIT_SEND_CMD; > > + host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; > > + host->version = sdhci_readw(host, SDHCI_HOST_VERSION); > > + > > + host->set_control_reg = &s5p_sdhci_set_control_reg; > > + host->set_clock = set_mmc_clk; > > + > > + host->host_caps = MMC_MODE_HC; > > + > > + return add_sdhci(host, 52000000, 400000); } > > + > > +static int sdhci_get_config(const void *blob, int node, struct > > +sdhci_host *host) { > > + int bus_width, dev_id; > > + unsigned int base; > > + > > + /* Get device id */ > > + dev_id = pinmux_decode_periph_id(blob, node); > > + if (dev_id < PERIPH_ID_SDMMC0) { > > Didn't need to check other boundary? Yes, I should check for the PERIPH_ID_SDMMC3 > > > + debug("MMC: Can't get device id\n"); > > + return -1; > > + } > > + host->index = dev_id - PERIPH_ID_SDMMC0; > > + > > + /* Get bus width */ > > + bus_width = fdtdec_get_int(blob, node, "samsung,bus-width", 0); > > + if (bus_width <= 0) { > > + debug("MMC: Can't get bus-width\n"); > > + return -1; > > + } > > + host->bus_width = bus_width; > > + > > + /* Get the base address from the device node */ > > + base = fdtdec_get_addr(blob, node, "reg"); > > + if (!base) { > > + debug("DWMMC: Can't get base address\n"); > > DWMMC? MMC > > > + return -1; > > + } > > + host->ioaddr = (void *)base; > > + > > + fdtdec_decode_gpio(blob, node, "pwr-gpios", &host->pwr_gpio); > > + fdtdec_decode_gpio(blob, node, "cd-gpios", &host->cd_gpio); > > + > > + return 0; > > +} > > + > > +static int process_nodes(const void *blob, int node_list[], int > > +count) { > > + struct sdhci_host *host; > > + int i, node; > > + > > + debug("%s: count = %d\n", __func__, count); > > + > > + /* build sdhci_host[] for each controller */ > > + for (i = 0; i < count; i++) { > > + node = node_list[i]; > > + if (node <= 0) > > + continue; > > + > > + host = &sdhci_host[i]; > > + > > + if (sdhci_get_config(blob, node, host)) { > > + printf("%s: failed to decode dev %d\n", __func__, > i); > > + return -1; > > + } > > + do_sdhci_init(host); > > + } > > + return 0; > > +} > > + > > +int exynos_mmc_init(const void *blob) { > > + int count; > > + int node_list[SDHCI_MAX_HOSTS]; > > + > > + count = fdtdec_find_aliases_for_id(blob, "mmc", > > + COMPAT_SAMSUNG_EXYNOS_MMC, node_list, > > + SDHCI_MAX_HOSTS); > > + > > + process_nodes(blob, node_list, count); > > + > > + return 1; > > +} > > +#endif > > diff --git a/include/fdtdec.h b/include/fdtdec.h index > > f12b4aa..d637f88 100644 > > --- a/include/fdtdec.h > > +++ b/include/fdtdec.h > > @@ -81,6 +81,7 @@ enum fdt_compat_id { > > COMPAT_SAMSUNG_EXYNOS_MIPI_DSI, /* Exynos mipi dsi */ > > COMPAT_SAMSUNG_EXYNOS5_DP, /* Exynos Display port controller */ > > COMPAT_SAMSUNG_EXYNOS5_DWMMC, /* Exynos5 DWMMC controller */ > > + COMPAT_SAMSUNG_EXYNOS_MMC, /* Exynos MMC controller */ > > COMPAT_SAMSUNG_EXYNOS_SERIAL, /* Exynos UART */ > > COMPAT_MAXIM_MAX77686_PMIC, /* MAX77686 PMIC */ > > COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */ > > diff --git a/include/sdhci.h b/include/sdhci.h index 74d06ae..0cba703 > > 100644 > > --- a/include/sdhci.h > > +++ b/include/sdhci.h > > @@ -12,6 +12,7 @@ > > > > #include <asm/io.h> > > #include <mmc.h> > > +#include <fdtdec.h> > > > > /* > > * Controller registers > > @@ -244,6 +245,10 @@ struct sdhci_host { > > const struct sdhci_ops *ops; > > int index; > > > > + int bus_width; > > + struct fdt_gpio_state pwr_gpio; /* Change Detect GPIO */ > > pwr_gpio is Change Detect GPIO? I think that Comment is wrong. Yes, the comment is wrong. > > > + struct fdt_gpio_state cd_gpio; /* Change Detect GPIO */ > > Maybe Card detect GPIO is right. Yes > > + > > void (*set_control_reg)(struct sdhci_host *host); > > void (*set_clock)(int dev_index, unsigned int div); > > uint voltages; > > diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 46e67ff..a88f648 > 100644 > > --- a/lib/fdtdec.c > > +++ b/lib/fdtdec.c > > @@ -54,6 +54,7 @@ static const char * const > compat_names[COMPAT_COUNT] = { > > COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"), > > COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"), > > COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"), > > + COMPAT(SAMSUNG_EXYNOS_MMC, "samsung,exynos-mmc"), > > how about using "exynos4-mmc" instead of "exynos-mmc"? Is this driver only for Exynos4? > > Best Regards, > Jaehoon Chung > > > COMPAT(SAMSUNG_EXYNOS_SERIAL, "samsung,exynos4210-uart"), > > COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"), > > COMPAT(GENERIC_SPI_FLASH, "spi-flash"), > > Best regards, Piotr Wilczek _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot