mmc: tegra: Add DM_MMC support to Tegra MMC driver
authorTom Warren <twarren@nvidia.com>
Tue, 13 Sep 2016 16:45:48 +0000 (10:45 -0600)
committerTom Warren <twarren@nvidia.com>
Tue, 27 Sep 2016 16:11:01 +0000 (09:11 -0700)
Convert the Tegra MMC driver to DM_MMC. Support for non-DM is removed
to avoid ifdefs in the code. DM_MMC is now enabled for all Tegra builds.

Cc: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Tom Warren <twarren@nvidia.com>
(swarren, fixed some NULL pointer dereferences, removed extraneous
changes, rebased on various other changes, removed non-DM support etc.)
Signed-off-by: Stephen Warren <swarren@nvidia.com>
arch/arm/include/asm/arch-tegra/mmc.h [deleted file]
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/board186.c
arch/arm/mach-tegra/board2.c
drivers/mmc/tegra_mmc.c

diff --git a/arch/arm/include/asm/arch-tegra/mmc.h b/arch/arm/include/asm/arch-tegra/mmc.h
deleted file mode 100644 (file)
index c2d52b2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (c) 2011, Google Inc. All rights reserved.
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#ifndef _TEGRA_MMC_H_
-#define _TEGRA_MMC_H_
-
-void tegra_mmc_init(void);
-
-#endif /* _TEGRA_MMC_H_ */
index 76909ee2d9b2d59121318c4564da23980ade9754..fb4b32e8b797c8463a7e8affa2ba1b513cb1fb7e 100644 (file)
@@ -27,6 +27,7 @@ config TEGRA_COMMON
        select DM_GPIO
        select DM_I2C
        select DM_KEYBOARD
+       select DM_MMC
        select DM_PCI
        select DM_PCI_COMPAT
        select DM_PWM
index 8b762059a01fec25443ef85dd99ffc6c70f0c7e8..a071758afe7b7b132f7d828eb81133b8d0690b52 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <common.h>
 #include <asm/arch/tegra.h>
-#include <asm/arch-tegra/mmc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -29,10 +28,3 @@ int board_late_init(void)
 {
        return 0;
 }
-
-int board_mmc_init(bd_t *bd)
-{
-       tegra_mmc_init();
-
-       return 0;
-}
index 3f87891b25c808c7064e57a75988509ba54aca95..cb9503f8e61f332397b960c592f640a76af4a773 100644 (file)
@@ -32,9 +32,6 @@
 #ifdef CONFIG_USB_EHCI_TEGRA
 #include <usb.h>
 #endif
-#ifdef CONFIG_TEGRA_MMC
-#include <asm/arch-tegra/mmc.h>
-#endif
 #include <asm/arch-tegra/xusb-padctl.h>
 #include <power/as3722.h>
 #include <i2c.h>
@@ -234,19 +231,6 @@ int board_late_init(void)
        return 0;
 }
 
-#if defined(CONFIG_TEGRA_MMC)
-/* this is a weak define that we are overriding */
-int board_mmc_init(bd_t *bd)
-{
-       debug("%s called\n", __func__);
-
-       debug("%s: init MMC\n", __func__);
-       tegra_mmc_init();
-
-       return 0;
-}
-#endif /* MMC */
-
 /*
  * In some SW environments, a memory carve-out exists to house a secure
  * monitor, a trusted OS, and/or various statically allocated media buffers.
index 9287f1c3424f02ad38e96ddbd93f3cbf470498ad..7b9628adb96efc5a0ddb35e180a6643635c1ad6f 100644 (file)
@@ -2,7 +2,7 @@
  * (C) Copyright 2009 SAMSUNG Electronics
  * Minkyu Kang <mk7.kang@samsung.com>
  * Jaehoon Chung <jh80.chung@samsung.com>
- * Portions Copyright 2011-2015 NVIDIA Corporation
+ * Portions Copyright 2011-2016 NVIDIA Corporation
  *
  * SPDX-License-Identifier:    GPL-2.0+
  */
@@ -17,7 +17,6 @@
 #include <asm/arch/clock.h>
 #include <asm/arch-tegra/clk_rst.h>
 #endif
-#include <asm/arch-tegra/mmc.h>
 #include <asm/arch-tegra/tegra_mmc.h>
 #include <mmc.h>
 
@@ -34,9 +33,6 @@ DECLARE_GLOBAL_DATA_PTR;
 
 struct tegra_mmc_priv {
        struct tegra_mmc *reg;
-       int id;                 /* device id/number, 0-3 */
-       int enabled;            /* 1 to enable, 0 to disable */
-       int width;              /* Bus Width, 1, 4 or 8 */
 #ifdef CONFIG_TEGRA186
        struct reset_ctl reset_ctl;
        struct clk clk;
@@ -49,14 +45,9 @@ struct tegra_mmc_priv {
        unsigned int version;   /* SDHCI spec. version */
        unsigned int clock;     /* Current clock (MHz) */
        struct mmc_config cfg;  /* mmc configuration */
+       struct mmc *mmc;
 };
 
-struct tegra_mmc_priv mmc_host[CONFIG_SYS_MMC_MAX_DEVICE];
-
-#if !CONFIG_IS_ENABLED(OF_CONTROL)
-#error "Please enable device tree support to use this driver"
-#endif
-
 static void tegra_mmc_set_power(struct tegra_mmc_priv *priv,
                                unsigned short power)
 {
@@ -534,11 +525,11 @@ static void tegra_mmc_reset(struct tegra_mmc_priv *priv, struct mmc *mmc)
        tegra_mmc_pad_init(priv);
 }
 
-static int tegra_mmc_core_init(struct mmc *mmc)
+static int tegra_mmc_init(struct mmc *mmc)
 {
        struct tegra_mmc_priv *priv = mmc->priv;
        unsigned int mask;
-       debug(" mmc_core_init called\n");
+       debug(" tegra_mmc_init called\n");
 
        tegra_mmc_reset(priv, mmc);
 
@@ -594,59 +585,30 @@ static int tegra_mmc_getcd(struct mmc *mmc)
 static const struct mmc_ops tegra_mmc_ops = {
        .send_cmd       = tegra_mmc_send_cmd,
        .set_ios        = tegra_mmc_set_ios,
-       .init           = tegra_mmc_core_init,
+       .init           = tegra_mmc_init,
        .getcd          = tegra_mmc_getcd,
 };
 
-static int do_mmc_init(int dev_index, bool removable)
+static int tegra_mmc_probe(struct udevice *dev)
 {
-       struct tegra_mmc_priv *priv;
-       struct mmc *mmc;
+       struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+       struct tegra_mmc_priv *priv = dev_get_priv(dev);
+       int bus_width;
 #ifdef CONFIG_TEGRA186
        int ret;
 #endif
 
-       /* DT should have been read & host config filled in */
-       priv = &mmc_host[dev_index];
-       if (!priv->enabled)
-               return -1;
-
-       debug(" do_mmc_init: index %d, bus width %d pwr_gpio %d cd_gpio %d\n",
-             dev_index, priv->width, gpio_get_number(&priv->pwr_gpio),
-             gpio_get_number(&priv->cd_gpio));
-
-       priv->clock = 0;
-
-#ifdef CONFIG_TEGRA186
-       ret = reset_assert(&priv->reset_ctl);
-       if (ret)
-               return ret;
-       ret = clk_enable(&priv->clk);
-       if (ret)
-               return ret;
-       ret = clk_set_rate(&priv->clk, 20000000);
-       if (IS_ERR_VALUE(ret))
-               return ret;
-       ret = reset_deassert(&priv->reset_ctl);
-       if (ret)
-               return ret;
-#else
-       clock_start_periph_pll(priv->mmc_id, CLOCK_ID_PERIPH, 20000000);
-#endif
-
-       if (dm_gpio_is_valid(&priv->pwr_gpio))
-               dm_gpio_set_value(&priv->pwr_gpio, 1);
-
-       memset(&priv->cfg, 0, sizeof(priv->cfg));
-
        priv->cfg.name = "Tegra SD/MMC";
        priv->cfg.ops = &tegra_mmc_ops;
 
+       bus_width = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "bus-width",
+                                  1);
+
        priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
        priv->cfg.host_caps = 0;
-       if (priv->width == 8)
+       if (bus_width == 8)
                priv->cfg.host_caps |= MMC_MODE_8BIT;
-       if (priv->width >= 4)
+       if (bus_width >= 4)
                priv->cfg.host_caps |= MMC_MODE_4BIT;
        priv->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
 
@@ -661,177 +623,76 @@ static int do_mmc_init(int dev_index, bool removable)
 
        priv->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
-       mmc = mmc_create(&priv->cfg, priv);
-       mmc->block_dev.removable = removable;
-       if (mmc == NULL)
-               return -1;
-
-       return 0;
-}
-
-/**
- * Get the host address and peripheral ID for a node.
- *
- * @param blob         fdt blob
- * @param node         Device index (0-3)
- * @param priv         Structure to fill in (reg, width, mmc_id)
- */
-static int mmc_get_config(const void *blob, int node,
-                         struct tegra_mmc_priv *priv, bool *removablep)
-{
-       debug("%s: node = %d\n", __func__, node);
-
-       priv->enabled = fdtdec_get_is_enabled(blob, node);
-
-       priv->reg = (struct tegra_mmc *)fdtdec_get_addr(blob, node, "reg");
-       if ((fdt_addr_t)priv->reg == FDT_ADDR_T_NONE) {
-               debug("%s: no sdmmc base reg info found\n", __func__);
-               return -FDT_ERR_NOTFOUND;
-       }
+       priv->reg = (void *)dev_get_addr(dev);
 
 #ifdef CONFIG_TEGRA186
-       {
-               /*
-                * FIXME: This variable should go away when the MMC device
-                * actually is a udevice.
-                */
-               struct udevice dev;
-               int ret;
-               dev.of_offset = node;
-               ret = reset_get_by_name(&dev, "sdhci", &priv->reset_ctl);
-               if (ret) {
-                       debug("reset_get_by_name() failed: %d\n", ret);
-                       return ret;
-               }
-               ret = clk_get_by_index(&dev, 0, &priv->clk);
-               if (ret) {
-                       debug("clk_get_by_index() failed: %d\n", ret);
-                       return ret;
-               }
+       ret = reset_get_by_name(dev, "sdhci", &priv->reset_ctl);
+       if (ret) {
+               debug("reset_get_by_name() failed: %d\n", ret);
+               return ret;
        }
+       ret = clk_get_by_index(dev, 0, &priv->clk);
+       if (ret) {
+               debug("clk_get_by_index() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = reset_assert(&priv->reset_ctl);
+       if (ret)
+               return ret;
+       ret = clk_enable(&priv->clk);
+       if (ret)
+               return ret;
+       ret = clk_set_rate(&priv->clk, 20000000);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+       ret = reset_deassert(&priv->reset_ctl);
+       if (ret)
+               return ret;
 #else
-       priv->mmc_id = clock_decode_periph_id(blob, node);
+       priv->mmc_id = clock_decode_periph_id(gd->fdt_blob, dev->of_offset);
        if (priv->mmc_id == PERIPH_ID_NONE) {
                debug("%s: could not decode periph id\n", __func__);
                return -FDT_ERR_NOTFOUND;
        }
-#endif
 
-       /*
-        * NOTE: mmc->bus_width is determined by mmc.c dynamically.
-        * TBD: Override it with this value?
-        */
-       priv->width = fdtdec_get_int(blob, node, "bus-width", 0);
-       if (!priv->width)
-               debug("%s: no sdmmc width found\n", __func__);
-
-       /* These GPIOs are optional */
-       gpio_request_by_name_nodev(blob, node, "cd-gpios", 0, &priv->cd_gpio,
-                                  GPIOD_IS_IN);
-       gpio_request_by_name_nodev(blob, node, "wp-gpios", 0, &priv->wp_gpio,
-                                  GPIOD_IS_IN);
-       gpio_request_by_name_nodev(blob, node, "power-gpios", 0,
-                                  &priv->pwr_gpio, GPIOD_IS_OUT);
-       *removablep = !fdtdec_get_bool(blob, node, "non-removable");
-
-       debug("%s: found controller at %p, width = %d, periph_id = %d\n",
-               __func__, priv->reg, priv->width,
-#ifndef CONFIG_TEGRA186
-               priv->mmc_id
-#else
-               -1
+       clock_start_periph_pll(priv->mmc_id, CLOCK_ID_PERIPH, 20000000);
 #endif
-       );
-       return 0;
-}
 
-/*
- * Process a list of nodes, adding them to our list of SDMMC ports.
- *
- * @param blob          fdt blob
- * @param node_list     list of nodes to process (any <=0 are ignored)
- * @param count         number of nodes to process
- * @return 0 if ok, -1 on error
- */
-static int process_nodes(const void *blob, int node_list[], int count)
-{
-       struct tegra_mmc_priv *priv;
-       bool removable;
-       int i, node;
-
-       debug("%s: count = %d\n", __func__, count);
+       /* These GPIOs are optional */
+       gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
+                            GPIOD_IS_IN);
+       gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio,
+                            GPIOD_IS_IN);
+       gpio_request_by_name(dev, "power-gpios", 0,
+                            &priv->pwr_gpio, GPIOD_IS_OUT);
+       if (dm_gpio_is_valid(&priv->pwr_gpio))
+               dm_gpio_set_value(&priv->pwr_gpio, 1);
 
-       /* build mmc_host[] for each controller */
-       for (i = 0; i < count; i++) {
-               node = node_list[i];
-               if (node <= 0)
-                       continue;
+       priv->mmc = mmc_create(&priv->cfg, priv);
+       if (priv->mmc == NULL)
+               return -1;
 
-               priv = &mmc_host[i];
-               priv->id = i;
+       priv->mmc->dev = dev;
+       upriv->mmc = priv->mmc;
 
-               if (mmc_get_config(blob, node, priv, &removable)) {
-                       printf("%s: failed to decode dev %d\n", __func__, i);
-                       return -1;
-               }
-               do_mmc_init(i, removable);
-       }
        return 0;
 }
 
-void tegra_mmc_init(void)
-{
-       int node_list[CONFIG_SYS_MMC_MAX_DEVICE], count;
-       const void *blob = gd->fdt_blob;
-       debug("%s entry\n", __func__);
-
-       /* See if any Tegra186 MMC controllers are present */
-       count = fdtdec_find_aliases_for_id(blob, "mmc",
-               COMPAT_NVIDIA_TEGRA186_SDMMC, node_list,
-               CONFIG_SYS_MMC_MAX_DEVICE);
-       debug("%s: count of Tegra186 sdhci nodes is %d\n", __func__, count);
-       if (process_nodes(blob, node_list, count)) {
-               printf("%s: Error processing T186 mmc node(s)!\n", __func__);
-               return;
-       }
-
-       /* See if any Tegra210 MMC controllers are present */
-       count = fdtdec_find_aliases_for_id(blob, "mmc",
-               COMPAT_NVIDIA_TEGRA210_SDMMC, node_list,
-               CONFIG_SYS_MMC_MAX_DEVICE);
-       debug("%s: count of Tegra210 sdhci nodes is %d\n", __func__, count);
-       if (process_nodes(blob, node_list, count)) {
-               printf("%s: Error processing T210 mmc node(s)!\n", __func__);
-               return;
-       }
-
-       /* See if any Tegra124 MMC controllers are present */
-       count = fdtdec_find_aliases_for_id(blob, "mmc",
-               COMPAT_NVIDIA_TEGRA124_SDMMC, node_list,
-               CONFIG_SYS_MMC_MAX_DEVICE);
-       debug("%s: count of Tegra124 sdhci nodes is %d\n", __func__, count);
-       if (process_nodes(blob, node_list, count)) {
-               printf("%s: Error processing T124 mmc node(s)!\n", __func__);
-               return;
-       }
-
-       /* See if any Tegra30 MMC controllers are present */
-       count = fdtdec_find_aliases_for_id(blob, "mmc",
-               COMPAT_NVIDIA_TEGRA30_SDMMC, node_list,
-               CONFIG_SYS_MMC_MAX_DEVICE);
-       debug("%s: count of T30 sdhci nodes is %d\n", __func__, count);
-       if (process_nodes(blob, node_list, count)) {
-               printf("%s: Error processing T30 mmc node(s)!\n", __func__);
-               return;
-       }
+static const struct udevice_id tegra_mmc_ids[] = {
+       { .compatible = "nvidia,tegra20-sdhci" },
+       { .compatible = "nvidia,tegra30-sdhci" },
+       { .compatible = "nvidia,tegra114-sdhci" },
+       { .compatible = "nvidia,tegra124-sdhci" },
+       { .compatible = "nvidia,tegra210-sdhci" },
+       { .compatible = "nvidia,tegra186-sdhci" },
+       { }
+};
 
-       /* Now look for any Tegra20 MMC controllers */
-       count = fdtdec_find_aliases_for_id(blob, "mmc",
-               COMPAT_NVIDIA_TEGRA20_SDMMC, node_list,
-               CONFIG_SYS_MMC_MAX_DEVICE);
-       debug("%s: count of T20 sdhci nodes is %d\n", __func__, count);
-       if (process_nodes(blob, node_list, count)) {
-               printf("%s: Error processing T20 mmc node(s)!\n", __func__);
-               return;
-       }
-}
+U_BOOT_DRIVER(tegra_mmc_drv) = {
+       .name           = "tegra_mmc",
+       .id             = UCLASS_MMC,
+       .of_match       = tegra_mmc_ids,
+       .probe          = tegra_mmc_probe,
+       .priv_auto_alloc_size = sizeof(struct tegra_mmc_priv),
+};