[U-Boot] [PATCH 07/21] mmc: tegra: Add DM_MMC support to Tegra MMC driver

Stephen Warren swarren at wwwdotorg.org
Tue Sep 13 18:45:48 CEST 2016


From: Tom Warren <twarren at nvidia.com>

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 at samsung.com>
Signed-off-by: Tom Warren <twarren at 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 at nvidia.com>
---
 arch/arm/include/asm/arch-tegra/mmc.h |  11 --
 arch/arm/mach-tegra/Kconfig           |   1 +
 arch/arm/mach-tegra/board186.c        |   8 -
 arch/arm/mach-tegra/board2.c          |  16 --
 drivers/mmc/tegra_mmc.c               | 277 +++++++++-------------------------
 5 files changed, 70 insertions(+), 243 deletions(-)
 delete mode 100644 arch/arm/include/asm/arch-tegra/mmc.h

diff --git a/arch/arm/include/asm/arch-tegra/mmc.h b/arch/arm/include/asm/arch-tegra/mmc.h
deleted file mode 100644
index c2d52b297743..000000000000
--- a/arch/arm/include/asm/arch-tegra/mmc.h
+++ /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_ */
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 1eaf40627254..448c31902d50 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -15,6 +15,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
diff --git a/arch/arm/mach-tegra/board186.c b/arch/arm/mach-tegra/board186.c
index 356556618907..691c3fd98dab 100644
--- a/arch/arm/mach-tegra/board186.c
+++ b/arch/arm/mach-tegra/board186.c
@@ -6,7 +6,6 @@
 
 #include <common.h>
 #include <asm/arch/tegra.h>
-#include <asm/arch-tegra/mmc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -34,10 +33,3 @@ int board_late_init(void)
 {
 	return tegra_soc_board_init_late();
 }
-
-int board_mmc_init(bd_t *bd)
-{
-	tegra_mmc_init();
-
-	return 0;
-}
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c
index 3f87891b25c8..cb9503f8e61f 100644
--- a/arch/arm/mach-tegra/board2.c
+++ b/arch/arm/mach-tegra/board2.c
@@ -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.
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 9287f1c3424f..7b9628adb96e 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -2,7 +2,7 @@
  * (C) Copyright 2009 SAMSUNG Electronics
  * Minkyu Kang <mk7.kang at samsung.com>
  * Jaehoon Chung <jh80.chung at 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),
+};
-- 
2.9.3



More information about the U-Boot mailing list