* [U-Boot] [PATCH 4/9] mmc: exynos_dw_mmc: restore the property into host
@ 2014-03-27 8:54 Jaehoon Chung
0 siblings, 0 replies; only message in thread
From: Jaehoon Chung @ 2014-03-27 8:54 UTC (permalink / raw)
To: u-boot
Restore the platdata(property of dt) into host struct.
Then The data's information is maintained and reused anywhere.
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Beomho Seo <beomho.seo@samsung.com>
---
drivers/mmc/exynos_dw_mmc.c | 213 ++++++++++++++++++++++++++----------------
include/dwmmc.h | 2 +
3 files changed, 138 insertions(+), 80 deletions(-)
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index b9d41d4..9d9cfde 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -45,6 +45,13 @@ unsigned int exynos_dwmci_get_clk(struct dwmci_host *host)
& DWMCI_DIVRATIO_MASK) + 1;
sclk = get_mmc_clk(host->dev_index);
+ /*
+ * Assume to know divider value.
+ * When clock unit is broken, need to set "host->div"
+ */
+ if (host->div)
+ sclk /= (host->div + 1);
+
return sclk / clk_div;
}
@@ -61,26 +68,17 @@ static void exynos_dwmci_board_init(struct dwmci_host *host)
}
}
-/*
- * This function adds the mmc channel to be registered with mmc core.
- * index - mmc channel number.
- * regbase - register base address of mmc channel specified in 'index'.
- * bus_width - operating bus width of mmc channel specified in 'index'.
- * clksel - value to be written into CLKSEL register in case of FDT.
- * NULL in case od non-FDT.
- */
-int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
+static int exynos_dwmci_core_init(struct dwmci_host *host, int index)
{
- struct dwmci_host *host = NULL;
unsigned int div;
unsigned long freq, sclk;
- host = malloc(sizeof(struct dwmci_host));
- if (!host) {
- printf("dwmci_host malloc fail!\n");
- return 1;
- }
+
+ if (host->bus_hz) {
+ freq = host->bus_hz;
+ } else
+ freq = DWMMC_MAX_FREQ;
+
/* request mmc clock vlaue of 52MHz. */
- freq = 52000000;
sclk = get_mmc_clk(index);
div = DIV_ROUND_UP(sclk, freq);
div -= 1;
@@ -88,16 +86,12 @@ int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
set_mmc_clk(index, div);
host->name = "EXYNOS DWMMC";
- host->ioaddr = (void *)regbase;
- host->buswidth = bus_width;
#ifdef CONFIG_EXYNOS5420
host->quirks = DWMCI_QUIRK_DISABLE_SMU;
#endif
host->board_init = exynos_dwmci_board_init;
- if (clksel) {
- host->clksel_val = clksel;
- } else {
+ if (!host->clksel_val) {
if (0 == index)
host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
if (2 == index)
@@ -112,83 +106,142 @@ int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
debug("dwmmc%d registration failed\n", index);
return -1;
}
+
return 0;
}
+/*
+ * This function adds the mmc channel to be registered with mmc core.
+ * index - mmc channel number.
+ * regbase - register base address of mmc channel specified in 'index'.
+ * bus_width - operating bus width of mmc channel specified in 'index'.
+ * clksel - value to be written into CLKSEL register in case of FDT.
+ * NULL in case od non-FDT.
+ */
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
+{
+ struct dwmci_host *host = NULL;
+
+ host = malloc(sizeof(struct dwmci_host));
+ if (!host) {
+ printf("dwmci_host malloc fail!\n");
+ return 1;
+ }
+
+ host->ioaddr = (void *)regbase;
+ host->buswidth = bus_width;
+
+ if (clksel)
+ host->clksel_val = clksel;
+
+ return exynos_dwmci_core_init(host, index);
+}
+
#ifdef CONFIG_OF_CONTROL
-int exynos_dwmmc_init(const void *blob)
+struct dwmci_host dwmci_host[DWMMC_MAX_CH_NUM];
+
+static int do_dwmci_init(struct dwmci_host *host)
{
- int index, bus_width;
- int node_list[DWMMC_MAX_CH_NUM];
- int err = 0, dev_id, flag, count, i, compat_id;
- u32 clksel_val, base, timing[3];
+ int index, flag = 0, err = 0;
-#ifdef CONFIG_EXYNOS4
- compat_id = COMPAT_SAMSUNG_EXYNOS4_DWMMC;
-#else
- compat_id = COMPAT_SAMSUNG_EXYNOS5_DWMMC;
-#endif
+ index = host->dev_index;
- count = fdtdec_find_aliases_for_id(blob, "mmc",
- compat_id, node_list, DWMMC_MAX_CH_NUM);
+ flag = host->buswidth == 8? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE;
+ err = exynos_pinmux_config(host->dev_id, flag);
+ if (err) {
+ debug("DWMMC not configure\n");
+ return err;
+ }
- for (i = 0; i < count; i++) {
- int node = node_list[i];
- struct fdt_gpio_state pwr_gpio;
+ return exynos_dwmci_core_init(host, index);
+}
- if (node <= 0)
- continue;
+static int exynos_dwmci_get_config(const void *blob, int node,
+ struct dwmci_host *host)
+{
+ int err = 0;
+ u32 base, clksel_val, timing[3];
- /* Extract device id for each mmc channel */
- dev_id = pinmux_decode_periph_id(blob, node);
+ /* Extract device id for each mmc channel */
+ host->dev_id = pinmux_decode_periph_id(blob, node);
- /* Get the bus width from the device node */
- bus_width = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
- if (bus_width <= 0) {
- debug("DWMMC: Can't get bus-width\n");
- return -1;
- }
- if (8 == bus_width)
- flag = PINMUX_FLAG_8BIT_MODE;
- else
- flag = PINMUX_FLAG_NONE;
-
- fdtdec_decode_gpio(blob, node, "pwr-gpios", &pwr_gpio);
- if (fdt_gpio_isvalid(&pwr_gpio))
- gpio_direction_output(pwr_gpio.gpio, 1);
- /* config pinmux for each mmc channel */
- err = exynos_pinmux_config(dev_id, flag);
- if (err) {
- debug("DWMMC not configured\n");
- return err;
- }
+ /* Get the bus width from the device node */
+ host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
+ if (host->buswidth <= 0) {
+ debug("DWMMC: Can't get bus-width\n");
+ return -1;
+ }
- index = fdtdec_get_int(blob, node, "index", dev_id);
- if (index == dev_id)
- index = dev_id - PERIPH_ID_SDMMC0;
+ host->dev_index = fdtdec_get_int(blob, node, "index", host->dev_id);
+ if (host->dev_index == host->dev_id)
+ host->dev_index = host->dev_id - PERIPH_ID_SDMMC0;
- /* 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");
- return -1;
- }
- /* Extract the timing info from the node */
- err = fdtdec_get_int_array(blob, node, "samsung,timing",
- timing, 3);
+ /* Set the base address from the device node */
+ base = fdtdec_get_addr(blob, node, "reg");
+ if (!base) {
+ debug("DWMMC: Can't get base address\n");
+ return -1;
+ }
+ host->ioaddr = (void *)base;
+
+ /* Extract the timing info from the node */
+ err = fdtdec_get_int_array(blob, node, "samsung,timing", timing, 3);
+ if (err) {
+ debug("Can't get sdr-timings for devider\n");
+ return -1;
+ }
+
+ clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+ DWMCI_SET_DRV_CLK(timing[1]) |
+ DWMCI_SET_DIV_RATIO(timing[2]));
+ if (clksel_val)
+ host->clksel_val = clksel_val;
+
+ host->fifoth_val = fdtdec_get_int(blob, node, "fifoth_val", 0);
+ host->bus_hz = fdtdec_get_int(blob, node, "bus_hz", 0);
+ host->div = fdtdec_get_int(blob, node, "div", 0);
+
+ return 0;
+}
+
+static int exynos_dwmci_process_node(const void *blob, int node_list[], int count)
+{
+ struct dwmci_host *host;
+ int i, node, err;
+
+ for (i = 0; i < count; i++) {
+ node = node_list[i];
+ if (node <= 0)
+ continue;
+ host = &dwmci_host[i];
+ err = exynos_dwmci_get_config(blob, node, host);
if (err) {
- debug("Can't get sdr-timings for divider\n");
+ debug("%s: failed to decode dev %d\n", __func__, i);
return -1;
}
- clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
- DWMCI_SET_DRV_CLK(timing[1]) |
- DWMCI_SET_DIV_RATIO(timing[2]));
- /* Initialise each mmc channel */
- err = exynos_dwmci_add_port(index, base, bus_width, clksel_val);
- if (err)
- debug("dwmmc Channel-%d init failed\n", index);
+ do_dwmci_init(host);
}
+
return 0;
}
+
+int exynos_dwmmc_init(const void *blob)
+{
+ int compat_id;
+ int node_list[DWMMC_MAX_CH_NUM];
+ int err = 0, count;
+
+#ifdef CONFIG_EXYNOS4
+ compat_id = COMPAT_SAMSUNG_EXYNOS4_DWMMC;
+#else
+ compat_id = COMPAT_SAMSUNG_EXYNOS5_DWMMC;
+#endif
+
+ count = fdtdec_find_aliases_for_id(blob, "mmc",
+ compat_id, node_list, DWMMC_MAX_CH_NUM);
+ err = exynos_dwmci_process_node(blob, node_list, count);
+
+ return err;
+}
#endif
diff --git a/include/dwmmc.h b/include/dwmmc.h
index b641558..f391b63 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -134,7 +134,9 @@ struct dwmci_host {
unsigned int version;
unsigned int clock;
unsigned int bus_hz;
+ unsigned int div;
int dev_index;
+ int dev_id;
int buswidth;
u32 clksel_val;
u32 fifoth_val;
--
1.7.9.5
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2014-03-27 8:54 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-27 8:54 [U-Boot] [PATCH 4/9] mmc: exynos_dw_mmc: restore the property into host Jaehoon Chung
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.