From 129adf5bf4769cd93f05e53e6aab724894c31036 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 25 Jul 2015 10:48:14 +0200 Subject: mmc: dw_mmc: Probe the MMC from OF Rework the driver to probe the MMC controller from Device Tree and make it mandatory. There is no longer support for probing from the ancient qts-generated header files. This patch now also removes previous temporary workaround. Signed-off-by: Marek Vasut Cc: Dinh Nguyen Cc: Pantelis Antoniou Cc: Tom Rini --- drivers/mmc/socfpga_dw_mmc.c | 81 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index eb69aed9df..8076761e06 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include #include @@ -42,34 +44,87 @@ static void socfpga_dwmci_clksel(struct dwmci_host *host) CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK); } -int socfpga_dwmmc_init(u32 regbase, int bus_width, int index) +static int socfpga_dwmci_of_probe(const void *blob, int node, const int idx) { + /* FIXME: probe from DT eventually too/ */ + const unsigned long clk = cm_get_mmc_controller_clk_hz(); + struct dwmci_host *host; - unsigned long clk = cm_get_mmc_controller_clk_hz(); + fdt_addr_t reg_base; + int bus_width, fifo_depth; if (clk == 0) { - printf("%s: MMC clock is zero!", __func__); + printf("DWMMC%d: MMC clock is zero!", idx); return -EINVAL; } - /* calloc for zero init */ - host = calloc(1, sizeof(struct dwmci_host)); - if (!host) { - printf("%s: calloc() failed!\n", __func__); - return -ENOMEM; + /* Get the register address from the device node */ + reg_base = fdtdec_get_addr(blob, node, "reg"); + if (!reg_base) { + printf("DWMMC%d: Can't get base address\n", idx); + return -EINVAL; + } + + /* Get the bus width from the device node */ + bus_width = fdtdec_get_int(blob, node, "bus-width", 0); + if (bus_width <= 0) { + printf("DWMMC%d: Can't get bus-width\n", idx); + return -EINVAL; } + fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0); + if (fifo_depth < 0) { + printf("DWMMC%d: Can't get FIFO depth\n", idx); + return -EINVAL; + } + + /* Allocate the host */ + host = calloc(1, sizeof(*host)); + if (!host) + return -ENOMEM; + host->name = "SOCFPGA DWMMC"; - host->ioaddr = (void *)regbase; + host->ioaddr = (void *)reg_base; host->buswidth = bus_width; host->clksel = socfpga_dwmci_clksel; - host->dev_index = index; - /* fixed clock divide by 4 which due to the SDMMC wrapper */ + host->dev_index = idx; + /* Fixed clock divide by 4 which due to the SDMMC wrapper */ host->bus_hz = clk; host->fifoth_val = MSIZE(0x2) | - RX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2 - 1) | - TX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2); + RX_WMARK(fifo_depth / 2 - 1) | TX_WMARK(fifo_depth / 2); return add_dwmci(host, host->bus_hz, 400000); } +static int socfpga_dwmci_process_node(const void *blob, int nodes[], + int count) +{ + int i, node, ret; + + for (i = 0; i < count; i++) { + node = nodes[i]; + if (node <= 0) + continue; + + ret = socfpga_dwmci_of_probe(blob, node, i); + if (ret) { + printf("%s: failed to decode dev %d\n", __func__, i); + return ret; + } + } + return 0; +} + +int socfpga_dwmmc_init(const void *blob) +{ + int nodes[2]; /* Max. two controllers. */ + int ret, count; + + count = fdtdec_find_aliases_for_id(blob, "mmc", + COMPAT_ALTERA_SOCFPGA_DWMMC, + nodes, ARRAY_SIZE(nodes)); + + ret = socfpga_dwmci_process_node(blob, nodes, count); + + return ret; +} -- cgit v1.2.1