Commit 3577fe8be9dc8c8aa027361d6424efba9f97f553

Authored by Piotr Wilczek
Committed by Minkyu Kang
1 parent 1591ee7352

drivers:mmc:sdhci: enable support for DT

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>
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>

Showing 5 changed files with 143 additions and 0 deletions Side-by-side Diff

arch/arm/include/asm/arch-exynos/mmc.h
... ... @@ -53,6 +53,8 @@
53 53 #define SDHCI_CTRL4_DRIVE_MASK(_x) ((_x) << 16)
54 54 #define SDHCI_CTRL4_DRIVE_SHIFT (16)
55 55  
  56 +#define SDHCI_MAX_HOSTS 4
  57 +
56 58 int s5p_sdhci_init(u32 regbase, int index, int bus_width);
57 59  
58 60 static inline int s5p_mmc_init(int index, int bus_width)
... ... @@ -62,5 +64,10 @@
62 64  
63 65 return s5p_sdhci_init(base, index, bus_width);
64 66 }
  67 +
  68 +#ifdef CONFIG_OF_CONTROL
  69 +int exynos_mmc_init(const void *blob);
  70 +#endif
  71 +
65 72 #endif
drivers/mmc/s5p_sdhci.c
... ... @@ -8,8 +8,15 @@
8 8 #include <common.h>
9 9 #include <malloc.h>
10 10 #include <sdhci.h>
  11 +#include <fdtdec.h>
  12 +#include <libfdt.h>
  13 +#include <asm/gpio.h>
11 14 #include <asm/arch/mmc.h>
12 15 #include <asm/arch/clk.h>
  16 +#include <errno.h>
  17 +#ifdef CONFIG_OF_CONTROL
  18 +#include <asm/arch/pinmux.h>
  19 +#endif
13 20  
14 21 static char *S5P_NAME = "SAMSUNG SDHCI";
15 22 static void s5p_sdhci_set_control_reg(struct sdhci_host *host)
... ... @@ -86,4 +93,126 @@
86 93  
87 94 return add_sdhci(host, 52000000, 400000);
88 95 }
  96 +
  97 +#ifdef CONFIG_OF_CONTROL
  98 +struct sdhci_host sdhci_host[SDHCI_MAX_HOSTS];
  99 +
  100 +static int do_sdhci_init(struct sdhci_host *host)
  101 +{
  102 + int dev_id, flag;
  103 + int err = 0;
  104 +
  105 + flag = host->bus_width == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE;
  106 + dev_id = host->index + PERIPH_ID_SDMMC0;
  107 +
  108 + if (fdt_gpio_isvalid(&host->pwr_gpio)) {
  109 + gpio_direction_output(host->pwr_gpio.gpio, 1);
  110 + err = exynos_pinmux_config(dev_id, flag);
  111 + if (err) {
  112 + debug("MMC not configured\n");
  113 + return err;
  114 + }
  115 + }
  116 +
  117 + if (fdt_gpio_isvalid(&host->cd_gpio)) {
  118 + gpio_direction_output(host->cd_gpio.gpio, 0xf);
  119 + if (gpio_get_value(host->cd_gpio.gpio))
  120 + return -ENODEV;
  121 +
  122 + err = exynos_pinmux_config(dev_id, flag);
  123 + if (err) {
  124 + printf("external SD not configured\n");
  125 + return err;
  126 + }
  127 + }
  128 +
  129 + host->name = S5P_NAME;
  130 +
  131 + host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
  132 + SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR |
  133 + SDHCI_QUIRK_WAIT_SEND_CMD;
  134 + host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
  135 + host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
  136 +
  137 + host->set_control_reg = &s5p_sdhci_set_control_reg;
  138 + host->set_clock = set_mmc_clk;
  139 +
  140 + host->host_caps = MMC_MODE_HC;
  141 +
  142 + return add_sdhci(host, 52000000, 400000);
  143 +}
  144 +
  145 +static int sdhci_get_config(const void *blob, int node, struct sdhci_host *host)
  146 +{
  147 + int bus_width, dev_id;
  148 + unsigned int base;
  149 +
  150 + /* Get device id */
  151 + dev_id = pinmux_decode_periph_id(blob, node);
  152 + if (dev_id < PERIPH_ID_SDMMC0 && dev_id > PERIPH_ID_SDMMC3) {
  153 + debug("MMC: Can't get device id\n");
  154 + return -1;
  155 + }
  156 + host->index = dev_id - PERIPH_ID_SDMMC0;
  157 +
  158 + /* Get bus width */
  159 + bus_width = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
  160 + if (bus_width <= 0) {
  161 + debug("MMC: Can't get bus-width\n");
  162 + return -1;
  163 + }
  164 + host->bus_width = bus_width;
  165 +
  166 + /* Get the base address from the device node */
  167 + base = fdtdec_get_addr(blob, node, "reg");
  168 + if (!base) {
  169 + debug("MMC: Can't get base address\n");
  170 + return -1;
  171 + }
  172 + host->ioaddr = (void *)base;
  173 +
  174 + fdtdec_decode_gpio(blob, node, "pwr-gpios", &host->pwr_gpio);
  175 + fdtdec_decode_gpio(blob, node, "cd-gpios", &host->cd_gpio);
  176 +
  177 + return 0;
  178 +}
  179 +
  180 +static int process_nodes(const void *blob, int node_list[], int count)
  181 +{
  182 + struct sdhci_host *host;
  183 + int i, node;
  184 +
  185 + debug("%s: count = %d\n", __func__, count);
  186 +
  187 + /* build sdhci_host[] for each controller */
  188 + for (i = 0; i < count; i++) {
  189 + node = node_list[i];
  190 + if (node <= 0)
  191 + continue;
  192 +
  193 + host = &sdhci_host[i];
  194 +
  195 + if (sdhci_get_config(blob, node, host)) {
  196 + printf("%s: failed to decode dev %d\n", __func__, i);
  197 + return -1;
  198 + }
  199 + do_sdhci_init(host);
  200 + }
  201 + return 0;
  202 +}
  203 +
  204 +int exynos_mmc_init(const void *blob)
  205 +{
  206 + int count;
  207 + int node_list[SDHCI_MAX_HOSTS];
  208 +
  209 + count = fdtdec_find_aliases_for_id(blob, "mmc",
  210 + COMPAT_SAMSUNG_EXYNOS_MMC, node_list,
  211 + SDHCI_MAX_HOSTS);
  212 +
  213 + process_nodes(blob, node_list, count);
  214 +
  215 + return 1;
  216 +}
  217 +#endif
... ... @@ -82,6 +82,7 @@
82 82 COMPAT_SAMSUNG_EXYNOS_MIPI_DSI, /* Exynos mipi dsi */
83 83 COMPAT_SAMSUNG_EXYNOS5_DP, /* Exynos Display port controller */
84 84 COMPAT_SAMSUNG_EXYNOS5_DWMMC, /* Exynos5 DWMMC controller */
  85 + COMPAT_SAMSUNG_EXYNOS_MMC, /* Exynos MMC controller */
85 86 COMPAT_SAMSUNG_EXYNOS_SERIAL, /* Exynos UART */
86 87 COMPAT_MAXIM_MAX77686_PMIC, /* MAX77686 PMIC */
87 88 COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */
... ... @@ -12,6 +12,7 @@
12 12  
13 13 #include <asm/io.h>
14 14 #include <mmc.h>
  15 +#include <fdtdec.h>
15 16  
16 17 /*
17 18 * Controller registers
... ... @@ -243,6 +244,10 @@
243 244 struct mmc *mmc;
244 245 const struct sdhci_ops *ops;
245 246 int index;
  247 +
  248 + int bus_width;
  249 + struct fdt_gpio_state pwr_gpio; /* Power GPIO */
  250 + struct fdt_gpio_state cd_gpio; /* Card Detect GPIO */
246 251  
247 252 void (*set_control_reg)(struct sdhci_host *host);
248 253 void (*set_clock)(int dev_index, unsigned int div);
... ... @@ -55,6 +55,7 @@
55 55 COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"),
56 56 COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"),
57 57 COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"),
  58 + COMPAT(SAMSUNG_EXYNOS_MMC, "samsung,exynos-mmc"),
58 59 COMPAT(SAMSUNG_EXYNOS_SERIAL, "samsung,exynos4210-uart"),
59 60 COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
60 61 COMPAT(GENERIC_SPI_FLASH, "spi-flash"),