
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.wilczek@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com Cc: Minkyu Kang mk7.kang@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)?
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 <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.
- 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"),