tegra2: Modify MMC driver to handle power and cd GPIOs

Pass the GPIO numbers for power and card detect to tegra2_mmc_init(), and
modify that function to perform all required GPIO initialization. This
removes the need for board files to perform these operations.

Move board_mmc_getcd() into tegra2_mmc.c now that the driver knows which
GPIOs to use.

Update affected call-sites in seaboard.c and harmony.c. Note that this
change should make all SD ports work on Harmony, since the required GPIO
setup is now being performed.

v4: Fix prototype of tegra2_mmc_init() in board.h to match driver change.
    Remove prototype of gpio_config_mmc() from board.h

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Cc: Andy Fleming <afleming@gmail.com>
Tested-by: Simon Glass <sjg@chromium.org>
Acked-by: Simon Glass <sjg@chromium.org>
Acked-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Tom Warren <twarren@nvidia.com>
diff --git a/drivers/mmc/tegra2_mmc.c b/drivers/mmc/tegra2_mmc.c
index ccf48bb..035a868 100644
--- a/drivers/mmc/tegra2_mmc.c
+++ b/drivers/mmc/tegra2_mmc.c
@@ -21,6 +21,7 @@
 
 #include <common.h>
 #include <mmc.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/clk_rst.h>
 #include <asm/arch/clock.h>
@@ -473,20 +474,37 @@
 	return 0;
 }
 
-static int tegra2_mmc_initialize(int dev_index, int bus_width)
+int tegra2_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio)
 {
 	struct mmc_host *host;
+	char gpusage[12]; /* "SD/MMCn PWR" or "SD/MMCn CD" */
 	struct mmc *mmc;
 
-	debug(" mmc_initialize called\n");
+	debug(" tegra2_mmc_init: index %d, bus width %d "
+		"pwr_gpio %d cd_gpio %d\n",
+		dev_index, bus_width, pwr_gpio, cd_gpio);
 
 	host = &mmc_host[dev_index];
 
 	host->clock = 0;
+	host->pwr_gpio = pwr_gpio;
+	host->cd_gpio = cd_gpio;
 	tegra2_get_setup(host, dev_index);
 
 	clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000);
 
+	if (host->pwr_gpio >= 0) {
+		sprintf(gpusage, "SD/MMC%d PWR", dev_index);
+		gpio_request(host->pwr_gpio, gpusage);
+		gpio_direction_output(host->pwr_gpio, 1);
+	}
+
+	if (host->cd_gpio >= 0) {
+		sprintf(gpusage, "SD/MMC%d CD", dev_index);
+		gpio_request(host->cd_gpio, gpusage);
+		gpio_direction_input(host->cd_gpio);
+	}
+
 	mmc = &mmc_dev[dev_index];
 
 	sprintf(mmc->name, "Tegra2 SD/MMC");
@@ -518,9 +536,21 @@
 	return 0;
 }
 
-int tegra2_mmc_init(int dev_index, int bus_width)
+/* this is a weak define that we are overriding */
+int board_mmc_getcd(u8 *cd, struct mmc *mmc)
 {
-	debug(" tegra2_mmc_init: index %d, bus width %d\n",
-		dev_index, bus_width);
-	return tegra2_mmc_initialize(dev_index, bus_width);
+	struct mmc_host *host = (struct mmc_host *)mmc->priv;
+
+	debug("board_mmc_getcd called\n");
+
+	*cd = 1; /* Assume card is inserted, or eMMC */
+
+	if (IS_SD(mmc)) {
+		if (host->cd_gpio >= 0) {
+			if (gpio_get_value(host->cd_gpio))
+				*cd = 0;
+		}
+	}
+
+	return 0;
 }