Ver código fonte

Merge branch 'hsmmc-init' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6 into devel

Russell King 16 anos atrás
pai
commit
cd4348339c
33 arquivos alterados com 1282 adições e 548 exclusões
  1. 32 57
      arch/arm/mach-omap1/board-h2-mmc.c
  2. 15 10
      arch/arm/mach-omap1/board-h2.c
  3. 29 71
      arch/arm/mach-omap1/board-h3-mmc.c
  4. 0 10
      arch/arm/mach-omap1/board-h3.c
  5. 42 8
      arch/arm/mach-omap1/board-innovator.c
  6. 59 15
      arch/arm/mach-omap1/board-nokia770.c
  7. 0 1
      arch/arm/mach-omap1/board-palmte.c
  8. 0 11
      arch/arm/mach-omap1/board-palmz71.c
  9. 11 69
      arch/arm/mach-omap1/board-sx1-mmc.c
  10. 0 10
      arch/arm/mach-omap1/board-sx1.c
  11. 1 9
      arch/arm/mach-omap1/board-voiceblue.c
  12. 1 2
      arch/arm/mach-omap1/clock.h
  13. 90 0
      arch/arm/mach-omap1/devices.c
  14. 10 5
      arch/arm/mach-omap2/Makefile
  15. 48 0
      arch/arm/mach-omap2/board-2430sdp.c
  16. 0 11
      arch/arm/mach-omap2/board-apollon.c
  17. 0 11
      arch/arm/mach-omap2/board-generic.c
  18. 0 11
      arch/arm/mach-omap2/board-h4.c
  19. 39 1
      arch/arm/mach-omap2/board-ldp.c
  20. 90 0
      arch/arm/mach-omap2/board-omap3beagle.c
  21. 32 0
      arch/arm/mach-omap2/board-omap3pandora.c
  22. 43 0
      arch/arm/mach-omap2/board-overo.c
  23. 3 6
      arch/arm/mach-omap2/clock24xx.h
  24. 4 6
      arch/arm/mach-omap2/clock34xx.h
  25. 169 0
      arch/arm/mach-omap2/devices.c
  26. 408 0
      arch/arm/mach-omap2/mmc-twl4030.c
  27. 29 0
      arch/arm/mach-omap2/mmc-twl4030.h
  28. 35 190
      arch/arm/plat-omap/devices.c
  29. 3 3
      arch/arm/plat-omap/include/mach/board-h2.h
  30. 0 22
      arch/arm/plat-omap/include/mach/board.h
  31. 17 0
      arch/arm/plat-omap/include/mach/control.h
  32. 68 6
      arch/arm/plat-omap/include/mach/mmc.h
  33. 4 3
      drivers/mmc/host/omap.c

+ 32 - 57
arch/arm/mach-omap1/board-h2-mmc.c

@@ -12,90 +12,68 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/platform_device.h>
+
+#include <linux/i2c/tps65010.h>
+
 #include <mach/mmc.h>
 #include <mach/gpio.h>
 
-#ifdef CONFIG_MMC_OMAP
-static int slot_cover_open;
-static struct device *mmc_device;
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
-static int h2_mmc_set_power(struct device *dev, int slot, int power_on,
+static int mmc_set_power(struct device *dev, int slot, int power_on,
 				int vdd)
 {
-#ifdef CONFIG_MMC_DEBUG
-	dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
-		power_on ? "on" : "off", vdd);
-#endif
-	if (slot != 0) {
-		dev_err(dev, "No such slot %d\n", slot + 1);
-		return -ENODEV;
-	}
+	if (power_on)
+		gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 1);
+	else
+		gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0);
 
 	return 0;
 }
 
-static int h2_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
+static int mmc_late_init(struct device *dev)
 {
-#ifdef CONFIG_MMC_DEBUG
-	dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1,
-		bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
-#endif
-	if (slot != 0) {
-		dev_err(dev, "No such slot %d\n", slot + 1);
-		return -ENODEV;
-	}
+	int ret;
 
-	return 0;
-}
+	ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
+	if (ret < 0)
+		return ret;
 
-static int h2_mmc_get_cover_state(struct device *dev, int slot)
-{
-	BUG_ON(slot != 0);
-
-	return slot_cover_open;
-}
-
-void h2_mmc_slot_cover_handler(void *arg, int state)
-{
-	if (mmc_device == NULL)
-		return;
-
-	slot_cover_open = state;
-	omap_mmc_notify_cover_event(mmc_device, 0, state);
-}
-
-static int h2_mmc_late_init(struct device *dev)
-{
-	int ret = 0;
-
-	mmc_device = dev;
+	gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0);
 
 	return ret;
 }
 
-static void h2_mmc_cleanup(struct device *dev)
+static void mmc_shutdown(struct device *dev)
 {
+	gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
 }
 
-static struct omap_mmc_platform_data h2_mmc_data = {
+/*
+ * H2 could use the following functions tested:
+ * - mmc_get_cover_state that uses OMAP_MPUIO(1)
+ * - mmc_get_wp that uses OMAP_MPUIO(3)
+ */
+static struct omap_mmc_platform_data mmc1_data = {
 	.nr_slots                       = 1,
-	.switch_slot                    = NULL,
-	.init                           = h2_mmc_late_init,
-	.cleanup                        = h2_mmc_cleanup,
+	.init				= mmc_late_init,
+	.shutdown			= mmc_shutdown,
+	.dma_mask			= 0xffffffff,
 	.slots[0]       = {
-		.set_power              = h2_mmc_set_power,
-		.set_bus_mode           = h2_mmc_set_bus_mode,
-		.get_ro                 = NULL,
-		.get_cover_state        = h2_mmc_get_cover_state,
+		.set_power              = mmc_set_power,
 		.ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
 					  MMC_VDD_32_33 | MMC_VDD_33_34,
 		.name                   = "mmcblk",
 	},
 };
 
+static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
+
 void __init h2_mmc_init(void)
 {
-	omap_set_mmc_info(1, &h2_mmc_data);
+	mmc_data[0] = &mmc1_data;
+	omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC);
 }
 
 #else
@@ -104,7 +82,4 @@ void __init h2_mmc_init(void)
 {
 }
 
-void h2_mmc_slot_cover_handler(void *arg, int state)
-{
-}
 #endif

+ 15 - 10
arch/arm/mach-omap1/board-h2.c

@@ -345,10 +345,25 @@ static void __init h2_init_smc91x(void)
 	}
 }
 
+static int tps_setup(struct i2c_client *client, void *context)
+{
+	tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V |
+				TPS_LDO1_ENABLE | TPS_VLDO1_3_0V);
+
+	return 0;
+}
+
+static struct tps65010_board tps_board = {
+	.base		= H2_TPS_GPIO_BASE,
+	.outmask	= 0x0f,
+	.setup		= tps_setup,
+};
+
 static struct i2c_board_info __initdata h2_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("tps65010", 0x48),
 		.irq            = OMAP_GPIO_IRQ(58),
+		.platform_data	= &tps_board,
 	}, {
 		I2C_BOARD_INFO("isp1301_omap", 0x2d),
 		.irq		= OMAP_GPIO_IRQ(2),
@@ -378,15 +393,6 @@ static struct omap_usb_config h2_usb_config __initdata = {
 	.pins[1]	= 3,
 };
 
-static struct omap_mmc_config h2_mmc_config __initdata = {
-	.mmc[0] = {
-		.enabled	= 1,
-		.wire4		= 1,
-	},
-};
-
-extern struct omap_mmc_platform_data h2_mmc_data;
-
 static struct omap_uart_config h2_uart_config __initdata = {
 	.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
 };
@@ -397,7 +403,6 @@ static struct omap_lcd_config h2_lcd_config __initdata = {
 
 static struct omap_board_config_kernel h2_config[] __initdata = {
 	{ OMAP_TAG_USB,		&h2_usb_config },
-	{ OMAP_TAG_MMC,		&h2_mmc_config },
 	{ OMAP_TAG_UART,	&h2_uart_config },
 	{ OMAP_TAG_LCD,		&h2_lcd_config },
 };

+ 29 - 71
arch/arm/mach-omap1/board-h3-mmc.c

@@ -12,94 +12,55 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/platform_device.h>
+
+#include <linux/i2c/tps65010.h>
+
 #include <mach/mmc.h>
 #include <mach/gpio.h>
 
-#ifdef CONFIG_MMC_OMAP
-static int slot_cover_open;
-static struct device *mmc_device;
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
-static int h3_mmc_set_power(struct device *dev, int slot, int power_on,
+static int mmc_set_power(struct device *dev, int slot, int power_on,
 				int vdd)
 {
-#ifdef CONFIG_MMC_DEBUG
-	dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
-		power_on ? "on" : "off", vdd);
-#endif
-	if (slot != 0) {
-		dev_err(dev, "No such slot %d\n", slot + 1);
-		return -ENODEV;
-	}
+	if (power_on)
+		gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 1);
+	else
+		gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0);
 
 	return 0;
 }
 
-static int h3_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
-{
-	int ret = 0;
-
-#ifdef CONFIG_MMC_DEBUG
-	dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1,
-		bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
-#endif
-	if (slot != 0) {
-		dev_err(dev, "No such slot %d\n", slot + 1);
-		return -ENODEV;
-	}
-
-	/* Treated on upper level */
-
-	return bus_mode;
-}
-
-static int h3_mmc_get_cover_state(struct device *dev, int slot)
-{
-	BUG_ON(slot != 0);
-
-	return slot_cover_open;
-}
-
-void h3_mmc_slot_cover_handler(void *arg, int state)
-{
-	if (mmc_device == NULL)
-		return;
-
-	slot_cover_open = state;
-	omap_mmc_notify_cover_event(mmc_device, 0, state);
-}
-
-static int h3_mmc_late_init(struct device *dev)
-{
-	int ret = 0;
-
-	mmc_device = dev;
-
-	return ret;
-}
-
-static void h3_mmc_cleanup(struct device *dev)
-{
-}
-
-static struct omap_mmc_platform_data h3_mmc_data = {
+/*
+ * H3 could use the following functions tested:
+ * - mmc_get_cover_state that uses OMAP_MPUIO(1)
+ * - mmc_get_wp that maybe uses OMAP_MPUIO(3)
+ */
+static struct omap_mmc_platform_data mmc1_data = {
 	.nr_slots                       = 1,
-	.switch_slot                    = NULL,
-	.init                           = h3_mmc_late_init,
-	.cleanup                        = h3_mmc_cleanup,
+	.dma_mask			= 0xffffffff,
 	.slots[0]       = {
-		.set_power              = h3_mmc_set_power,
-		.set_bus_mode           = h3_mmc_set_bus_mode,
-		.get_ro                 = NULL,
-		.get_cover_state        = h3_mmc_get_cover_state,
+		.set_power              = mmc_set_power,
 		.ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
 					  MMC_VDD_32_33 | MMC_VDD_33_34,
 		.name                   = "mmcblk",
 	},
 };
 
+static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
+
 void __init h3_mmc_init(void)
 {
-	omap_set_mmc_info(1, &h3_mmc_data);
+	int ret;
+
+	ret = gpio_request(H3_TPS_GPIO_MMC_PWR_EN, "MMC power");
+	if (ret < 0)
+		return;
+	gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0);
+
+	mmc_data[0] = &mmc1_data;
+	omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC);
 }
 
 #else
@@ -108,7 +69,4 @@ void __init h3_mmc_init(void)
 {
 }
 
-void h3_mmc_slot_cover_handler(void *arg, int state)
-{
-}
 #endif

+ 0 - 10
arch/arm/mach-omap1/board-h3.c

@@ -447,15 +447,6 @@ static struct omap_usb_config h3_usb_config __initdata = {
 	.pins[1]	= 3,
 };
 
-static struct omap_mmc_config h3_mmc_config __initdata = {
-	.mmc[0] = {
-		.enabled	= 1,
-		.wire4		= 1,
-       },
-};
-
-extern struct omap_mmc_platform_data h3_mmc_data;
-
 static struct omap_uart_config h3_uart_config __initdata = {
 	.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
 };
@@ -466,7 +457,6 @@ static struct omap_lcd_config h3_lcd_config __initdata = {
 
 static struct omap_board_config_kernel h3_config[] __initdata = {
 	{ OMAP_TAG_USB,		&h3_usb_config },
-	{ OMAP_TAG_MMC,		&h3_mmc_config },
 	{ OMAP_TAG_UART,	&h3_uart_config },
 	{ OMAP_TAG_LCD,		&h3_lcd_config },
 };

+ 42 - 8
arch/arm/mach-omap1/board-innovator.c

@@ -39,6 +39,7 @@
 #include <mach/common.h>
 #include <mach/mcbsp.h>
 #include <mach/omap-alsa.h>
+#include <mach/mmc.h>
 
 static int innovator_keymap[] = {
 	KEY(0, 0, KEY_F1),
@@ -360,16 +361,49 @@ static struct omap_lcd_config innovator1610_lcd_config __initdata = {
 };
 #endif
 
-static struct omap_mmc_config innovator_mmc_config __initdata = {
-	.mmc [0] = {
-		.enabled 	= 1,
-		.wire4		= 1,
-		.wp_pin		= OMAP_MPUIO(3),
-		.power_pin	= -1,	/* FPGA F3 UIO42 */
-		.switch_pin	= -1,	/* FPGA F4 UIO43 */
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+static int mmc_set_power(struct device *dev, int slot, int power_on,
+				int vdd)
+{
+	if (power_on)
+		fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
+				OMAP1510_FPGA_POWER);
+	else
+		fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
+				OMAP1510_FPGA_POWER);
+
+	return 0;
+}
+
+/*
+ * Innovator could use the following functions tested:
+ * - mmc_get_wp that uses OMAP_MPUIO(3)
+ * - mmc_get_cover_state that uses FPGA F4 UIO43
+ */
+static struct omap_mmc_platform_data mmc1_data = {
+	.nr_slots                       = 1,
+	.slots[0]       = {
+		.set_power		= mmc_set_power,
+		.wires			= 4,
+		.name                   = "mmcblk",
 	},
 };
 
+static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
+
+void __init innovator_mmc_init(void)
+{
+	mmc_data[0] = &mmc1_data;
+	omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC);
+}
+
+#else
+static inline void innovator_mmc_init(void)
+{
+}
+#endif
+
 static struct omap_uart_config innovator_uart_config __initdata = {
 	.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
 };
@@ -377,7 +411,6 @@ static struct omap_uart_config innovator_uart_config __initdata = {
 static struct omap_board_config_kernel innovator_config[] = {
 	{ OMAP_TAG_USB,         NULL },
 	{ OMAP_TAG_LCD,		NULL },
-	{ OMAP_TAG_MMC,		&innovator_mmc_config },
 	{ OMAP_TAG_UART,	&innovator_uart_config },
 };
 
@@ -412,6 +445,7 @@ static void __init innovator_init(void)
 	omap_board_config_size = ARRAY_SIZE(innovator_config);
 	omap_serial_init();
 	omap_register_i2c_bus(1, 100, NULL, 0);
+	innovator_mmc_init();
 }
 
 static void __init innovator_map_io(void)

+ 59 - 15
arch/arm/mach-omap1/board-nokia770.c

@@ -35,6 +35,7 @@
 #include <mach/aic23.h>
 #include <mach/omapfb.h>
 #include <mach/lcd_mipid.h>
+#include <mach/mmc.h>
 
 #define ADS7846_PENDOWN_GPIO	15
 
@@ -173,26 +174,68 @@ static struct omap_usb_config nokia770_usb_config __initdata = {
 	.pins[0]	= 6,
 };
 
-static struct omap_mmc_config nokia770_mmc_config __initdata = {
-	.mmc[0] = {
-		.enabled	= 0,
-		.wire4		= 0,
-		.wp_pin		= -1,
-		.power_pin	= -1,
-		.switch_pin	= -1,
-	},
-	.mmc[1] = {
-		.enabled	= 0,
-		.wire4		= 0,
-		.wp_pin		= -1,
-		.power_pin	= -1,
-		.switch_pin	= -1,
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+#define NOKIA770_GPIO_MMC_POWER		41
+#define NOKIA770_GPIO_MMC_SWITCH	23
+
+static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on,
+				int vdd)
+{
+	if (power_on)
+		gpio_set_value(NOKIA770_GPIO_MMC_POWER, 1);
+	else
+		gpio_set_value(NOKIA770_GPIO_MMC_POWER, 0);
+
+	return 0;
+}
+
+static int nokia770_mmc_get_cover_state(struct device *dev, int slot)
+{
+	return gpio_get_value(NOKIA770_GPIO_MMC_SWITCH);
+}
+
+static struct omap_mmc_platform_data nokia770_mmc2_data = {
+	.nr_slots                       = 1,
+	.dma_mask			= 0xffffffff,
+	.slots[0]       = {
+		.set_power		= nokia770_mmc_set_power,
+		.get_cover_state	= nokia770_mmc_get_cover_state,
+		.name                   = "mmcblk",
 	},
 };
 
+static struct omap_mmc_platform_data *nokia770_mmc_data[OMAP16XX_NR_MMC];
+
+static void __init nokia770_mmc_init(void)
+{
+	int ret;
+
+	ret = gpio_request(NOKIA770_GPIO_MMC_POWER, "MMC power");
+	if (ret < 0)
+		return;
+	gpio_direction_output(NOKIA770_GPIO_MMC_POWER, 0);
+
+	ret = gpio_request(NOKIA770_GPIO_MMC_SWITCH, "MMC cover");
+	if (ret < 0) {
+		gpio_free(NOKIA770_GPIO_MMC_POWER);
+		return;
+	}
+	gpio_direction_input(NOKIA770_GPIO_MMC_SWITCH);
+
+	/* Only the second MMC controller is used */
+	nokia770_mmc_data[1] = &nokia770_mmc2_data;
+	omap1_init_mmc(nokia770_mmc_data, OMAP16XX_NR_MMC);
+}
+
+#else
+static inline void nokia770_mmc_init(void)
+{
+}
+#endif
+
 static struct omap_board_config_kernel nokia770_config[] __initdata = {
 	{ OMAP_TAG_USB,		NULL },
-	{ OMAP_TAG_MMC,		&nokia770_mmc_config },
 };
 
 #if	defined(CONFIG_OMAP_DSP)
@@ -335,6 +378,7 @@ static void __init omap_nokia770_init(void)
 	omap_dsp_init();
 	ads7846_dev_init();
 	mipid_dev_init();
+	nokia770_mmc_init();
 }
 
 static void __init omap_nokia770_map_io(void)

+ 0 - 1
arch/arm/mach-omap1/board-palmte.c

@@ -316,7 +316,6 @@ static void palmte_get_power_status(struct apm_power_info *info, int *battery)
 
 static struct omap_board_config_kernel palmte_config[] __initdata = {
 	{ OMAP_TAG_USB,		&palmte_usb_config },
-	{ OMAP_TAG_MMC,		&palmte_mmc_config },
 	{ OMAP_TAG_LCD,		&palmte_lcd_config },
 	{ OMAP_TAG_UART,	&palmte_uart_config },
 };

+ 0 - 11
arch/arm/mach-omap1/board-palmz71.c

@@ -267,16 +267,6 @@ static struct omap_usb_config palmz71_usb_config __initdata = {
 	.pins[0]	= 2,
 };
 
-static struct omap_mmc_config palmz71_mmc_config __initdata = {
-	.mmc[0] = {
-		.enabled	= 1,
-		.wire4		= 0,
-		.wp_pin		= PALMZ71_MMC_WP_GPIO,
-		.power_pin	= -1,
-		.switch_pin	= PALMZ71_MMC_IN_GPIO,
-	},
-};
-
 static struct omap_lcd_config palmz71_lcd_config __initdata = {
 	.ctrl_name = "internal",
 };
@@ -287,7 +277,6 @@ static struct omap_uart_config palmz71_uart_config __initdata = {
 
 static struct omap_board_config_kernel palmz71_config[] __initdata = {
 	{OMAP_TAG_USB,	&palmz71_usb_config},
-	{OMAP_TAG_MMC,	&palmz71_mmc_config},
 	{OMAP_TAG_LCD,	&palmz71_lcd_config},
 	{OMAP_TAG_UART,	&palmz71_uart_config},
 };

+ 11 - 69
arch/arm/mach-omap1/board-sx1-mmc.c

@@ -12,30 +12,20 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/platform_device.h>
+
 #include <mach/hardware.h>
 #include <mach/mmc.h>
 #include <mach/gpio.h>
 
-#ifdef CONFIG_MMC_OMAP
-static int slot_cover_open;
-static struct device *mmc_device;
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
-static int sx1_mmc_set_power(struct device *dev, int slot, int power_on,
+static int mmc_set_power(struct device *dev, int slot, int power_on,
 				int vdd)
 {
 	int err;
 	u8 dat = 0;
 
-#ifdef CONFIG_MMC_DEBUG
-	dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
-		power_on ? "on" : "off", vdd);
-#endif
-
-	if (slot != 0) {
-		dev_err(dev, "No such slot %d\n", slot + 1);
-		return -ENODEV;
-	}
-
 	err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
 	if (err < 0)
 		return err;
@@ -48,68 +38,23 @@ static int sx1_mmc_set_power(struct device *dev, int slot, int power_on,
 	return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
 }
 
-static int sx1_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
-{
-#ifdef CONFIG_MMC_DEBUG
-	dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1,
-		bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
-#endif
-	if (slot != 0) {
-		dev_err(dev, "No such slot %d\n", slot + 1);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static int sx1_mmc_get_cover_state(struct device *dev, int slot)
-{
-	BUG_ON(slot != 0);
-
-	return slot_cover_open;
-}
-
-void sx1_mmc_slot_cover_handler(void *arg, int state)
-{
-	if (mmc_device == NULL)
-		return;
-
-	slot_cover_open = state;
-	omap_mmc_notify_cover_event(mmc_device, 0, state);
-}
-
-static int sx1_mmc_late_init(struct device *dev)
-{
-	int ret = 0;
-
-	mmc_device = dev;
-
-	return ret;
-}
-
-static void sx1_mmc_cleanup(struct device *dev)
-{
-}
-
-static struct omap_mmc_platform_data sx1_mmc_data = {
+/* Cover switch is at OMAP_MPUIO(3) */
+static struct omap_mmc_platform_data mmc1_data = {
 	.nr_slots                       = 1,
-	.switch_slot                    = NULL,
-	.init                           = sx1_mmc_late_init,
-	.cleanup                        = sx1_mmc_cleanup,
 	.slots[0]       = {
-		.set_power              = sx1_mmc_set_power,
-		.set_bus_mode           = sx1_mmc_set_bus_mode,
-		.get_ro                 = NULL,
-		.get_cover_state        = sx1_mmc_get_cover_state,
+		.set_power              = mmc_set_power,
 		.ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
 					  MMC_VDD_32_33 | MMC_VDD_33_34,
 		.name                   = "mmcblk",
 	},
 };
 
+static struct omap_mmc_platform_data *mmc_data[OMAP15XX_NR_MMC];
+
 void __init sx1_mmc_init(void)
 {
-	omap_set_mmc_info(1, &sx1_mmc_data);
+	mmc_data[0] = &mmc1_data;
+	omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC);
 }
 
 #else
@@ -118,7 +63,4 @@ void __init sx1_mmc_init(void)
 {
 }
 
-void sx1_mmc_slot_cover_handler(void *arg, int state)
-{
-}
 #endif

+ 0 - 10
arch/arm/mach-omap1/board-sx1.c

@@ -378,15 +378,6 @@ static struct omap_usb_config sx1_usb_config __initdata = {
 	.pins[2]	= 0,
 };
 
-/*----------- MMC -------------------------*/
-
-static struct omap_mmc_config sx1_mmc_config __initdata = {
-	.mmc [0] = {
-		.enabled	= 1,
-		.wire4		= 0,
-	},
-};
-
 /*----------- LCD -------------------------*/
 
 static struct platform_device sx1_lcd_device = {
@@ -414,7 +405,6 @@ static struct omap_uart_config sx1_uart_config __initdata = {
 
 static struct omap_board_config_kernel sx1_config[] __initdata = {
 	{ OMAP_TAG_USB,	&sx1_usb_config },
-	{ OMAP_TAG_MMC,	&sx1_mmc_config },
 	{ OMAP_TAG_LCD,	&sx1_lcd_config },
 	{ OMAP_TAG_UART,	&sx1_uart_config },
 };

+ 1 - 9
arch/arm/mach-omap1/board-voiceblue.c

@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/notifier.h>
@@ -140,21 +141,12 @@ static struct omap_usb_config voiceblue_usb_config __initdata = {
 	.pins[2]	= 6,
 };
 
-static struct omap_mmc_config voiceblue_mmc_config __initdata = {
-	.mmc[0] = {
-		.enabled	= 1,
-		.power_pin	= 2,
-		.switch_pin	= -1,
-	},
-};
-
 static struct omap_uart_config voiceblue_uart_config __initdata = {
 	.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
 };
 
 static struct omap_board_config_kernel voiceblue_config[] = {
 	{ OMAP_TAG_USB,  &voiceblue_usb_config },
-	{ OMAP_TAG_MMC,  &voiceblue_mmc_config },
 	{ OMAP_TAG_UART, &voiceblue_uart_config },
 };
 

+ 1 - 2
arch/arm/mach-omap1/clock.h

@@ -705,7 +705,6 @@ static struct clk bclk_16xx = {
 
 static struct clk mmc1_ck = {
 	.name		= "mmc_ck",
-	.id		= 1,
 	/* Functional clock is direct from ULPD, interface clock is ARMPER */
 	.parent		= &armper_ck.clk,
 	.rate		= 48000000,
@@ -720,7 +719,7 @@ static struct clk mmc1_ck = {
 
 static struct clk mmc2_ck = {
 	.name		= "mmc_ck",
-	.id		= 2,
+	.id		= 1,
 	/* Functional clock is direct from ULPD, interface clock is ARMPER */
 	.parent		= &armper_ck.clk,
 	.rate		= 48000000,

+ 90 - 0
arch/arm/mach-omap1/devices.c

@@ -22,6 +22,7 @@
 #include <mach/board.h>
 #include <mach/mux.h>
 #include <mach/gpio.h>
+#include <mach/mmc.h>
 
 /*-------------------------------------------------------------------------*/
 
@@ -99,6 +100,95 @@ static inline void omap_init_mbox(void)
 static inline void omap_init_mbox(void) { }
 #endif
 
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+static inline void omap1_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
+			int controller_nr)
+{
+	if (controller_nr == 0) {
+		omap_cfg_reg(MMC_CMD);
+		omap_cfg_reg(MMC_CLK);
+		omap_cfg_reg(MMC_DAT0);
+		if (cpu_is_omap1710()) {
+			omap_cfg_reg(M15_1710_MMC_CLKI);
+			omap_cfg_reg(P19_1710_MMC_CMDDIR);
+			omap_cfg_reg(P20_1710_MMC_DATDIR0);
+		}
+		if (mmc_controller->slots[0].wires == 4) {
+			omap_cfg_reg(MMC_DAT1);
+			/* NOTE: DAT2 can be on W10 (here) or M15 */
+			if (!mmc_controller->slots[0].nomux)
+				omap_cfg_reg(MMC_DAT2);
+			omap_cfg_reg(MMC_DAT3);
+		}
+	}
+
+	/* Block 2 is on newer chips, and has many pinout options */
+	if (cpu_is_omap16xx() && controller_nr == 1) {
+		if (!mmc_controller->slots[1].nomux) {
+			omap_cfg_reg(Y8_1610_MMC2_CMD);
+			omap_cfg_reg(Y10_1610_MMC2_CLK);
+			omap_cfg_reg(R18_1610_MMC2_CLKIN);
+			omap_cfg_reg(W8_1610_MMC2_DAT0);
+			if (mmc_controller->slots[1].wires == 4) {
+				omap_cfg_reg(V8_1610_MMC2_DAT1);
+				omap_cfg_reg(W15_1610_MMC2_DAT2);
+				omap_cfg_reg(R10_1610_MMC2_DAT3);
+			}
+
+			/* These are needed for the level shifter */
+			omap_cfg_reg(V9_1610_MMC2_CMDDIR);
+			omap_cfg_reg(V5_1610_MMC2_DATDIR0);
+			omap_cfg_reg(W19_1610_MMC2_DATDIR1);
+		}
+
+		/* Feedback clock must be set on OMAP-1710 MMC2 */
+		if (cpu_is_omap1710())
+			omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24),
+					MOD_CONF_CTRL_1);
+	}
+}
+
+void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
+			int nr_controllers)
+{
+	int i;
+
+	for (i = 0; i < nr_controllers; i++) {
+		unsigned long base, size;
+		unsigned int irq = 0;
+
+		if (!mmc_data[i])
+			continue;
+
+		omap1_mmc_mux(mmc_data[i], i);
+
+		switch (i) {
+		case 0:
+			base = OMAP1_MMC1_BASE;
+			irq = INT_MMC;
+			break;
+		case 1:
+			if (!cpu_is_omap16xx())
+				return;
+			base = OMAP1_MMC2_BASE;
+			irq = INT_1610_MMC2;
+			break;
+		default:
+			continue;
+		}
+		size = OMAP1_MMC_SIZE;
+
+		omap_mmc_add(i, base, size, irq, mmc_data[i]);
+	};
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 #if defined(CONFIG_OMAP_STI)
 
 #define OMAP1_STI_BASE		0xfffea000

+ 10 - 5
arch/arm/mach-omap2/Makefile

@@ -27,10 +27,15 @@ obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
-obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o
+obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o \
+					   mmc-twl4030.o
 obj-$(CONFIG_MACH_OMAP_APOLLON)		+= board-apollon.o
-obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o
-obj-$(CONFIG_MACH_OMAP_LDP)		+= board-ldp.o
-obj-$(CONFIG_MACH_OVERO)		+= board-overo.o
-obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o
+obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o \
+					   mmc-twl4030.o
+obj-$(CONFIG_MACH_OMAP_LDP)		+= board-ldp.o \
+					   mmc-twl4030.o
+obj-$(CONFIG_MACH_OVERO)		+= board-overo.o \
+					   mmc-twl4030.o
+obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o \
+					   mmc-twl4030.o
 

+ 48 - 0
arch/arm/mach-omap2/board-2430sdp.c

@@ -19,6 +19,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
+#include <linux/i2c/twl4030.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -35,6 +36,7 @@
 #include <mach/common.h>
 #include <mach/gpmc.h>
 
+#include "mmc-twl4030.h"
 
 #define	SDP2430_FLASH_CS	0
 #define	SDP2430_SMC91X_CS	5
@@ -197,12 +199,58 @@ static struct omap_board_config_kernel sdp2430_config[] = {
 	{OMAP_TAG_UART, &sdp2430_uart_config},
 };
 
+
+static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+};
+
+static struct twl4030_platform_data sdp2430_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.gpio		= &sdp2430_gpio_data,
+};
+
+static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags = I2C_CLIENT_WAKE,
+		.irq = INT_24XX_SYS_NIRQ,
+		.platform_data = &sdp2430_twldata,
+	},
+};
+
+static int __init omap2430_i2c_init(void)
+{
+	omap_register_i2c_bus(1, 400, NULL, 0);
+	omap_register_i2c_bus(2, 2600, sdp2430_i2c_boardinfo,
+			ARRAY_SIZE(sdp2430_i2c_boardinfo));
+	return 0;
+}
+
+static struct twl4030_hsmmc_info mmc[] __initdata = {
+	{
+		.mmc		= 1,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+		.ext_clock	= 1,
+	},
+	{}	/* Terminator */
+};
+
 static void __init omap_2430sdp_init(void)
 {
+	omap2430_i2c_init();
+
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
 	omap_board_config = sdp2430_config;
 	omap_board_config_size = ARRAY_SIZE(sdp2430_config);
 	omap_serial_init();
+	twl4030_mmc_init(mmc);
 }
 
 static void __init omap_2430sdp_map_io(void)

+ 0 - 11
arch/arm/mach-omap2/board-apollon.c

@@ -261,16 +261,6 @@ static struct omap_uart_config apollon_uart_config __initdata = {
 	.enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2),
 };
 
-static struct omap_mmc_config apollon_mmc_config __initdata = {
-	.mmc [0] = {
-		.enabled 	= 1,
-		.wire4		= 1,
-		.wp_pin		= -1,
-		.power_pin	= -1,
-		.switch_pin	= -1,
-	},
-};
-
 static struct omap_usb_config apollon_usb_config __initdata = {
 	.register_dev	= 1,
 	.hmc_mode	= 0x14,	/* 0:dev 1:host1 2:disable */
@@ -284,7 +274,6 @@ static struct omap_lcd_config apollon_lcd_config __initdata = {
 
 static struct omap_board_config_kernel apollon_config[] = {
 	{ OMAP_TAG_UART,	&apollon_uart_config },
-	{ OMAP_TAG_MMC,		&apollon_mmc_config },
 	{ OMAP_TAG_USB,		&apollon_usb_config },
 	{ OMAP_TAG_LCD,		&apollon_lcd_config },
 };

+ 0 - 11
arch/arm/mach-omap2/board-generic.c

@@ -41,19 +41,8 @@ static struct omap_uart_config generic_uart_config __initdata = {
 	.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
 };
 
-static struct omap_mmc_config generic_mmc_config __initdata = {
-	.mmc [0] = {
-		.enabled 	= 0,
-		.wire4		= 0,
-		.wp_pin		= -1,
-		.power_pin	= -1,
-		.switch_pin	= -1,
-	},
-};
-
 static struct omap_board_config_kernel generic_config[] = {
 	{ OMAP_TAG_UART,	&generic_uart_config },
-	{ OMAP_TAG_MMC,		&generic_mmc_config },
 };
 
 static void __init omap_generic_init(void)

+ 0 - 11
arch/arm/mach-omap2/board-h4.c

@@ -373,23 +373,12 @@ static struct omap_uart_config h4_uart_config __initdata = {
 	.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
 };
 
-static struct omap_mmc_config h4_mmc_config __initdata = {
-	.mmc [0] = {
-		.enabled	= 1,
-		.wire4		= 1,
-		.wp_pin		= -1,
-		.power_pin	= -1,
-		.switch_pin	= -1,
-	},
-};
-
 static struct omap_lcd_config h4_lcd_config __initdata = {
 	.ctrl_name	= "internal",
 };
 
 static struct omap_board_config_kernel h4_config[] = {
 	{ OMAP_TAG_UART,	&h4_uart_config },
-	{ OMAP_TAG_MMC,		&h4_mmc_config },
 	{ OMAP_TAG_LCD,		&h4_lcd_config },
 };
 

+ 39 - 1
arch/arm/mach-omap2/board-ldp.c

@@ -21,6 +21,7 @@
 #include <linux/clk.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/i2c/twl4030.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -38,6 +39,8 @@
 #include <asm/delay.h>
 #include <mach/control.h>
 
+#include "mmc-twl4030.h"
+
 #define SDP3430_SMC91X_CS	3
 
 static struct resource ldp_smc911x_resources[] = {
@@ -109,14 +112,48 @@ static struct omap_board_config_kernel ldp_config[] __initdata = {
 	{ OMAP_TAG_UART,	&ldp_uart_config },
 };
 
+static struct twl4030_gpio_platform_data ldp_gpio_data = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+};
+
+static struct twl4030_platform_data ldp_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.gpio		= &ldp_gpio_data,
+};
+
+static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags = I2C_CLIENT_WAKE,
+		.irq = INT_34XX_SYS_NIRQ,
+		.platform_data = &ldp_twldata,
+	},
+};
+
 static int __init omap_i2c_init(void)
 {
-	omap_register_i2c_bus(1, 2600, NULL, 0);
+	omap_register_i2c_bus(1, 2600, ldp_i2c_boardinfo,
+			ARRAY_SIZE(ldp_i2c_boardinfo));
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, NULL, 0);
 	return 0;
 }
 
+static struct twl4030_hsmmc_info mmc[] __initdata = {
+	{
+		.mmc		= 1,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+	{}	/* Terminator */
+};
+
 static void __init omap_ldp_init(void)
 {
 	omap_i2c_init();
@@ -124,6 +161,7 @@ static void __init omap_ldp_init(void)
 	omap_board_config = ldp_config;
 	omap_board_config_size = ARRAY_SIZE(ldp_config);
 	omap_serial_init();
+	twl4030_mmc_init(mmc);
 }
 
 static void __init omap_ldp_map_io(void)

+ 90 - 0
arch/arm/mach-omap2/board-omap3beagle.c

@@ -38,7 +38,9 @@
 #include <mach/common.h>
 #include <mach/gpmc.h>
 #include <mach/nand.h>
+#include <mach/mux.h>
 
+#include "mmc-twl4030.h"
 
 #define GPMC_CS0_BASE  0x60
 #define GPMC_CS_SIZE   0x30
@@ -103,6 +105,78 @@ static struct omap_uart_config omap3_beagle_uart_config __initdata = {
 	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
 };
 
+static struct twl4030_hsmmc_info mmc[] = {
+	{
+		.mmc		= 1,
+		.wires		= 8,
+		.gpio_wp	= 29,
+	},
+	{}	/* Terminator */
+};
+
+static struct gpio_led gpio_leds[];
+
+static int beagle_twl_gpio_setup(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
+
+	/* REVISIT: need ehci-omap hooks for external VBUS
+	 * power switch and overcurrent detect
+	 */
+
+	gpio_request(gpio + 1, "EHCI_nOC");
+	gpio_direction_input(gpio + 1);
+
+	/* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+	gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
+	gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
+
+	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+
+	return 0;
+}
+
+static struct twl4030_gpio_platform_data beagle_gpio_data = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.use_leds	= true,
+	.pullups	= BIT(1),
+	.pulldowns	= BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
+				| BIT(15) | BIT(16) | BIT(17),
+	.setup		= beagle_twl_gpio_setup,
+};
+
+static struct twl4030_platform_data beagle_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.gpio		= &beagle_gpio_data,
+};
+
+static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags = I2C_CLIENT_WAKE,
+		.irq = INT_34XX_SYS_NIRQ,
+		.platform_data = &beagle_twldata,
+	},
+};
+
+static int __init omap3_beagle_i2c_init(void)
+{
+	omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
+			ARRAY_SIZE(beagle_i2c_boardinfo));
+#ifdef CONFIG_I2C2_OMAP_BEAGLE
+	omap_register_i2c_bus(2, 400, NULL, 0);
+#endif
+	omap_register_i2c_bus(3, 400, NULL, 0);
+	return 0;
+}
+
 static void __init omap3_beagle_init_irq(void)
 {
 	omap2_init_common_hw();
@@ -130,6 +204,11 @@ static struct gpio_led gpio_leds[] = {
 		.default_trigger	= "mmc0",
 		.gpio			= 149,
 	},
+	{
+		.name			= "beagleboard::pmu_stat",
+		.gpio			= -EINVAL,	/* gets replaced */
+		.active_low		= true,
+	},
 };
 
 static struct gpio_led_platform_data gpio_led_info = {
@@ -218,11 +297,22 @@ static void __init omap3beagle_flash_init(void)
 
 static void __init omap3_beagle_init(void)
 {
+	omap3_beagle_i2c_init();
 	platform_add_devices(omap3_beagle_devices,
 			ARRAY_SIZE(omap3_beagle_devices));
 	omap_board_config = omap3_beagle_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
 	omap_serial_init();
+
+	omap_cfg_reg(AH8_34XX_GPIO29);
+	mmc[0].gpio_cd = gpio + 0;
+	twl4030_mmc_init(mmc);
+
+	omap_cfg_reg(J25_34XX_GPIO170);
+	gpio_request(170, "DVI_nPD");
+	/* REVISIT leave DVI powered down until it's needed ... */
+	gpio_direction_output(170, true);
+
 	omap3beagle_flash_init();
 }
 

+ 32 - 0
arch/arm/mach-omap2/board-omap3pandora.c

@@ -35,16 +35,48 @@
 #include <mach/hardware.h>
 #include <mach/mcspi.h>
 
+#include "mmc-twl4030.h"
+
 #define OMAP3_PANDORA_TS_GPIO		94
 
+static struct twl4030_hsmmc_info omap3pandora_mmc[] = {
+	{
+		.mmc		= 1,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= 126,
+		.ext_clock	= 0,
+	},
+	{
+		.mmc		= 2,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= 127,
+		.ext_clock	= 1,
+	},
+	{}	/* Terminator */
+};
+
 static struct omap_uart_config omap3pandora_uart_config __initdata = {
 	.enabled_uarts	= (1 << 2), /* UART3 */
 };
 
+static int omap3pandora_twl_gpio_setup(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	/* gpio + {0,1} is "mmc{0,1}_cd" (input/IRQ) */
+	omap3pandora_mmc[0].gpio_cd = gpio + 0;
+	omap3pandora_mmc[1].gpio_cd = gpio + 1;
+	twl4030_mmc_init(omap3pandora_mmc);
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data omap3pandora_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.setup		= omap3pandora_twl_gpio_setup,
 };
 
 static struct twl4030_usb_data omap3pandora_usb_data = {

+ 43 - 0
arch/arm/mach-omap2/board-overo.c

@@ -26,6 +26,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/i2c/twl4030.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -44,6 +45,8 @@
 #include <mach/hardware.h>
 #include <mach/nand.h>
 
+#include "mmc-twl4030.h"
+
 #define NAND_BLOCK_SIZE SZ_128K
 #define GPMC_CS0_BASE  0x60
 #define GPMC_CS_SIZE   0x30
@@ -139,8 +142,31 @@ static struct omap_uart_config overo_uart_config __initdata = {
 	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
 };
 
+static struct twl4030_gpio_platform_data overo_gpio_data = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+};
+
+static struct twl4030_platform_data overo_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+	.gpio		= &overo_gpio_data,
+};
+
+static struct i2c_board_info __initdata overo_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags = I2C_CLIENT_WAKE,
+		.irq = INT_34XX_SYS_NIRQ,
+		.platform_data = &overo_twldata,
+	},
+};
+
 static int __init overo_i2c_init(void)
 {
+	omap_register_i2c_bus(1, 2600, overo_i2c_boardinfo,
+			ARRAY_SIZE(overo_i2c_boardinfo));
 	/* i2c2 pins are used for gpio */
 	omap_register_i2c_bus(3, 400, NULL, 0);
 	return 0;
@@ -171,6 +197,22 @@ static struct platform_device *overo_devices[] __initdata = {
 	&overo_lcd_device,
 };
 
+static struct twl4030_hsmmc_info mmc[] __initdata = {
+	{
+		.mmc		= 1,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+	{
+		.mmc		= 2,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+	{}	/* Terminator */
+};
+
 static void __init overo_init(void)
 {
 	overo_i2c_init();
@@ -178,6 +220,7 @@ static void __init overo_init(void)
 	omap_board_config = overo_config;
 	omap_board_config_size = ARRAY_SIZE(overo_config);
 	omap_serial_init();
+	twl4030_mmc_init(mmc);
 	overo_flash_init();
 
 	if ((gpio_request(OVERO_GPIO_W2W_NRESET,

+ 3 - 6
arch/arm/mach-omap2/clock24xx.h

@@ -2522,7 +2522,6 @@ static struct clk usbhs_ick = {
 
 static struct clk mmchs1_ick = {
 	.name		= "mmchs_ick",
-	.id		= 1,
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
@@ -2533,7 +2532,6 @@ static struct clk mmchs1_ick = {
 
 static struct clk mmchs1_fck = {
 	.name		= "mmchs_fck",
-	.id		= 1,
 	.parent		= &func_96m_ck,
 	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l3_clkdm",
@@ -2544,7 +2542,7 @@ static struct clk mmchs1_fck = {
 
 static struct clk mmchs2_ick = {
 	.name		= "mmchs_ick",
-	.id		= 2,
+	.id		= 1,
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
@@ -2555,7 +2553,7 @@ static struct clk mmchs2_ick = {
 
 static struct clk mmchs2_fck = {
 	.name		= "mmchs_fck",
-	.id		= 2,
+	.id		= 1,
 	.parent		= &func_96m_ck,
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
@@ -2595,7 +2593,6 @@ static struct clk mdm_intc_ick = {
 
 static struct clk mmchsdb1_fck = {
 	.name		= "mmchsdb_fck",
-	.id		= 1,
 	.parent		= &func_32k_ck,
 	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
@@ -2606,7 +2603,7 @@ static struct clk mmchsdb1_fck = {
 
 static struct clk mmchsdb2_fck = {
 	.name		= "mmchsdb_fck",
-	.id		= 2,
+	.id		= 1,
 	.parent		= &func_32k_ck,
 	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",

+ 4 - 6
arch/arm/mach-omap2/clock34xx.h

@@ -1374,7 +1374,7 @@ static struct clk core_96m_fck = {
 
 static struct clk mmchs3_fck = {
 	.name		= "mmchs_fck",
-	.id		= 3,
+	.id		= 2,
 	.parent		= &core_96m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
@@ -1385,7 +1385,7 @@ static struct clk mmchs3_fck = {
 
 static struct clk mmchs2_fck = {
 	.name		= "mmchs_fck",
-	.id		= 2,
+	.id		= 1,
 	.parent		= &core_96m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
@@ -1406,7 +1406,6 @@ static struct clk mspro_fck = {
 
 static struct clk mmchs1_fck = {
 	.name		= "mmchs_fck",
-	.id		= 1,
 	.parent		= &core_96m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
@@ -1722,7 +1721,7 @@ static struct clk usbtll_ick = {
 
 static struct clk mmchs3_ick = {
 	.name		= "mmchs_ick",
-	.id		= 3,
+	.id		= 2,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
@@ -1774,7 +1773,7 @@ static struct clk des2_ick = {
 
 static struct clk mmchs2_ick = {
 	.name		= "mmchs_ick",
-	.id		= 2,
+	.id		= 1,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
@@ -1785,7 +1784,6 @@ static struct clk mmchs2_ick = {
 
 static struct clk mmchs1_ick = {
 	.name		= "mmchs_ick",
-	.id		= 1,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,

+ 169 - 0
arch/arm/mach-omap2/devices.c

@@ -14,16 +14,19 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 
+#include <mach/control.h>
 #include <mach/tc.h>
 #include <mach/board.h>
 #include <mach/mux.h>
 #include <mach/gpio.h>
 #include <mach/eac.h>
+#include <mach/mmc.h>
 
 #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
 #define OMAP2_MBOX_BASE		IO_ADDRESS(OMAP24XX_MAILBOX_BASE)
@@ -295,6 +298,171 @@ static void omap_init_sha1_md5(void)
 static inline void omap_init_sha1_md5(void) { }
 #endif
 
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_OMAP3
+
+#define MMCHS_SYSCONFIG			0x0010
+#define MMCHS_SYSCONFIG_SWRESET		(1 << 1)
+#define MMCHS_SYSSTATUS			0x0014
+#define MMCHS_SYSSTATUS_RESETDONE	(1 << 0)
+
+static struct platform_device dummy_pdev = {
+	.dev = {
+		.bus = &platform_bus_type,
+	},
+};
+
+/**
+ * omap_hsmmc_reset() - Full reset of each HS-MMC controller
+ *
+ * Ensure that each MMC controller is fully reset.  Controllers
+ * left in an unknown state (by bootloader) may prevent retention
+ * or OFF-mode.  This is especially important in cases where the
+ * MMC driver is not enabled, _or_ built as a module.
+ *
+ * In order for reset to work, interface, functional and debounce
+ * clocks must be enabled.  The debounce clock comes from func_32k_clk
+ * and is not under SW control, so we only enable i- and f-clocks.
+ **/
+static void __init omap_hsmmc_reset(void)
+{
+	u32 i, nr_controllers = cpu_is_omap34xx() ? OMAP34XX_NR_MMC :
+		OMAP24XX_NR_MMC;
+
+	for (i = 0; i < nr_controllers; i++) {
+		u32 v, base = 0;
+		struct clk *iclk, *fclk;
+		struct device *dev = &dummy_pdev.dev;
+
+		switch (i) {
+		case 0:
+			base = OMAP2_MMC1_BASE;
+			break;
+		case 1:
+			base = OMAP2_MMC2_BASE;
+			break;
+		case 2:
+			base = OMAP3_MMC3_BASE;
+			break;
+		}
+
+		dummy_pdev.id = i;
+		iclk = clk_get(dev, "mmchs_ick");
+		if (iclk && clk_enable(iclk))
+			iclk = NULL;
+
+		fclk = clk_get(dev, "mmchs_fck");
+		if (fclk && clk_enable(fclk))
+			fclk = NULL;
+
+		if (!iclk || !fclk) {
+			printk(KERN_WARNING
+			       "%s: Unable to enable clocks for MMC%d, "
+			       "cannot reset.\n",  __func__, i);
+			break;
+		}
+
+		omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG);
+		v = omap_readl(base + MMCHS_SYSSTATUS);
+		while (!(omap_readl(base + MMCHS_SYSSTATUS) &
+			 MMCHS_SYSSTATUS_RESETDONE))
+			cpu_relax();
+
+		if (fclk) {
+			clk_disable(fclk);
+			clk_put(fclk);
+		}
+		if (iclk) {
+			clk_disable(iclk);
+			clk_put(iclk);
+		}
+	}
+}
+#else
+static inline void omap_hsmmc_reset(void) {}
+#endif
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
+	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
+
+static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
+			int controller_nr)
+{
+	if (cpu_is_omap2420() && controller_nr == 0) {
+		omap_cfg_reg(H18_24XX_MMC_CMD);
+		omap_cfg_reg(H15_24XX_MMC_CLKI);
+		omap_cfg_reg(G19_24XX_MMC_CLKO);
+		omap_cfg_reg(F20_24XX_MMC_DAT0);
+		omap_cfg_reg(F19_24XX_MMC_DAT_DIR0);
+		omap_cfg_reg(G18_24XX_MMC_CMD_DIR);
+		if (mmc_controller->slots[0].wires == 4) {
+			omap_cfg_reg(H14_24XX_MMC_DAT1);
+			omap_cfg_reg(E19_24XX_MMC_DAT2);
+			omap_cfg_reg(D19_24XX_MMC_DAT3);
+			omap_cfg_reg(E20_24XX_MMC_DAT_DIR1);
+			omap_cfg_reg(F18_24XX_MMC_DAT_DIR2);
+			omap_cfg_reg(E18_24XX_MMC_DAT_DIR3);
+		}
+
+		/*
+		 * Use internal loop-back in MMC/SDIO Module Input Clock
+		 * selection
+		 */
+		if (mmc_controller->slots[0].internal_clock) {
+			u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+			v |= (1 << 24);
+			omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
+		}
+	}
+}
+
+void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
+			int nr_controllers)
+{
+	int i;
+
+	for (i = 0; i < nr_controllers; i++) {
+		unsigned long base, size;
+		unsigned int irq = 0;
+
+		if (!mmc_data[i])
+			continue;
+
+		omap2_mmc_mux(mmc_data[i], i);
+
+		switch (i) {
+		case 0:
+			base = OMAP2_MMC1_BASE;
+			irq = INT_24XX_MMC_IRQ;
+			break;
+		case 1:
+			base = OMAP2_MMC2_BASE;
+			irq = INT_24XX_MMC2_IRQ;
+			break;
+		case 2:
+			if (!cpu_is_omap34xx())
+				return;
+			base = OMAP3_MMC3_BASE;
+			irq = INT_34XX_MMC3_IRQ;
+			break;
+		default:
+			continue;
+		}
+
+		if (cpu_is_omap2420())
+			size = OMAP2420_MMC_SIZE;
+		else
+			size = HSMMC_SIZE;
+
+		omap_mmc_add(i, base, size, irq, mmc_data[i]);
+	};
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 #if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE)
 #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
 #define OMAP_HDQ_BASE	0x480B2000
@@ -334,6 +502,7 @@ static int __init omap2_init_devices(void)
 	/* please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
+	omap_hsmmc_reset();
 	omap_init_mbox();
 	omap_init_mcspi();
 	omap_hdq_init();

+ 408 - 0
arch/arm/mach-omap2/mmc-twl4030.c

@@ -0,0 +1,408 @@
+/*
+ * linux/arch/arm/mach-omap2/mmc-twl4030.c
+ *
+ * Copyright (C) 2007-2008 Texas Instruments
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c/twl4030.h>
+
+#include <mach/hardware.h>
+#include <mach/control.h>
+#include <mach/mmc.h>
+#include <mach/board.h>
+
+#include "mmc-twl4030.h"
+
+#if defined(CONFIG_TWL4030_CORE) && \
+	(defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
+
+#define LDO_CLR			0x00
+#define VSEL_S2_CLR		0x40
+
+#define VMMC1_DEV_GRP		0x27
+#define VMMC1_CLR		0x00
+#define VMMC1_315V		0x03
+#define VMMC1_300V		0x02
+#define VMMC1_285V		0x01
+#define VMMC1_185V		0x00
+#define VMMC1_DEDICATED		0x2A
+
+#define VMMC2_DEV_GRP		0x2B
+#define VMMC2_CLR		0x40
+#define VMMC2_315V		0x0c
+#define VMMC2_300V		0x0b
+#define VMMC2_285V		0x0a
+#define VMMC2_260V		0x08
+#define VMMC2_185V		0x06
+#define VMMC2_DEDICATED		0x2E
+
+#define VMMC_DEV_GRP_P1		0x20
+
+static u16 control_pbias_offset;
+static u16 control_devconf1_offset;
+
+#define HSMMC_NAME_LEN	9
+
+static struct twl_mmc_controller {
+	struct omap_mmc_platform_data	*mmc;
+	u8		twl_vmmc_dev_grp;
+	u8		twl_mmc_dedicated;
+	char		name[HSMMC_NAME_LEN];
+} hsmmc[] = {
+	{
+		.twl_vmmc_dev_grp		= VMMC1_DEV_GRP,
+		.twl_mmc_dedicated		= VMMC1_DEDICATED,
+	},
+	{
+		.twl_vmmc_dev_grp		= VMMC2_DEV_GRP,
+		.twl_mmc_dedicated		= VMMC2_DEDICATED,
+	},
+};
+
+static int twl_mmc_card_detect(int irq)
+{
+	unsigned i;
+
+	for (i = 0; i < ARRAY_SIZE(hsmmc); i++) {
+		struct omap_mmc_platform_data *mmc;
+
+		mmc = hsmmc[i].mmc;
+		if (!mmc)
+			continue;
+		if (irq != mmc->slots[0].card_detect_irq)
+			continue;
+
+		/* NOTE: assumes card detect signal is active-low */
+		return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
+	}
+	return -ENOSYS;
+}
+
+static int twl_mmc_get_ro(struct device *dev, int slot)
+{
+	struct omap_mmc_platform_data *mmc = dev->platform_data;
+
+	/* NOTE: assumes write protect signal is active-high */
+	return gpio_get_value_cansleep(mmc->slots[0].gpio_wp);
+}
+
+/*
+ * MMC Slot Initialization.
+ */
+static int twl_mmc_late_init(struct device *dev)
+{
+	struct omap_mmc_platform_data *mmc = dev->platform_data;
+	int ret = 0;
+	int i;
+
+	ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd");
+	if (ret)
+		goto done;
+	ret = gpio_direction_input(mmc->slots[0].switch_pin);
+	if (ret)
+		goto err;
+
+	for (i = 0; i < ARRAY_SIZE(hsmmc); i++) {
+		if (hsmmc[i].name == mmc->slots[0].name) {
+			hsmmc[i].mmc = mmc;
+			break;
+		}
+	}
+
+	return 0;
+
+err:
+	gpio_free(mmc->slots[0].switch_pin);
+done:
+	mmc->slots[0].card_detect_irq = 0;
+	mmc->slots[0].card_detect = NULL;
+
+	dev_err(dev, "err %d configuring card detect\n", ret);
+	return ret;
+}
+
+static void twl_mmc_cleanup(struct device *dev)
+{
+	struct omap_mmc_platform_data *mmc = dev->platform_data;
+
+	gpio_free(mmc->slots[0].switch_pin);
+}
+
+#ifdef CONFIG_PM
+
+static int twl_mmc_suspend(struct device *dev, int slot)
+{
+	struct omap_mmc_platform_data *mmc = dev->platform_data;
+
+	disable_irq(mmc->slots[0].card_detect_irq);
+	return 0;
+}
+
+static int twl_mmc_resume(struct device *dev, int slot)
+{
+	struct omap_mmc_platform_data *mmc = dev->platform_data;
+
+	enable_irq(mmc->slots[0].card_detect_irq);
+	return 0;
+}
+
+#else
+#define twl_mmc_suspend	NULL
+#define twl_mmc_resume	NULL
+#endif
+
+/*
+ * Sets the MMC voltage in twl4030
+ */
+static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
+{
+	int ret;
+	u8 vmmc, dev_grp_val;
+
+	switch (1 << vdd) {
+	case MMC_VDD_35_36:
+	case MMC_VDD_34_35:
+	case MMC_VDD_33_34:
+	case MMC_VDD_32_33:
+	case MMC_VDD_31_32:
+	case MMC_VDD_30_31:
+		if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
+			vmmc = VMMC1_315V;
+		else
+			vmmc = VMMC2_315V;
+		break;
+	case MMC_VDD_29_30:
+		if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
+			vmmc = VMMC1_315V;
+		else
+			vmmc = VMMC2_300V;
+		break;
+	case MMC_VDD_27_28:
+	case MMC_VDD_26_27:
+		if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
+			vmmc = VMMC1_285V;
+		else
+			vmmc = VMMC2_285V;
+		break;
+	case MMC_VDD_25_26:
+	case MMC_VDD_24_25:
+	case MMC_VDD_23_24:
+	case MMC_VDD_22_23:
+	case MMC_VDD_21_22:
+	case MMC_VDD_20_21:
+		if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
+			vmmc = VMMC1_285V;
+		else
+			vmmc = VMMC2_260V;
+		break;
+	case MMC_VDD_165_195:
+		if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
+			vmmc = VMMC1_185V;
+		else
+			vmmc = VMMC2_185V;
+		break;
+	default:
+		vmmc = 0;
+		break;
+	}
+
+	if (vmmc)
+		dev_grp_val = VMMC_DEV_GRP_P1;	/* Power up */
+	else
+		dev_grp_val = LDO_CLR;		/* Power down */
+
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+					dev_grp_val, c->twl_vmmc_dev_grp);
+	if (ret)
+		return ret;
+
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+					vmmc, c->twl_mmc_dedicated);
+
+	return ret;
+}
+
+static int twl_mmc1_set_power(struct device *dev, int slot, int power_on,
+				int vdd)
+{
+	u32 reg;
+	int ret = 0;
+	struct twl_mmc_controller *c = &hsmmc[0];
+	struct omap_mmc_platform_data *mmc = dev->platform_data;
+
+	if (power_on) {
+		if (cpu_is_omap2430()) {
+			reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1);
+			if ((1 << vdd) >= MMC_VDD_30_31)
+				reg |= OMAP243X_MMC1_ACTIVE_OVERWRITE;
+			else
+				reg &= ~OMAP243X_MMC1_ACTIVE_OVERWRITE;
+			omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1);
+		}
+
+		if (mmc->slots[0].internal_clock) {
+			reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+			reg |= OMAP2_MMCSDIO1ADPCLKISEL;
+			omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0);
+		}
+
+		reg = omap_ctrl_readl(control_pbias_offset);
+		reg |= OMAP2_PBIASSPEEDCTRL0;
+		reg &= ~OMAP2_PBIASLITEPWRDNZ0;
+		omap_ctrl_writel(reg, control_pbias_offset);
+
+		ret = twl_mmc_set_voltage(c, vdd);
+
+		/* 100ms delay required for PBIAS configuration */
+		msleep(100);
+		reg = omap_ctrl_readl(control_pbias_offset);
+		reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0);
+		if ((1 << vdd) <= MMC_VDD_165_195)
+			reg &= ~OMAP2_PBIASLITEVMODE0;
+		else
+			reg |= OMAP2_PBIASLITEVMODE0;
+		omap_ctrl_writel(reg, control_pbias_offset);
+	} else {
+		reg = omap_ctrl_readl(control_pbias_offset);
+		reg &= ~OMAP2_PBIASLITEPWRDNZ0;
+		omap_ctrl_writel(reg, control_pbias_offset);
+
+		ret = twl_mmc_set_voltage(c, 0);
+
+		/* 100ms delay required for PBIAS configuration */
+		msleep(100);
+		reg = omap_ctrl_readl(control_pbias_offset);
+		reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 |
+			OMAP2_PBIASLITEVMODE0);
+		omap_ctrl_writel(reg, control_pbias_offset);
+	}
+
+	return ret;
+}
+
+static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vdd)
+{
+	int ret;
+	struct twl_mmc_controller *c = &hsmmc[1];
+	struct omap_mmc_platform_data *mmc = dev->platform_data;
+
+	if (power_on) {
+		if (mmc->slots[0].internal_clock) {
+			u32 reg;
+
+			reg = omap_ctrl_readl(control_devconf1_offset);
+			reg |= OMAP2_MMCSDIO2ADPCLKISEL;
+			omap_ctrl_writel(reg, control_devconf1_offset);
+		}
+		ret = twl_mmc_set_voltage(c, vdd);
+	} else {
+		ret = twl_mmc_set_voltage(c, 0);
+	}
+
+	return ret;
+}
+
+static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
+
+void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
+{
+	struct twl4030_hsmmc_info *c;
+	int nr_hsmmc = ARRAY_SIZE(hsmmc_data);
+
+	if (cpu_is_omap2430()) {
+		control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
+		control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1;
+		nr_hsmmc = 2;
+	} else {
+		control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
+		control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
+	}
+
+	for (c = controllers; c->mmc; c++) {
+		struct twl_mmc_controller *twl = hsmmc + c->mmc - 1;
+		struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1];
+
+		if (!c->mmc || c->mmc > nr_hsmmc) {
+			pr_debug("MMC%d: no such controller\n", c->mmc);
+			continue;
+		}
+		if (mmc) {
+			pr_debug("MMC%d: already configured\n", c->mmc);
+			continue;
+		}
+
+		mmc = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL);
+		if (!mmc) {
+			pr_err("Cannot allocate memory for mmc device!\n");
+			return;
+		}
+
+		sprintf(twl->name, "mmc%islot%i", c->mmc, 1);
+		mmc->slots[0].name = twl->name;
+		mmc->nr_slots = 1;
+		mmc->slots[0].ocr_mask = MMC_VDD_165_195 |
+					MMC_VDD_26_27 | MMC_VDD_27_28 |
+					MMC_VDD_29_30 |
+					MMC_VDD_30_31 | MMC_VDD_31_32;
+		mmc->slots[0].wires = c->wires;
+		mmc->slots[0].internal_clock = !c->ext_clock;
+		mmc->dma_mask = 0xffffffff;
+
+		/* note: twl4030 card detect GPIOs normally switch VMMCx ... */
+		if (gpio_is_valid(c->gpio_cd)) {
+			mmc->init = twl_mmc_late_init;
+			mmc->cleanup = twl_mmc_cleanup;
+			mmc->suspend = twl_mmc_suspend;
+			mmc->resume = twl_mmc_resume;
+
+			mmc->slots[0].switch_pin = c->gpio_cd;
+			mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd);
+			mmc->slots[0].card_detect = twl_mmc_card_detect;
+		} else
+			mmc->slots[0].switch_pin = -EINVAL;
+
+		/* write protect normally uses an OMAP gpio */
+		if (gpio_is_valid(c->gpio_wp)) {
+			gpio_request(c->gpio_wp, "mmc_wp");
+			gpio_direction_input(c->gpio_wp);
+
+			mmc->slots[0].gpio_wp = c->gpio_wp;
+			mmc->slots[0].get_ro = twl_mmc_get_ro;
+		} else
+			mmc->slots[0].gpio_wp = -EINVAL;
+
+		/* NOTE:  we assume OMAP's MMC1 and MMC2 use
+		 * the TWL4030's VMMC1 and VMMC2, respectively;
+		 * and that OMAP's MMC3 isn't used.
+		 */
+
+		switch (c->mmc) {
+		case 1:
+			mmc->slots[0].set_power = twl_mmc1_set_power;
+			break;
+		case 2:
+			mmc->slots[0].set_power = twl_mmc2_set_power;
+			break;
+		default:
+			pr_err("MMC%d configuration not supported!\n", c->mmc);
+			continue;
+		}
+		hsmmc_data[c->mmc - 1] = mmc;
+	}
+
+	omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC);
+}
+
+#endif

+ 29 - 0
arch/arm/mach-omap2/mmc-twl4030.h

@@ -0,0 +1,29 @@
+/*
+ * MMC definitions for OMAP2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+struct twl4030_hsmmc_info {
+	u8	mmc;		/* controller 1/2/3 */
+	u8	wires;		/* 1/4/8 wires */
+	int	gpio_cd;	/* or -EINVAL */
+	int	gpio_wp;	/* or -EINVAL */
+	int	ext_clock:1;	/* use external pin for input clock */
+};
+
+#if	defined(CONFIG_TWL4030_CORE) && \
+	(defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
+	 defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
+
+void twl4030_mmc_init(struct twl4030_hsmmc_info *);
+
+#else
+
+static inline void twl4030_mmc_init(struct twl4030_hsmmc_info *info)
+{
+}
+
+#endif

+ 35 - 190
arch/arm/plat-omap/devices.c

@@ -192,202 +192,48 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
 
 /*-------------------------------------------------------------------------*/
 
-#if	defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
 	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
-#define	OMAP_MMC1_BASE		0x4809c000
-#define	OMAP_MMC1_END		(OMAP_MMC1_BASE + 0x1fc)
-#define	OMAP_MMC1_INT		INT_24XX_MMC_IRQ
+#define OMAP_MMC_NR_RES		2
 
-#define	OMAP_MMC2_BASE		0x480b4000
-#define	OMAP_MMC2_END		(OMAP_MMC2_BASE + 0x1fc)
-#define	OMAP_MMC2_INT		INT_24XX_MMC2_IRQ
-
-#else
-
-#define	OMAP_MMC1_BASE		0xfffb7800
-#define	OMAP_MMC1_END		(OMAP_MMC1_BASE + 0x7f)
-#define OMAP_MMC1_INT		INT_MMC
-
-#define	OMAP_MMC2_BASE		0xfffb7c00	/* omap16xx only */
-#define	OMAP_MMC2_END		(OMAP_MMC2_BASE + 0x7f)
-#define	OMAP_MMC2_INT		INT_1610_MMC2
-
-#endif
-
-static struct omap_mmc_platform_data mmc1_data;
-
-static u64 mmc1_dmamask = 0xffffffff;
-
-static struct resource mmc1_resources[] = {
-	{
-		.start		= OMAP_MMC1_BASE,
-		.end		= OMAP_MMC1_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP_MMC1_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device mmc_omap_device1 = {
-	.name		= "mmci-omap",
-	.id		= 1,
-	.dev = {
-		.dma_mask	= &mmc1_dmamask,
-		.platform_data	= &mmc1_data,
-	},
-	.num_resources	= ARRAY_SIZE(mmc1_resources),
-	.resource	= mmc1_resources,
-};
-
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \
-	defined(CONFIG_ARCH_OMAP34XX)
-
-static struct omap_mmc_platform_data mmc2_data;
-
-static u64 mmc2_dmamask = 0xffffffff;
-
-static struct resource mmc2_resources[] = {
-	{
-		.start		= OMAP_MMC2_BASE,
-		.end		= OMAP_MMC2_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP_MMC2_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device mmc_omap_device2 = {
-	.name		= "mmci-omap",
-	.id		= 2,
-	.dev = {
-		.dma_mask	= &mmc2_dmamask,
-		.platform_data	= &mmc2_data,
-	},
-	.num_resources	= ARRAY_SIZE(mmc2_resources),
-	.resource	= mmc2_resources,
-};
-#endif
-
-static inline void omap_init_mmc_conf(const struct omap_mmc_config *mmc_conf)
-{
-	if (cpu_is_omap2430() || cpu_is_omap34xx())
-		return;
-
-	if (mmc_conf->mmc[0].enabled) {
-		if (cpu_is_omap24xx()) {
-			omap_cfg_reg(H18_24XX_MMC_CMD);
-			omap_cfg_reg(H15_24XX_MMC_CLKI);
-			omap_cfg_reg(G19_24XX_MMC_CLKO);
-			omap_cfg_reg(F20_24XX_MMC_DAT0);
-			omap_cfg_reg(F19_24XX_MMC_DAT_DIR0);
-			omap_cfg_reg(G18_24XX_MMC_CMD_DIR);
-		} else {
-			omap_cfg_reg(MMC_CMD);
-			omap_cfg_reg(MMC_CLK);
-			omap_cfg_reg(MMC_DAT0);
-			if (cpu_is_omap1710()) {
-				omap_cfg_reg(M15_1710_MMC_CLKI);
-				omap_cfg_reg(P19_1710_MMC_CMDDIR);
-				omap_cfg_reg(P20_1710_MMC_DATDIR0);
-			}
-		}
-		if (mmc_conf->mmc[0].wire4) {
-			if (cpu_is_omap24xx()) {
-				omap_cfg_reg(H14_24XX_MMC_DAT1);
-				omap_cfg_reg(E19_24XX_MMC_DAT2);
-				omap_cfg_reg(D19_24XX_MMC_DAT3);
-				omap_cfg_reg(E20_24XX_MMC_DAT_DIR1);
-				omap_cfg_reg(F18_24XX_MMC_DAT_DIR2);
-				omap_cfg_reg(E18_24XX_MMC_DAT_DIR3);
-			} else {
-				omap_cfg_reg(MMC_DAT1);
-				/* NOTE:  DAT2 can be on W10 (here) or M15 */
-				if (!mmc_conf->mmc[0].nomux)
-					omap_cfg_reg(MMC_DAT2);
-				omap_cfg_reg(MMC_DAT3);
-			}
-		}
-	}
-
-#ifdef	CONFIG_ARCH_OMAP16XX
-	/* block 2 is on newer chips, and has many pinout options */
-	if (mmc_conf->mmc[1].enabled) {
-		if (!mmc_conf->mmc[1].nomux) {
-			omap_cfg_reg(Y8_1610_MMC2_CMD);
-			omap_cfg_reg(Y10_1610_MMC2_CLK);
-			omap_cfg_reg(R18_1610_MMC2_CLKIN);
-			omap_cfg_reg(W8_1610_MMC2_DAT0);
-			if (mmc_conf->mmc[1].wire4) {
-				omap_cfg_reg(V8_1610_MMC2_DAT1);
-				omap_cfg_reg(W15_1610_MMC2_DAT2);
-				omap_cfg_reg(R10_1610_MMC2_DAT3);
-			}
-
-			/* These are needed for the level shifter */
-			omap_cfg_reg(V9_1610_MMC2_CMDDIR);
-			omap_cfg_reg(V5_1610_MMC2_DATDIR0);
-			omap_cfg_reg(W19_1610_MMC2_DATDIR1);
-		}
-
-		/* Feedback clock must be set on OMAP-1710 MMC2 */
-		if (cpu_is_omap1710())
-			omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24),
-				     MOD_CONF_CTRL_1);
-	}
-#endif
-}
-
-static void __init omap_init_mmc(void)
+/*
+ * Register MMC devices. Called from mach-omap1 and mach-omap2 device init.
+ */
+int __init omap_mmc_add(int id, unsigned long base, unsigned long size,
+		unsigned int irq, struct omap_mmc_platform_data *data)
 {
-	const struct omap_mmc_config	*mmc_conf;
-
-	/* NOTE:  assumes MMC was never (wrongly) enabled */
-	mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config);
-	if (!mmc_conf)
-		return;
-
-	omap_init_mmc_conf(mmc_conf);
-
-	if (mmc_conf->mmc[0].enabled) {
-		mmc1_data.conf = mmc_conf->mmc[0];
-		(void) platform_device_register(&mmc_omap_device1);
-	}
-
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \
-	defined(CONFIG_ARCH_OMAP34XX)
-	if (mmc_conf->mmc[1].enabled) {
-		mmc2_data.conf = mmc_conf->mmc[1];
-		(void) platform_device_register(&mmc_omap_device2);
-	}
-#endif
-}
+	struct platform_device *pdev;
+	struct resource res[OMAP_MMC_NR_RES];
+	int ret;
+
+	pdev = platform_device_alloc("mmci-omap", id);
+	if (!pdev)
+		return -ENOMEM;
+
+	memset(res, 0, OMAP_MMC_NR_RES * sizeof(struct resource));
+	res[0].start = base;
+	res[0].end = base + size - 1;
+	res[0].flags = IORESOURCE_MEM;
+	res[1].start = res[1].end = irq;
+	res[1].flags = IORESOURCE_IRQ;
+
+	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+	if (ret == 0)
+		ret = platform_device_add_data(pdev, data, sizeof(*data));
+	if (ret)
+		goto fail;
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto fail;
+	return 0;
 
-void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info)
-{
-	switch (host) {
-	case 1:
-		mmc1_data = *info;
-		break;
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \
-	defined(CONFIG_ARCH_OMAP34XX)
-	case 2:
-		mmc2_data = *info;
-		break;
-#endif
-	default:
-		BUG();
-	}
+fail:
+	platform_device_put(pdev);
+	return ret;
 }
 
-#else
-static inline void omap_init_mmc(void) {}
-void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info) {}
 #endif
 
 /*-------------------------------------------------------------------------*/
@@ -532,7 +378,6 @@ static int __init omap_init_devices(void)
 	 */
 	omap_init_dsp();
 	omap_init_kp();
-	omap_init_mmc();
 	omap_init_uwire();
 	omap_init_wdt();
 	omap_init_rng();

+ 3 - 3
arch/arm/plat-omap/include/mach/board-h2.h

@@ -29,13 +29,13 @@
 #ifndef __ASM_ARCH_OMAP_H2_H
 #define __ASM_ARCH_OMAP_H2_H
 
-/* Placeholder for H2 specific defines */
-
 /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
 #define OMAP1610_ETHR_START		0x04000300
 
+#define H2_TPS_GPIO_BASE		(OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
+#	define H2_TPS_GPIO_MMC_PWR_EN	(H2_TPS_GPIO_BASE + 3)
+
 extern void h2_mmc_init(void);
-extern void h2_mmc_slot_cover_handler(void *arg, int state);
 
 #endif /*  __ASM_ARCH_OMAP_H2_H */
 

+ 0 - 22
arch/arm/plat-omap/include/mach/board.h

@@ -16,7 +16,6 @@
 
 /* Different peripheral ids */
 #define OMAP_TAG_CLOCK		0x4f01
-#define OMAP_TAG_MMC		0x4f02
 #define OMAP_TAG_SERIAL_CONSOLE 0x4f03
 #define OMAP_TAG_USB		0x4f04
 #define OMAP_TAG_LCD		0x4f05
@@ -35,27 +34,6 @@ struct omap_clock_config {
 	u8 system_clock_type;
 };
 
-struct omap_mmc_conf {
-	unsigned enabled:1;
-	/* nomux means "standard" muxing is wrong on this board, and that
-	 * board-specific code handled it before common init logic.
-	 */
-	unsigned nomux:1;
-	/* switch pin can be for card detect (default) or card cover */
-	unsigned cover:1;
-	/* 4 wire signaling is optional, and is only used for SD/SDIO */
-	unsigned wire4:1;
-	/* use the internal clock */
-	unsigned internal_clock:1;
-	s16 power_pin;
-	s16 switch_pin;
-	s16 wp_pin;
-};
-
-struct omap_mmc_config {
-	struct omap_mmc_conf mmc[2];
-};
-
 struct omap_serial_console_config {
 	u8 console_uart;
 	u32 console_speed;

+ 17 - 0
arch/arm/plat-omap/include/mach/control.h

@@ -74,6 +74,7 @@
 #define OMAP243X_CONTROL_IVA2_BOOTADDR	(OMAP2_CONTROL_GENERAL + 0x0190)
 #define OMAP243X_CONTROL_IVA2_BOOTMOD	(OMAP2_CONTROL_GENERAL + 0x0194)
 #define OMAP243X_CONTROL_IVA2_GEMCFG	(OMAP2_CONTROL_GENERAL + 0x0198)
+#define OMAP243X_CONTROL_PBIAS_LITE	(OMAP2_CONTROL_GENERAL + 0x0230)
 
 /* 24xx-only CONTROL_GENERAL register offsets */
 #define OMAP24XX_CONTROL_DEBOBS		(OMAP2_CONTROL_GENERAL + 0x0000)
@@ -140,6 +141,7 @@
 #define OMAP343X_CONTROL_TEST_KEY_13	(OMAP2_CONTROL_GENERAL + 0x00fc)
 #define OMAP343X_CONTROL_IVA2_BOOTADDR	(OMAP2_CONTROL_GENERAL + 0x0190)
 #define OMAP343X_CONTROL_IVA2_BOOTMOD	(OMAP2_CONTROL_GENERAL + 0x0194)
+#define OMAP343X_CONTROL_PBIAS_LITE	(OMAP2_CONTROL_GENERAL + 0x02b0)
 #define OMAP343X_CONTROL_TEMP_SENSOR	(OMAP2_CONTROL_GENERAL + 0x02b4)
 
 /*
@@ -154,11 +156,14 @@
  * and the security mode (secure, non-secure, don't care)
  */
 /* CONTROL_DEVCONF0 bits */
+#define OMAP2_MMCSDIO1ADPCLKISEL	(1 << 24) /* MMC1 loop back clock */
 #define OMAP24XX_USBSTANDBYCTRL		(1 << 15)
 #define OMAP2_MCBSP2_CLKS_MASK		(1 << 6)
 #define OMAP2_MCBSP1_CLKS_MASK		(1 << 2)
 
 /* CONTROL_DEVCONF1 bits */
+#define OMAP243X_MMC1_ACTIVE_OVERWRITE	(1 << 31)
+#define OMAP2_MMCSDIO2ADPCLKISEL	(1 << 6) /* MMC2 loop back clock */
 #define OMAP2_MCBSP5_CLKS_MASK		(1 << 4) /* > 242x */
 #define OMAP2_MCBSP4_CLKS_MASK		(1 << 2) /* > 242x */
 #define OMAP2_MCBSP3_CLKS_MASK		(1 << 0) /* > 242x */
@@ -172,6 +177,18 @@
 #define OMAP2_SYSBOOT_1_MASK		(1 << 1)
 #define OMAP2_SYSBOOT_0_MASK		(1 << 0)
 
+/* CONTROL_PBIAS_LITE bits */
+#define OMAP343X_PBIASLITESUPPLY_HIGH1	(1 << 15)
+#define OMAP343X_PBIASLITEVMODEERROR1	(1 << 11)
+#define OMAP343X_PBIASSPEEDCTRL1	(1 << 10)
+#define OMAP343X_PBIASLITEPWRDNZ1	(1 << 9)
+#define OMAP343X_PBIASLITEVMODE1	(1 << 8)
+#define OMAP343X_PBIASLITESUPPLY_HIGH0	(1 << 7)
+#define OMAP343X_PBIASLITEVMODEERROR0	(1 << 3)
+#define OMAP2_PBIASSPEEDCTRL0		(1 << 2)
+#define OMAP2_PBIASLITEPWRDNZ0		(1 << 1)
+#define OMAP2_PBIASLITEVMODE0		(1 << 0)
+
 #ifndef __ASSEMBLY__
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 extern void __iomem *omap_ctrl_base_get(void);

+ 68 - 6
arch/arm/plat-omap/include/mach/mmc.h

@@ -17,12 +17,28 @@
 
 #include <mach/board.h>
 
+#define OMAP15XX_NR_MMC		1
+#define OMAP16XX_NR_MMC		2
+#define OMAP1_MMC_SIZE		0x080
+#define OMAP1_MMC1_BASE		0xfffb7800
+#define OMAP1_MMC2_BASE		0xfffb7c00	/* omap16xx only */
+
+#define OMAP24XX_NR_MMC		2
+#define OMAP34XX_NR_MMC		3
+#define OMAP2420_MMC_SIZE	OMAP1_MMC_SIZE
+#define HSMMC_SIZE		0x200
+#define OMAP2_MMC1_BASE		0x4809c000
+#define OMAP2_MMC2_BASE		0x480b4000
+#define OMAP3_MMC3_BASE		0x480ad000
+#define HSMMC3			(1 << 2)
+#define HSMMC2			(1 << 1)
+#define HSMMC1			(1 << 0)
+
 #define OMAP_MMC_MAX_SLOTS	2
 
 struct omap_mmc_platform_data {
-	struct omap_mmc_conf	conf;
 
-	/* number of slots on board */
+	/* number of slots per controller */
 	unsigned nr_slots:2;
 
 	/* set if your board has components or wiring that limits the
@@ -41,7 +57,31 @@ struct omap_mmc_platform_data {
 	int (*suspend)(struct device *dev, int slot);
 	int (*resume)(struct device *dev, int slot);
 
+	u64 dma_mask;
+
 	struct omap_mmc_slot_data {
+
+		/* 4 wire signaling is optional, and is used for SD/SDIO/HSMMC;
+		 * 8 wire signaling is also optional, and is used with HSMMC
+		 */
+		u8 wires;
+
+		/*
+		 * nomux means "standard" muxing is wrong on this board, and
+		 * that board-specific code handled it before common init logic.
+		 */
+		unsigned nomux:1;
+
+		/* switch pin can be for card detect (default) or card cover */
+		unsigned cover:1;
+
+		/* use the internal clock */
+		unsigned internal_clock:1;
+		s16 power_pin;
+
+		int switch_pin;			/* gpio (card detect) */
+		int gpio_wp;			/* gpio (write protect) */
+
 		int (* set_bus_mode)(struct device *dev, int slot, int bus_mode);
 		int (* set_power)(struct device *dev, int slot, int power_on, int vdd);
 		int (* get_ro)(struct device *dev, int slot);
@@ -49,8 +89,8 @@ struct omap_mmc_platform_data {
 		/* return MMC cover switch state, can be NULL if not supported.
 		 *
 		 * possible return values:
-		 *   0 - open
-		 *   1 - closed
+		 *   0 - closed
+		 *   1 - open
 		 */
 		int (* get_cover_state)(struct device *dev, int slot);
 
@@ -66,9 +106,31 @@ struct omap_mmc_platform_data {
 	} slots[OMAP_MMC_MAX_SLOTS];
 };
 
-extern void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info);
-
 /* called from board-specific card detection service routine */
 extern void omap_mmc_notify_cover_event(struct device *dev, int slot, int is_closed);
 
+#if	defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
+	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
+void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
+				int nr_controllers);
+void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
+				int nr_controllers);
+int omap_mmc_add(int id, unsigned long base, unsigned long size,
+			unsigned int irq, struct omap_mmc_platform_data *data);
+#else
+static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
+				int nr_controllers)
+{
+}
+static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
+				int nr_controllers)
+{
+}
+static inline int omap_mmc_add(int id, unsigned long base, unsigned long size,
+		unsigned int irq, struct omap_mmc_platform_data *data)
+{
+	return 0;
+}
+
+#endif
 #endif

+ 4 - 3
drivers/mmc/host/omap.c

@@ -1015,7 +1015,7 @@ static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data
 	}
 
 	if (is_read) {
-		if (host->id == 1) {
+		if (host->id == 0) {
 			sync_dev = OMAP_DMA_MMC_RX;
 			dma_dev_name = "MMC1 read";
 		} else {
@@ -1023,7 +1023,7 @@ static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data
 			dma_dev_name = "MMC2 read";
 		}
 	} else {
-		if (host->id == 1) {
+		if (host->id == 0) {
 			sync_dev = OMAP_DMA_MMC_TX;
 			dma_dev_name = "MMC1 write";
 		} else {
@@ -1317,7 +1317,7 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id)
 	host->slots[id] = slot;
 
 	mmc->caps = 0;
-	if (host->pdata->conf.wire4)
+	if (host->pdata->slots[id].wires >= 4)
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
 
 	mmc->ops = &mmc_omap_ops;
@@ -1451,6 +1451,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
 	host->irq = irq;
 
 	host->use_dma = 1;
+	host->dev->dma_mask = &pdata->dma_mask;
 	host->dma_ch = -1;
 
 	host->irq = irq;