From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jaehoon Chung Date: Tue, 28 Jan 2014 18:42:47 +0900 Subject: [U-Boot] [PATCH 4/9] drivers:mmc:sdhci: enable support for DT In-Reply-To: <1390832143-372-5-git-send-email-p.wilczek@samsung.com> References: <1390832143-372-1-git-send-email-p.wilczek@samsung.com> <1390832143-372-5-git-send-email-p.wilczek@samsung.com> Message-ID: <52E77B97.3030201@samsung.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 > Signed-off-by: Kyungmin Park > Cc: Minkyu Kang > --- > 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 > #include > #include > +#include > +#include > +#include > #include > #include > - > +#include > +#ifdef CONFIG_OF_CONTROL > +#include > +#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)? > + 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? > + 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? > + 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 > #include > +#include > > /* > * 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. > + struct fdt_gpio_state cd_gpio; /* Change Detect GPIO */ Maybe Card detect GPIO is right. > + > 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"? Best Regards, Jaehoon Chung > COMPAT(SAMSUNG_EXYNOS_SERIAL, "samsung,exynos4210-uart"), > COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"), > COMPAT(GENERIC_SPI_FLASH, "spi-flash"), >