Skip to contentSkip to conversation

Omap MMC init updates and new controller for 2.6.29 merge window

PATCH In review Tony Lindgren 9 participants 37 messages Dec 7, 2008 – Mar 24, 2009

Subsystems (8)
lore
Share & tools
lore

Tony Lindgren

author maintainer
#0 lore raw

cover Omap MMC init updates and new controller for 2.6.29 merge window

Hi Pierre & Russell,

This series contains a better platform init for omap MMC as discussed earlier on the linux-omap mailing list. The last patch in the series adds support for a newer omap MMC controller available on 2430 and 34xx omaps.

The first four patches should get merged via Russell. The last one adding the new controller depends on comments from Pierre, so I can separate that out if desired.

The third patch in the series depends on the "Omap3 updates for 2.6.29 merge window" series for the changes to Pandora board support.

Comments welcome as always!

Regards,

Tony

---

Kevin Hilman (1):
omap mmc: force MMC module reset on boot

Madhusudhan Chikkature (1):
omap mmc: Add new omap hsmmc controller for 2430 and 34xx

Tony Lindgren (3):
omap mmc: Add low-level initialization for hsmmc controller omap mmc: Add better MMC low-level init
omap mmc: Remove broken MMC init code

 arch/arm/mach-omap1/board-h2-mmc.c         |   89 +-
 arch/arm/mach-omap1/board-h2.c             |   25 -
 arch/arm/mach-omap1/board-h3-mmc.c         |  100 +-
 arch/arm/mach-omap1/board-h3.c             |   10 
 arch/arm/mach-omap1/board-innovator.c      |   50 +
 arch/arm/mach-omap1/board-nokia770.c       |   74 +-
 arch/arm/mach-omap1/board-palmte.c         |    1 
 arch/arm/mach-omap1/board-palmz71.c        |   11 
 arch/arm/mach-omap1/board-sx1-mmc.c        |   80 --
 arch/arm/mach-omap1/board-sx1.c            |   10 
 arch/arm/mach-omap1/board-voiceblue.c      |   10 
 arch/arm/mach-omap1/clock.h                |    3 
 arch/arm/mach-omap1/devices.c              |   90 ++
 arch/arm/mach-omap2/Makefile               |   15 
 arch/arm/mach-omap2/board-2430sdp.c        |   48 +
 arch/arm/mach-omap2/board-apollon.c        |   11 
 arch/arm/mach-omap2/board-generic.c        |   11 
 arch/arm/mach-omap2/board-h4.c             |   11 
 arch/arm/mach-omap2/board-ldp.c            |   40 +
 arch/arm/mach-omap2/board-omap3beagle.c    |   90 ++
 arch/arm/mach-omap2/board-omap3pandora.c   |   32 +
 arch/arm/mach-omap2/board-overo.c          |   43 +
 arch/arm/mach-omap2/clock24xx.h            |    9 
 arch/arm/mach-omap2/clock34xx.h            |   10 
 arch/arm/mach-omap2/devices.c              |  169 ++++
 arch/arm/mach-omap2/mmc-twl4030.c          |  408 +++++++++
 arch/arm/mach-omap2/mmc-twl4030.h          |   29 +
 arch/arm/plat-omap/devices.c               |  225 +----
 arch/arm/plat-omap/include/mach/board-h2.h |    6 
 arch/arm/plat-omap/include/mach/board.h    |   22 
 arch/arm/plat-omap/include/mach/control.h  |   17 
 arch/arm/plat-omap/include/mach/mmc.h      |   74 ++
 drivers/mmc/host/Kconfig                   |   11 
 drivers/mmc/host/Makefile                  |    1 
 drivers/mmc/host/omap.c                    |    7 
 drivers/mmc/host/omap_hsmmc.c              | 1242 ++++++++++++++++++++++++++++
 36 files changed, 2536 insertions(+), 548 deletions(-)
 create mode 100644 arch/arm/mach-omap2/mmc-twl4030.c
 create mode 100644 arch/arm/mach-omap2/mmc-twl4030.h
 create mode 100644 drivers/mmc/host/omap_hsmmc.c
Signature · 1 line
Signature
author maintainer
#1 lore raw

PATCH 1/5 omap mmc: Remove broken MMC init code

Most of the omap1 MMC boards got broken by an earlier patch 138ab9f8321f67c71984ca43222efa71b0a0a0a9. If you look closely, the MMC init funtions are pretty much just stubs.

Remove broken init code to make room for cleaner MMC init code.

---
 arch/arm/mach-omap1/board-h2-mmc.c    |   86 --------------------------------
 arch/arm/mach-omap1/board-h2.c        |   10 ----
 arch/arm/mach-omap1/board-h3-mmc.c    |   90 ---------------------------------
 arch/arm/mach-omap1/board-h3.c        |   10 ----
 arch/arm/mach-omap1/board-palmte.c    |    1 
 arch/arm/mach-omap1/board-palmz71.c   |   11 ----
 arch/arm/mach-omap1/board-sx1-mmc.c   |   49 ------------------
 arch/arm/mach-omap1/board-sx1.c       |   10 ----
 arch/arm/mach-omap1/board-voiceblue.c |   10 ----
 arch/arm/mach-omap2/board-apollon.c   |   11 ----
 arch/arm/mach-omap2/board-generic.c   |   11 ----
 arch/arm/mach-omap2/board-h4.c        |   11 ----
 12 files changed, 1 insertions(+), 309 deletions(-)
arch/arm/mach-omap1/board-h2-mmc.c +0 -86
index ab9ee58..504ae88 100644
@@ -15,91 +15,6 @@
 #include <mach/mmc.h>
 #include <mach/gpio.h>
 
-#ifdef CONFIG_MMC_OMAP
-static int slot_cover_open;
-static struct device *mmc_device;
-
-static int h2_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;
-	}
-
-	return 0;
-}
-
-static int h2_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 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;
-
-	return ret;
-}
-
-static void h2_mmc_cleanup(struct device *dev)
-{
-}
-
-static struct omap_mmc_platform_data h2_mmc_data = {
-	.nr_slots                       = 1,
-	.switch_slot                    = NULL,
-	.init                           = h2_mmc_late_init,
-	.cleanup                        = h2_mmc_cleanup,
-	.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,
-		.ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
-					  MMC_VDD_32_33 | MMC_VDD_33_34,
-		.name                   = "mmcblk",
-	},
-};
-
-void __init h2_mmc_init(void)
-{
-	omap_set_mmc_info(1, &h2_mmc_data);
-}
-
-#else
-
 void __init h2_mmc_init(void)
 {
 }
@@ -107,4 +22,3 @@ void __init h2_mmc_init(void)
 void h2_mmc_slot_cover_handler(void *arg, int state)
 {
 }
-#endif
arch/arm/mach-omap1/board-h2.c +0 -10
index c5b4a3b..125d8e2 100644
@@ -378,15 +378,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 +388,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 },
 };
arch/arm/mach-omap1/board-h3-mmc.c +0 -90

99 lines not on this page · raw message

arch/arm/mach-omap1/board-h3.c +0 -10
index 0332203..5157eea 100644
@@ -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 },
 };
arch/arm/mach-omap1/board-palmte.c +0 -1
index 4141e39..75e32d3 100644
@@ -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 },
 };
arch/arm/mach-omap1/board-palmz71.c +0 -11
index 801fb5f..cc05257 100644
@@ -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},
 };
arch/arm/mach-omap1/board-sx1-mmc.c +0 -49

59 lines not on this page · raw message

arch/arm/mach-omap1/board-sx1.c +0 -10
index 93bd395..8171fe0 100644
@@ -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 },
 };
arch/arm/mach-omap1/board-voiceblue.c +1 -9
index 92c9de1..c224f3c 100644
@@ -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 },
 };
 
arch/arm/mach-omap2/board-apollon.c +0 -11
index d83035b..bf1e5d3 100644
@@ -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 },
 };
arch/arm/mach-omap2/board-generic.c +0 -11
index 9ba0978..3b34c20 100644
@@ -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)
arch/arm/mach-omap2/board-h4.c +0 -11
index 7de0506..5e9b146 100644
@@ -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 },
 };
 
author maintainer
#2 lore raw

PATCH 2/5 omap mmc: Add better MMC low-level init

In reply to Tony Lindgren

This will simplify the MMC low-level init, and make it more flexible to add support for a newer MMC controller in the following patches.

The patch rearranges platform data and gets rid of slot vs controller confusion in the old data structures. Also fix device id numbering in the clock code.

Some code snippets are based on an earlier patch by Russell King <[email protected]>.

---
 arch/arm/mach-omap1/board-h2-mmc.c         |   63 ++++++++
 arch/arm/mach-omap1/board-h2.c             |   15 ++
 arch/arm/mach-omap1/board-h3-mmc.c         |   50 ++++++
 arch/arm/mach-omap1/board-innovator.c      |   50 +++++-
 arch/arm/mach-omap1/board-nokia770.c       |   74 +++++++--
 arch/arm/mach-omap1/board-sx1-mmc.c        |   31 +---
 arch/arm/mach-omap1/clock.h                |    3 
 arch/arm/mach-omap1/devices.c              |   90 +++++++++++
 arch/arm/mach-omap2/clock24xx.h            |    9 -
 arch/arm/mach-omap2/clock34xx.h            |   10 -
 arch/arm/mach-omap2/devices.c              |   83 ++++++++++
 arch/arm/plat-omap/devices.c               |  225 ++++------------------------
 arch/arm/plat-omap/include/mach/board-h2.h |    6 -
 arch/arm/plat-omap/include/mach/board.h    |   22 ---
 arch/arm/plat-omap/include/mach/mmc.h      |   74 ++++++++-
 drivers/mmc/host/omap.c                    |    7 -
 16 files changed, 529 insertions(+), 283 deletions(-)
arch/arm/mach-omap1/board-h2-mmc.c +62 -1
index 504ae88..409fa56 100644
@@ -12,13 +12,74 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/platform_device.h>
+
+#include <linux/i2c/tps65010.h>
+
 #include <mach/mmc.h>
 #include <mach/gpio.h>
 
+#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)
+		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 mmc_late_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
+	if (ret < 0)
+		return ret;
+
+	gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0);
+
+	return ret;
+}
+
+static void mmc_shutdown(struct device *dev)
+{
+	gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
+}
+
+/*
+ * 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,
+	.init				= mmc_late_init,
+	.shutdown			= mmc_shutdown,
+	.dma_mask			= 0xffffffff,
+	.slots[0]       = {
+		.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)
 {
+	mmc_data[0] = &mmc1_data;
+	omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC);
 }
 
-void h2_mmc_slot_cover_handler(void *arg, int state)
+#else
+
+void __init h2_mmc_init(void)
 {
 }
+
+#endif
arch/arm/mach-omap1/board-h2.c +15 -0
index 125d8e2..b240c5f 100644
@@ -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),
arch/arm/mach-omap1/board-h3-mmc.c +49 -1

62 lines not on this page · raw message

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

77 lines not on this page · raw message

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

97 lines not on this page · raw message

arch/arm/mach-omap1/board-sx1-mmc.c +11 -20
index 0ece109..66a4d7d 100644
@@ -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,19 +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 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,
 	.slots[0]       = {
-		.set_power              = sx1_mmc_set_power,
+		.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
@@ -69,7 +63,4 @@ void __init sx1_mmc_init(void)
 {
 }
 
-void sx1_mmc_slot_cover_handler(void *arg, int state)
-{
-}
 #endif
arch/arm/mach-omap1/clock.h +1 -2
index 5635b51..c1dcdf1 100644
@@ -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,
arch/arm/mach-omap1/devices.c +90 -0

102 lines not on this page · raw message

arch/arm/mach-omap2/clock24xx.h +3 -6
index 242a19d..ff6cd14 100644
@@ -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",
arch/arm/mach-omap2/clock34xx.h +4 -6
index 7217a08..a826094 100644
@@ -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,
arch/arm/mach-omap2/devices.c +83 -0

95 lines not on this page · raw message

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

244 lines not on this page · raw message

arch/arm/plat-omap/include/mach/board-h2.h +3 -3
index 2a050e9..15531c8 100644
@@ -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 */
 
arch/arm/plat-omap/include/mach/board.h +0 -22
index c23c12c..9466772 100644
@@ -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;
arch/arm/plat-omap/include/mach/mmc.h +68 -6

104 lines not on this page · raw message

drivers/mmc/host/omap.c +4 -3
index 1b9fc3c..c6544d2 100644
@@ -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].wire4)
 		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;
#3 lore raw

Re: [PATCH 2/5] omap mmc: Add better MMC low-level init

Quoted 4 lines · Tony Lindgren
arch/arm/mach-omap1/board-h2-mmc.c +0 -0
index 504ae88..409fa56 100644

[snip]

Quoted 4 lines
arch/arm/mach-omap1/board-h2-mmc.c +4 -0
+static void mmc_shutdown(struct device *dev)
+{
+	gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
+}

arch/arm/mach-omap1/board-h2-mmc.c

Quoted 10 lines
arch/arm/mach-omap1/board-h2-mmc.c +10 -0
+
+/*
+ * 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,
+	.init				= mmc_late_init,
+	.shutdown			= mmc_shutdown,

It seems that shutdown is no-op, so what about patch below?

arch/arm/mach-omap1/board-h2-mmc.c +4 -10
index 409fa56..613adfc 100644
@@ -24,19 +24,13 @@
 static int mmc_set_power(struct device *dev, int slot, int power_on,
 				int vdd)
 {
-	if (power_on)
-		gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 1);
-	else
-		gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0);
-
+	gpio_set_value(H2_TPS_GPIO_MMC_PWR_EN, power_on);
 	return 0;
 }
 
 static int mmc_late_init(struct device *dev)
 {
-	int ret;
-
-	ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
+	int ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
 	if (ret < 0)
 		return ret;
 
@@ -45,7 +39,7 @@ static int mmc_late_init(struct device *dev)
 	return ret;
 }
 
-static void mmc_shutdown(struct device *dev)
+static void mmc_cleanup(struct device *dev)
 {
 	gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
 }
@@ -58,7 +52,7 @@ static void mmc_shutdown(struct device *dev)
 static struct omap_mmc_platform_data mmc1_data = {
 	.nr_slots                       = 1,
 	.init				= mmc_late_init,
-	.shutdown			= mmc_shutdown,
+	.cleanup			= mmc_cleanup,
 	.dma_mask			= 0xffffffff,
 	.slots[0]       = {
 		.set_power              = mmc_set_power,
#4 lore raw

Re: [PATCH 2/5] omap mmc: Add better MMC low-level init

Quoted 6 lines · Ladislav Michl
Quoted 4 lines · Tony Lindgren
arch/arm/mach-omap1/board-h2-mmc.c +0 -0
index 504ae88..409fa56 100644

[snip]

Quoted 15 lines
Quoted 4 lines
arch/arm/mach-omap1/board-h2-mmc.c +4 -0
+static void mmc_shutdown(struct device *dev)
+{
+	gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
+}

arch/arm/mach-omap1/board-h2-mmc.c

Quoted 10 lines
arch/arm/mach-omap1/board-h2-mmc.c +10 -0
+
+/*
+ * 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,
+	.init				= mmc_late_init,
+	.shutdown			= mmc_shutdown,

It seems that shutdown is no-op, so what about patch below?

After all, lets remove some unused fields.

arch/arm/plat-omap/include/mach/mmc.h +0 -5
index 031250f..1129e97 100644
@@ -51,7 +51,6 @@ struct omap_mmc_platform_data {
 	 * not supported */
 	int (* init)(struct device *dev);
 	void (* cleanup)(struct device *dev);
-	void (* shutdown)(struct device *dev);
 
 	/* To handle board related suspend/resume functionality for MMC */
 	int (*suspend)(struct device *dev, int slot);
@@ -77,10 +76,6 @@ struct omap_mmc_platform_data {
 
 		/* 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);
drivers/mmc/host/omap.c +0 -2
index 67d7b7f..84de289 100644
@@ -157,8 +157,6 @@ struct mmc_omap_host {
 	struct timer_list	dma_timer;
 	unsigned		dma_len;
 
-	short			power_pin;
-
 	struct mmc_omap_slot    *slots[OMAP_MMC_MAX_SLOTS];
 	struct mmc_omap_slot    *current_slot;
 	spinlock_t              slot_lock;
author maintainer
#5 lore raw

Re: [PATCH 2/5] omap mmc: Add better MMC low-level init

Quoted 40 lines · Ladislav Michl
Quoted 6 lines · Ladislav Michl
Quoted 4 lines · Tony Lindgren
arch/arm/mach-omap1/board-h2-mmc.c +0 -0
index 504ae88..409fa56 100644

[snip]

Quoted 15 lines
Quoted 4 lines
arch/arm/mach-omap1/board-h2-mmc.c +4 -0
+static void mmc_shutdown(struct device *dev)
+{
+	gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
+}

arch/arm/mach-omap1/board-h2-mmc.c

Quoted 10 lines
arch/arm/mach-omap1/board-h2-mmc.c +10 -0
+
+/*
+ * 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,
+	.init				= mmc_late_init,
+	.shutdown			= mmc_shutdown,

It seems that shutdown is no-op, so what about patch below?

After all, lets remove some unused fields.

arch/arm/plat-omap/include/mach/mmc.h +0 -1
index 031250f..1129e97 100644
@@ -51,7 +51,6 @@ struct omap_mmc_platform_data {
 	 * not supported */
 	int (* init)(struct device *dev);
 	void (* cleanup)(struct device *dev);
-	void (* shutdown)(struct device *dev);
 
 	/* To handle board related suspend/resume functionality for MMC */
 	int (*suspend)(struct device *dev, int slot);

arch/arm/plat-omap/include/mach/mmc.h struct omap_mmc_platform_data { · line 81

Quoted 10 lines
arch/arm/plat-omap/include/mach/mmc.h +0 -4
@@ -77,10 +76,6 @@ struct omap_mmc_platform_data {
 
 		/* 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);

Hmm, aren't switch_pin and gpio_wp used at least in the mmc-twl4030.c?

I guess they could be internal to mmc-twl4030.c if not used in the drivers directly.

Quoted 6 lines
drivers/mmc/host/omap.c +0 -0
index 67d7b7f..84de289 100644

drivers/mmc/host/omap.c struct mmc_omap_host { · line 162

Quoted 8 lines
drivers/mmc/host/omap.c +0 -2
@@ -157,8 +157,6 @@ struct mmc_omap_host {
 	struct timer_list	dma_timer;
 	unsigned		dma_len;
 
-	short			power_pin;
-
 	struct mmc_omap_slot    *slots[OMAP_MMC_MAX_SLOTS];
 	struct mmc_omap_slot    *current_slot;
 	spinlock_t              slot_lock;

Looks like power_pin could go though.

Tony

#6 lore raw

Re: [PATCH 2/5] omap mmc: Add better MMC low-level init

Quoted 21 lines · Tony Lindgren
Quoted 21 lines
arch/arm/plat-omap/include/mach/mmc.h +0 -5
index 031250f..1129e97 100644
@@ -51,7 +51,6 @@ struct omap_mmc_platform_data {
 	 * not supported */
 	int (* init)(struct device *dev);
 	void (* cleanup)(struct device *dev);
-	void (* shutdown)(struct device *dev);
 
 	/* To handle board related suspend/resume functionality for MMC */
 	int (*suspend)(struct device *dev, int slot);
@@ -77,10 +76,6 @@ struct omap_mmc_platform_data {
 
 		/* use the internal clock */
 		unsigned internal_clock:1;
-		s16 power_pin;
-
-		int switch_pin;			/* gpio (card detect) */
-		int gpio_wp;			/* gpio (write protect) */
 
Quoted 5 lines

arch/arm/plat-omap/include/mach/mmc.h struct omap_mmc_platform_data { · line 81

Quoted 2 lines
arch/arm/plat-omap/include/mach/mmc.h +0 -0
 		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);

Hmm, aren't switch_pin and gpio_wp used at least in the mmc-twl4030.c?

Yes, they are. I missed them completely. Sorry.

Quoted 2 lines

I guess they could be internal to mmc-twl4030.c if not used in the drivers directly.

They could, but that's a bit more complicated. Will look at it later.

Quoted 8 lines
Quoted 8 lines
drivers/mmc/host/omap.c +0 -0
index 67d7b7f..84de289 100644
@@ -157,8 +157,6 @@ struct mmc_omap_host {
 	struct timer_list	dma_timer;
 	unsigned		dma_len;
 
Quoted 8 lines

drivers/mmc/host/omap.c struct mmc_omap_host { · line 162

Quoted 6 lines
drivers/mmc/host/omap.c +0 -2
-	short			power_pin;
-
 	struct mmc_omap_slot    *slots[OMAP_MMC_MAX_SLOTS];
 	struct mmc_omap_slot    *current_slot;
 	spinlock_t              slot_lock;

Looks like power_pin could go though.

Updated patch follows

arch/arm/plat-omap/include/mach/mmc.h +0 -1
index 4435bd4..81d5b36 100644
@@ -79,7 +79,6 @@ struct omap_mmc_platform_data {
 
 		/* use the internal clock */
 		unsigned internal_clock:1;
-		s16 power_pin;
 
 		int switch_pin;			/* gpio (card detect) */
 		int gpio_wp;			/* gpio (write protect) */
drivers/mmc/host/omap.c +0 -2
index 67d7b7f..e8e0e09 100644
@@ -157,8 +157,6 @@ struct mmc_omap_host {
 	struct timer_list	dma_timer;
 	unsigned		dma_len;
 
-	short			power_pin;
-
 	struct mmc_omap_slot    *slots[OMAP_MMC_MAX_SLOTS];
 	struct mmc_omap_slot    *current_slot;
 	spinlock_t              slot_lock;
#8 lore raw

Re: [PATCH 2/5] omap mmc: Add better MMC low-level init

In reply to Tony Lindgren
Quoted 3 lines · Tony Lindgren

This will simplify the MMC low-level init, and make it more flexible to add support for a newer MMC controller in the following patches.

Simple simplification...

arch/arm/mach-omap1/board-h3-mmc.c +1 -5
index fdfe793..d7f40f9 100644
@@ -24,11 +24,7 @@
 static int mmc_set_power(struct device *dev, int slot, int power_on,
 				int vdd)
 {
-	if (power_on)
-		gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 1);
-	else
-		gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0);
-
+	gpio_set_value(H3_TPS_GPIO_MMC_PWR_EN, power_on);
 	return 0;
 }
 
arch/arm/mach-omap1/board-nokia770.c +1 -5
index 7fdb725..4de55c7 100644
@@ -223,11 +223,7 @@ static struct omap_usb_config nokia770_usb_config __initdata = {
 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);
-
+	gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on);
 	return 0;
 }
 
author maintainer
#9 lore raw

PATCH 3/5 omap mmc: Add low-level initialization for hsmmc controller

In reply to Tony Lindgren

Add low-level initialization for hsmmc controller. Merged into this patch patch are various improvments and board support by Grazvydas Ignotas and David Brownell.

Also change wire4 to be wires, as some newer controllers support 8 data lines.

---
 arch/arm/mach-omap1/board-innovator.c     |    2 
 arch/arm/mach-omap1/devices.c             |    4 
 arch/arm/mach-omap2/Makefile              |   15 +
 arch/arm/mach-omap2/board-2430sdp.c       |   48 +++
 arch/arm/mach-omap2/board-ldp.c           |   40 +++
 arch/arm/mach-omap2/board-omap3beagle.c   |   90 ++++++
 arch/arm/mach-omap2/board-omap3pandora.c  |   32 ++
 arch/arm/mach-omap2/board-overo.c         |   43 +++
 arch/arm/mach-omap2/devices.c             |    3 
 arch/arm/mach-omap2/mmc-twl4030.c         |  408 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/mmc-twl4030.h         |   29 ++
 arch/arm/plat-omap/include/mach/control.h |   17 +
 arch/arm/plat-omap/include/mach/mmc.h     |   16 +
 drivers/mmc/host/omap.c                   |    2 
 14 files changed, 730 insertions(+), 19 deletions(-)
 create mode 100644 arch/arm/mach-omap2/mmc-twl4030.c
 create mode 100644 arch/arm/mach-omap2/mmc-twl4030.h
arch/arm/mach-omap1/board-innovator.c +1 -1
index eee0657..f59acef 100644
@@ -385,7 +385,7 @@ static struct omap_mmc_platform_data mmc1_data = {
 	.nr_slots                       = 1,
 	.slots[0]       = {
 		.set_power		= mmc_set_power,
-		.wire4			= 1,
+		.wires			= 4,
 		.name                   = "mmcblk",
 	},
 };
arch/arm/mach-omap1/devices.c +2 -2
index 024dab1..77382d8 100644
@@ -116,7 +116,7 @@ static inline void omap1_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
 			omap_cfg_reg(P19_1710_MMC_CMDDIR);
 			omap_cfg_reg(P20_1710_MMC_DATDIR0);
 		}
-		if (mmc_controller->slots[0].wire4) {
+		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)
@@ -132,7 +132,7 @@ static inline void omap1_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
 			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].wire4) {
+			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);
arch/arm/mach-omap2/Makefile +10 -5
index f12c43e..bbd12bc 100644
@@ -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
 
arch/arm/mach-omap2/board-2430sdp.c +48 -0

72 lines not on this page · raw message

arch/arm/mach-omap2/board-ldp.c +39 -1
index 43c7ac4..aa69727 100644
@@ -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)
arch/arm/mach-omap2/board-omap3beagle.c +90 -0

120 lines not on this page · raw message

arch/arm/mach-omap2/board-omap3pandora.c +32 -0
index fcb6bdc..b3954a0 100644
@@ -46,6 +46,8 @@
 #include <mach/nand.h>
 #include <mach/mcspi.h>
 
+#include "mmc-twl4030.h"
+
 #define NAND_BLOCK_SIZE			SZ_128K
 #define GPMC_CS0_BASE			0x60
 #define GPMC_CS_SIZE			0x30
@@ -137,14 +139,44 @@ static void __init omap3pandora_flash_init(void)
 	}
 }
 
+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 = {
arch/arm/mach-omap2/board-overo.c +43 -0

75 lines not on this page · raw message

arch/arm/mach-omap2/devices.c +2 -1
index 8ccdfcf..6e03272 100644
@@ -19,6 +19,7 @@
 #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>
@@ -311,7 +312,7 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
 		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].wire4) {
+		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);
arch/arm/mach-omap2/mmc-twl4030.c new file +408 -0

408 lines not on this page · raw message

arch/arm/mach-omap2/mmc-twl4030.h new file +29 -0
new file mode 100644
index 0000000..e1c8076
@@ -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
arch/arm/plat-omap/include/mach/control.h +17 -0
index dc98867..269147f 100644
@@ -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);
arch/arm/plat-omap/include/mach/mmc.h +8 -8
index 0c2ef3b..031250f 100644
@@ -61,6 +61,11 @@ struct omap_mmc_platform_data {
 
 	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.
@@ -70,13 +75,12 @@ struct omap_mmc_platform_data {
 		/* 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;
+
+		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);
@@ -111,7 +115,6 @@ 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);
-void hsmmc_init(int controller_mask);
 int omap_mmc_add(int id, unsigned long base, unsigned long size,
 			unsigned int irq, struct omap_mmc_platform_data *data);
 #else
@@ -123,9 +126,6 @@ static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
 				int nr_controllers)
 {
 }
-static inline void hsmmc_init(int controller_mask)
-{
-}
 static inline int omap_mmc_add(int id, unsigned long base, unsigned long size,
 		unsigned int irq, struct omap_mmc_platform_data *data)
 {
drivers/mmc/host/omap.c +1 -1
index c6544d2..67d7b7f 100644
@@ -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->slots[id].wire4)
+	if (host->pdata->slots[id].wires >= 4)
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
 
 	mmc->ops = &mmc_omap_ops;
author maintainer
#10 lore raw

PATCH 4/5 omap mmc: force MMC module reset on boot

In reply to Tony Lindgren

From: Kevin Hilman <[email protected]>

The bootloader may leave the MMC in a state which prevents hitting retention. Even when MMC is not compiled in, each MMC module needs to be forced into reset.

---
 arch/arm/mach-omap2/devices.c |   85 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 85 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +85 -0
index 6e03272..9d7216f 100644
@@ -14,6 +14,7 @@
 #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>
@@ -299,6 +300,89 @@ static inline void omap_init_sha1_md5(void) { }
 
 /*-------------------------------------------------------------------------*/
 
+#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)
 
@@ -418,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();
author maintainer
#11 lore raw

PATCH 5/5 omap mmc: Add new omap hsmmc controller for 2430 and 34xx

In reply to Tony Lindgren

From: Madhusudhan Chikkature <[email protected]>

Add omap hsmmc controller for 2430 and 34xx.

Note that this controller has different registers compared to the earlier omap MMC controller, so sharing code currently is not possible.

Various updates and fixes from linux-omap list have been merged into this patch.

---
 drivers/mmc/host/Kconfig      |   11 
 drivers/mmc/host/Makefile     |    1 
 drivers/mmc/host/omap_hsmmc.c | 1242 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1254 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/Kconfig +11 -0
index dfa585f..63e3356 100644
@@ -76,6 +76,17 @@ config MMC_OMAP
 
 	  If unsure, say N.
 
+config MMC_OMAP_HS
+	tristate "TI OMAP High Speed Multimedia Card Interface support"
+	depends on (ARCH_OMAP2 && ARCH_OMAP2430) || ARCH_OMAP3
+	select TWL4030_CORE
+	help
+	  This selects the TI OMAP High Speed Multimedia card Interface.
+	  If you have an OMAP2(2430) or OMAP3 board with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_WBSD
 	tristate "Winbond W83L51xD SD/MMC Card Interface support"
 	depends on ISA_DMA_API
drivers/mmc/host/Makefile +1 -0
index c794cc5..ba477bc 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_RICOH_MMC)	+= ricoh_mmc.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
+obj-$(CONFIG_MMC_OMAP_HS)	+= omap_hsmmc.o
 obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
 obj-$(CONFIG_MMC_ATMELMCI)	+= atmel-mci.o
 obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
drivers/mmc/host/omap_hsmmc.c new file +1242 -0

1,242 lines not on this page · raw message

Acked-by on v1 5/5
#12 lore raw

Re: [PATCH 5/5] omap mmc: Add new omap hsmmc controller for 2430 and 34xx

drivers/mmc/host/omap_hsmmc.c line 254

Quoted 6 lines · On Sun, 07 Dec 2008 13:51:39 -0800 Tony Lindgren <[email protected]> wrote:
drivers/mmc/host/omap_hsmmc.c new file +6 -0
+	/*
+	 * Unlike OMAP1 controller, the cmdtype does not seem to be based on
+	 * ac, bc, adtc, bcr. Only CMD12 needs a val of 0x3, rest 0x0.
+	 */
+	if (cmd->opcode == 12)
+		cmdtype = 0x3;

Isn't it more likely that it needs 0x3 for any commands that ends an open ended transfer? I.e. every time cmd == mrq.stop.

drivers/mmc/host/omap_hsmmc.c line 946

Quoted 6 lines
drivers/mmc/host/omap_hsmmc.c new file +6 -0
+	host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
+	/*
+	 * MMC can still work without debounce clock.
+	 */
+	if (IS_ERR(host->dbclk))
+		dev_dbg(mmc_dev(host->mmc), "Failed to get debounce clock\n");

Perhaps a warning should be printed though, as there could be some problems caused by trying to init a card that is still bouncing.

Quoted 13 lines
drivers/mmc/host/omap_hsmmc.c new file +13 -0
+static int omap_mmc_remove(struct platform_device *pdev)
+{
+	struct mmc_omap_host *host = platform_get_drvdata(pdev);
+	struct resource *res;
+	u16 vdd = 0;
+
+	if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
+	/*
+	 * Set the vdd back to 3V,
+	 * applicable for dual volt support.
+	 */
+		vdd = fls(host->mmc->ocr_avail) - 1;
+		if (omap_mmc_switch_opcond(host, vdd) != 0)

drivers/mmc/host/omap_hsmmc.c line 1091

Quoted 10 lines
drivers/mmc/host/omap_hsmmc.c new file +10 -0
+			host->mmc->ios.vdd = vdd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res)
+		release_mem_region(res->start, res->end - res->start + 1);
+
+	platform_set_drvdata(pdev, NULL);
+	if (host) {
+		mmc_remove_host(host->mmc);

You can't go fiddling with the voltage and removing the MMIO until you've made sure that there is no more activity on the slot.

Fix the above issues and you can let it go via Russell with a:

Rgds

Signature · 9 lines
     -- Pierre Ossman

  Linux kernel, MMC maintainer        http://www.kernel.org
  rdesktop, core developer          http://www.rdesktop.org

  WARNING: This correspondence is being monitored by the
  Swedish government. Make sure your server uses encryption
  for SMTP traffic and consider using PGP for end-to-end
  encryption.
author maintainer
#13 lore raw

Re: [PATCH 5/5] omap mmc: Add new omap hsmmc controller for 2430 and 34xx

Hi,

Quoted 12 lines · Pierre Ossman

Review

Quoted 6 lines · On Sun, 07 Dec 2008 13:51:39 -0800 Tony Lindgren <[email protected]> wrote:
(quoted diff) +6 -0
+	/*
+	 * Unlike OMAP1 controller, the cmdtype does not seem to be based on
+	 * ac, bc, adtc, bcr. Only CMD12 needs a val of 0x3, rest 0x0.
+	 */
+	if (cmd->opcode == 12)
+		cmdtype = 0x3;

Isn't it more likely that it needs 0x3 for any commands that ends an open ended transfer? I.e. every time cmd == mrq.stop.

OK, changed and still works :)

Quoted 9 lines

Review

Quoted 6 lines
(quoted diff) +6 -0
+	host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
+	/*
+	 * MMC can still work without debounce clock.
+	 */
+	if (IS_ERR(host->dbclk))
+		dev_dbg(mmc_dev(host->mmc), "Failed to get debounce clock\n");

Perhaps a warning should be printed though, as there could be some problems caused by trying to init a card that is still bouncing.

OK

Quoted 18 lines
Quoted 18 lines
(quoted diff) +18 -0
+static int omap_mmc_remove(struct platform_device *pdev)
+{
+	struct mmc_omap_host *host = platform_get_drvdata(pdev);
+	struct resource *res;
+	u16 vdd = 0;
+
+	if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
+	/*
+	 * Set the vdd back to 3V,
+	 * applicable for dual volt support.
+	 */
+		vdd = fls(host->mmc->ocr_avail) - 1;
+		if (omap_mmc_switch_opcond(host, vdd) != 0)
+			host->mmc->ios.vdd = vdd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res)
Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+		release_mem_region(res->start, res->end - res->start + 1);
+
+	platform_set_drvdata(pdev, NULL);
+	if (host) {
+		mmc_remove_host(host->mmc);

You can't go fiddling with the voltage and removing the MMIO until you've made sure that there is no more activity on the slot.

Changed in the attached patch. I've changed the code to reset the controller voltage setting after powering down the socket instead of trying to do it in two earlier places..

Do you have any better suggestions for this? Basically it looks like the controller may fail to detect the next card after unplugging a 1.8V card unless the controller is reset to 3V.

Quoted 3 lines

Fix the above issues and you can let it go via Russell with a:

Thank you for your comments. Care to take a one more look at the attached patch before I add your Ack? I also fixed the remaining checkpatch warnings.

Regards,

Tony

Quoted 1 line

From f201a545403fdecaf3e2a77359e4adaf803871f5 Mon Sep 17 00:00:00 2001

From: Tony Lindgren <[email protected]>
Date: Mon, 29 Dec 2008 16:31:53 +0200
Subject: [PATCH] omap mmc: Add new omap hsmmc controller for 2430 and 34xx, v2

Add omap hsmmc controller for 2430 and 34xx.

Note that this controller has different registers compared to the earlier omap MMC controller, so sharing code currently is not possible.

Various updates and fixes from linux-omap list have been merged into this patch.

drivers/mmc/host/Kconfig +11 -0
index dfa585f..63e3356 100644
@@ -76,6 +76,17 @@ config MMC_OMAP
 
 	  If unsure, say N.
 
+config MMC_OMAP_HS
+	tristate "TI OMAP High Speed Multimedia Card Interface support"
+	depends on (ARCH_OMAP2 && ARCH_OMAP2430) || ARCH_OMAP3
+	select TWL4030_CORE
+	help
+	  This selects the TI OMAP High Speed Multimedia card Interface.
+	  If you have an OMAP2(2430) or OMAP3 board with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_WBSD
 	tristate "Winbond W83L51xD SD/MMC Card Interface support"
 	depends on ISA_DMA_API
drivers/mmc/host/Makefile +1 -0
index c794cc5..ba477bc 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_RICOH_MMC)	+= ricoh_mmc.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
+obj-$(CONFIG_MMC_OMAP_HS)	+= omap_hsmmc.o
 obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
 obj-$(CONFIG_MMC_ATMELMCI)	+= atmel-mci.o
 obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
drivers/mmc/host/omap_hsmmc.c new file +1242 -0

1,242 lines not on this page · raw message

author maintainer
#14 lore raw

Re: [PATCH 5/5] omap mmc: Add new omap hsmmc controller for 2430 and 34xx

Quoted 65 lines · Tony Lindgren

Hi,

Quoted 12 lines · Pierre Ossman

Review

Quoted 6 lines · On Sun, 07 Dec 2008 13:51:39 -0800 Tony Lindgren <[email protected]> wrote:
(quoted diff) +6 -0
+	/*
+	 * Unlike OMAP1 controller, the cmdtype does not seem to be based on
+	 * ac, bc, adtc, bcr. Only CMD12 needs a val of 0x3, rest 0x0.
+	 */
+	if (cmd->opcode == 12)
+		cmdtype = 0x3;

Isn't it more likely that it needs 0x3 for any commands that ends an open ended transfer? I.e. every time cmd == mrq.stop.

OK, changed and still works :)

Quoted 9 lines

Review

Quoted 6 lines
(quoted diff) +6 -0
+	host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
+	/*
+	 * MMC can still work without debounce clock.
+	 */
+	if (IS_ERR(host->dbclk))
+		dev_dbg(mmc_dev(host->mmc), "Failed to get debounce clock\n");

Perhaps a warning should be printed though, as there could be some problems caused by trying to init a card that is still bouncing.

OK

Quoted 18 lines
Quoted 18 lines
(quoted diff) +18 -0
+static int omap_mmc_remove(struct platform_device *pdev)
+{
+	struct mmc_omap_host *host = platform_get_drvdata(pdev);
+	struct resource *res;
+	u16 vdd = 0;
+
+	if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
+	/*
+	 * Set the vdd back to 3V,
+	 * applicable for dual volt support.
+	 */
+		vdd = fls(host->mmc->ocr_avail) - 1;
+		if (omap_mmc_switch_opcond(host, vdd) != 0)
+			host->mmc->ios.vdd = vdd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res)
Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+		release_mem_region(res->start, res->end - res->start + 1);
+
+	platform_set_drvdata(pdev, NULL);
+	if (host) {
+		mmc_remove_host(host->mmc);

You can't go fiddling with the voltage and removing the MMIO until you've made sure that there is no more activity on the slot.

Changed in the attached patch. I've changed the code to reset the controller voltage setting after powering down the socket instead of trying to do it in two earlier places..

Do you have any better suggestions for this? Basically it looks like the controller may fail to detect the next card after unplugging a 1.8V card unless the controller is reset to 3V.

Quoted 7 lines
Quoted 3 lines

Fix the above issues and you can let it go via Russell with a:

Thank you for your comments. Care to take a one more look at the attached patch before I add your Ack? I also fixed the remaining checkpatch warnings.

Here's one more version that leaves out the unnecessary TWL4030 dependency in the Kconfig as pointed out by David Brownell.

Quoted 4 lines

Regards,

Tony
From ce15009433bcc482c439326fd08960e6d1f0eb1a Mon Sep 17 00:00:00 2001

From: Tony Lindgren <[email protected]>
Date: Mon, 29 Dec 2008 16:31:53 +0200
Subject: [PATCH] omap mmc: Add new omap hsmmc controller for 2430 and 34xx, v3

Add omap hsmmc controller for 2430 and 34xx.

Note that this controller has different registers compared to the earlier omap MMC controller, so sharing code currently is not possible.

Various updates and fixes from linux-omap list have been merged into this patch.

drivers/mmc/host/Kconfig +10 -0
index dfa585f..0efa390 100644
@@ -76,6 +76,16 @@ config MMC_OMAP
 
 	  If unsure, say N.
 
+config MMC_OMAP_HS
+	tristate "TI OMAP High Speed Multimedia Card Interface support"
+	depends on ARCH_OMAP2430 || ARCH_OMAP3
+	help
+	  This selects the TI OMAP High Speed Multimedia card Interface.
+	  If you have an OMAP2430 or OMAP3 board with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_WBSD
 	tristate "Winbond W83L51xD SD/MMC Card Interface support"
 	depends on ISA_DMA_API
drivers/mmc/host/Makefile +1 -0
index c794cc5..ba477bc 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_RICOH_MMC)	+= ricoh_mmc.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
+obj-$(CONFIG_MMC_OMAP_HS)	+= omap_hsmmc.o
 obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
 obj-$(CONFIG_MMC_ATMELMCI)	+= atmel-mci.o
 obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
drivers/mmc/host/omap_hsmmc.c new file +1242 -0

1,242 lines not on this page · raw message

Acked-by
#15 lore raw

Re: [PATCH 5/5] omap mmc: Add new omap hsmmc controller for 2430 and 34xx

Quoted 4 lines · On Tue, 30 Dec 2008 10:36:26 +0200 Tony Lindgren <[email protected]> wrote:

Here's one more version that leaves out the unnecessary TWL4030 dependency in the Kconfig as pointed out by David Brownell.

Looks ok.

Signature · 9 lines
     -- Pierre Ossman

  Linux kernel, MMC maintainer        http://www.kernel.org
  rdesktop, core developer          http://www.rdesktop.org

  WARNING: This correspondence is being monitored by the
  Swedish government. Make sure your server uses encryption
  for SMTP traffic and consider using PGP for end-to-end
  encryption.
author maintainer
#16 lore raw

Re: [PATCH 5/5] omap mmc: Add new omap hsmmc controller for 2430 and 34xx

Quoted 11 lines · Pierre Ossman
Quoted 4 lines · On Tue, 30 Dec 2008 10:36:26 +0200 Tony Lindgren <[email protected]> wrote:

Here's one more version that leaves out the unnecessary TWL4030 dependency in the Kconfig as pointed out by David Brownell.

Looks ok.

Thanks, I'll queue it up with Russell with one change to include <mach/dma.h> instead of <asm/dma.h>.

All further patches to this driver will come to you via LKML.

Regards,

Tony

Quoted 16 lines
Signature · 15 lines
-- 
     -- Pierre Ossman

  Linux kernel, MMC maintainer        http://www.kernel.org
  rdesktop, core developer          http://www.rdesktop.org

  WARNING: This correspondence is being monitored by the
  Swedish government. Make sure your server uses encryption
  for SMTP traffic and consider using PGP for end-to-end
  encryption.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
#17 lore raw

PATCH 1/1 OMAP: MMC: recover from transfer failures (was: Re: [PATCH 5/5] omap mmc: Add new omap hsmmc controller for 2430 and 34xx)

Tony, Pierre,

Here is a patch that fixes a MMC host controller deadlock. The problem happens when removing the MMC/SD device when a transfer is on-going.

It has been tested on OMAP3430 but this fix should apply to OMAP2 chips as well, as seen from the TRMs.

What do you think?

Regards,
Jean.

OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

The indication that the mmc host controller is in this error state is that the DATI bit is set in the PSTATE register. This patch checks to see if the DATI bit is set before starting a new command, and if it is set it resets the data state machine to clear the error.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

Regards,
Jean

From 48a40925a4d57f6e7e45809a4b5c09b20f9314d7 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Tue, 16 Dec 2008 19:44:12 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

The indication that the mmc host controller is in this error state is that the DATI bit is set in the PSTATE register. This patch checks to see if the DATI bit is set before starting a new command, and if it is set it resets the data state machine to clear the error.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
drivers/mmc/host/omap_hsmmc.c +2 -0
index 1fcc544..b7d111e 100644
@@ -44,6 +44,7 @@
 #define OMAP_HSMMC_RSP54       0x0118
 #define OMAP_HSMMC_RSP76       0x011C
 #define OMAP_HSMMC_DATA                0x0120
+#define OMAP_HSMMC_PSTATE      0x0124
 #define OMAP_HSMMC_HCTL                0x0128
 #define OMAP_HSMMC_SYSCTL      0x012C
 #define OMAP_HSMMC_STAT                0x0130
@@ -89,6 +90,7 @@
 #define DUAL_VOLT_OCR_BIT      7
 #define SRC                    (1 << 25)
 #define SRD                    (1 << 26)
+#define DATI                   (1 << 1)
 
 /*
  * FIXME: Most likely all the data using these _DEVID defines should come
@@ -273,6 +275,15 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct 

mmc_command *cmd,

                mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
        host->cmd = cmd;

+ if (OMAP_HSMMC_READ(host->base, PSTATE) & DATI) {
+ dev_dbg(mmc_dev(host->mmc), "mmc_omap_start_command: "
+ " resetting data state machine\n");
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
+ while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
+ ;
+ }
+

        /*
         * Clear status bits and enable interrupts
         */
Signature · 1 line
1.5.4.4.21.gc4a6c
Quoted 37 lines · On Wednesday 07 January 2009 11:18:13 Tony Lindgren wrote:
Quoted 9 lines · Pierre Ossman

On Tue, 30 Dec 2008 10:36:26 +0200

Quoted 2 lines · Tony Lindgren

Here's one more version that leaves out the unnecessary TWL4030 dependency in the Kconfig as pointed out by David Brownell.

Looks ok.

Thanks, I'll queue it up with Russell with one change to include <mach/dma.h> instead of <asm/dma.h>.

All further patches to this driver will come to you via LKML.

Regards,

Tony

Quoted 6 lines

--
-- Pierre Ossman

Linux kernel, MMC maintainer http://www.kernel.org
rdesktop, core developer http://www.rdesktop.org

Quoted 9 lines

WARNING: This correspondence is being monitored by the Swedish government. Make sure your server uses encryption for SMTP traffic and consider using PGP for end-to-end encryption.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Quoted 4 lines

-------------------------------------------------------------------

List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php

From 48a40925a4d57f6e7e45809a4b5c09b20f9314d7 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Tue, 16 Dec 2008 19:44:12 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

The indication that the mmc host controller is in this error state is that the DATI bit is set in the PSTATE register. This patch checks to see if the DATI bit is set before starting a new command, and if it is set it resets the data state machine to clear the error.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
drivers/mmc/host/omap_hsmmc.c +11 -0
index 1fcc544..b7d111e 100644
@@ -44,6 +44,7 @@
 #define OMAP_HSMMC_RSP54	0x0118
 #define OMAP_HSMMC_RSP76	0x011C
 #define OMAP_HSMMC_DATA		0x0120
+#define OMAP_HSMMC_PSTATE	0x0124
 #define OMAP_HSMMC_HCTL		0x0128
 #define OMAP_HSMMC_SYSCTL	0x012C
 #define OMAP_HSMMC_STAT		0x0130
@@ -89,6 +90,7 @@
 #define DUAL_VOLT_OCR_BIT	7
 #define SRC			(1 << 25)
 #define SRD			(1 << 26)
+#define DATI			(1 << 1)
 
 /*
  * FIXME: Most likely all the data using these _DEVID defines should come
@@ -273,6 +275,15 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
 		mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
 	host->cmd = cmd;
 
+	if (OMAP_HSMMC_READ(host->base, PSTATE) & DATI) {
+		dev_dbg(mmc_dev(host->mmc), "mmc_omap_start_command: "
+			" resetting data state machine\n");
+		OMAP_HSMMC_WRITE(host->base, SYSCTL,
+			OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
+		while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
+			;
+	}
+
 	/*
 	 * Clear status bits and enable interrupts
 	 */
Signature · 1 line
1.5.4.4.21.gc4a6c
author maintainer
#18 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures (was: Re: [PATCH 5/5] omap mmc: Add new omap hsmmc controller for 2430 and 34xx)

Hi,

Quoted 9 lines · Jean Pihet

Tony, Pierre,

Here is a patch that fixes a MMC host controller deadlock. The problem happens when removing the MMC/SD device when a transfer is on-going.

It has been tested on OMAP3430 but this fix should apply to OMAP2 chips as well, as seen from the TRMs.

What do you think?

Looks OK to me, adding Jarkko to Cc.

Tony

Quoted 195 lines

Regards,
Jean.

OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

The indication that the mmc host controller is in this error state is that the DATI bit is set in the PSTATE register. This patch checks to see if the DATI bit is set before starting a new command, and if it is set it resets the data state machine to clear the error.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

Regards,
Jean

From 48a40925a4d57f6e7e45809a4b5c09b20f9314d7 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Tue, 16 Dec 2008 19:44:12 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

The indication that the mmc host controller is in this error state is that the DATI bit is set in the PSTATE register. This patch checks to see if the DATI bit is set before starting a new command, and if it is set it resets the data state machine to clear the error.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
drivers/mmc/host/omap_hsmmc.c +11 -0
index 1fcc544..b7d111e 100644
@@ -44,6 +44,7 @@
 #define OMAP_HSMMC_RSP54       0x0118
 #define OMAP_HSMMC_RSP76       0x011C
 #define OMAP_HSMMC_DATA                0x0120
+#define OMAP_HSMMC_PSTATE      0x0124
 #define OMAP_HSMMC_HCTL                0x0128
 #define OMAP_HSMMC_SYSCTL      0x012C
 #define OMAP_HSMMC_STAT                0x0130
@@ -89,6 +90,7 @@
 #define DUAL_VOLT_OCR_BIT      7
 #define SRC                    (1 << 25)
 #define SRD                    (1 << 26)
+#define DATI                   (1 << 1)
 
 /*
  * FIXME: Most likely all the data using these _DEVID defines should come
@@ -273,6 +275,15 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct 
 mmc_command *cmd,
                mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
        host->cmd = cmd;
 
+       if (OMAP_HSMMC_READ(host->base, PSTATE) & DATI) {
+               dev_dbg(mmc_dev(host->mmc), "mmc_omap_start_command: "
+                       " resetting data state machine\n");
+               OMAP_HSMMC_WRITE(host->base, SYSCTL,
+                       OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
+               while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
+                       ;
+       }
+
        /*
         * Clear status bits and enable interrupts
         */
Signature · 1 line
1.5.4.4.21.gc4a6c
Quoted 37 lines · On Wednesday 07 January 2009 11:18:13 Tony Lindgren wrote:
Quoted 9 lines · Pierre Ossman

On Tue, 30 Dec 2008 10:36:26 +0200

Quoted 2 lines · Tony Lindgren

Here's one more version that leaves out the unnecessary TWL4030 dependency in the Kconfig as pointed out by David Brownell.

Looks ok.

Thanks, I'll queue it up with Russell with one change to include <mach/dma.h> instead of <asm/dma.h>.

All further patches to this driver will come to you via LKML.

Regards,

Tony

Quoted 6 lines

--
-- Pierre Ossman

Linux kernel, MMC maintainer http://www.kernel.org
rdesktop, core developer http://www.rdesktop.org

Quoted 9 lines

WARNING: This correspondence is being monitored by the Swedish government. Make sure your server uses encryption for SMTP traffic and consider using PGP for end-to-end encryption.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Quoted 4 lines

-------------------------------------------------------------------

List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php

From 48a40925a4d57f6e7e45809a4b5c09b20f9314d7 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Tue, 16 Dec 2008 19:44:12 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

The indication that the mmc host controller is in this error state is that the DATI bit is set in the PSTATE register. This patch checks to see if the DATI bit is set before starting a new command, and if it is set it resets the data state machine to clear the error.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
drivers/mmc/host/omap_hsmmc.c +11 -0
index 1fcc544..b7d111e 100644
@@ -44,6 +44,7 @@
 #define OMAP_HSMMC_RSP54	0x0118
 #define OMAP_HSMMC_RSP76	0x011C
 #define OMAP_HSMMC_DATA		0x0120
+#define OMAP_HSMMC_PSTATE	0x0124
 #define OMAP_HSMMC_HCTL		0x0128
 #define OMAP_HSMMC_SYSCTL	0x012C
 #define OMAP_HSMMC_STAT		0x0130
@@ -89,6 +90,7 @@
 #define DUAL_VOLT_OCR_BIT	7
 #define SRC			(1 << 25)
 #define SRD			(1 << 26)
+#define DATI			(1 << 1)
 
 /*
  * FIXME: Most likely all the data using these _DEVID defines should come
@@ -273,6 +275,15 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
 		mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
 	host->cmd = cmd;
 
+	if (OMAP_HSMMC_READ(host->base, PSTATE) & DATI) {
+		dev_dbg(mmc_dev(host->mmc), "mmc_omap_start_command: "
+			" resetting data state machine\n");
+		OMAP_HSMMC_WRITE(host->base, SYSCTL,
+			OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
+		while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
+			;
+	}
+
 	/*
 	 * Clear status bits and enable interrupts
 	 */
Signature · 1 line
1.5.4.4.21.gc4a6c
#19 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures

In reply to Jean Pihet
Quoted 90 lines · Jean Pihet

Tony, Pierre,

Here is a patch that fixes a MMC host controller deadlock. The problem happens when removing the MMC/SD device when a transfer is on-going.

It has been tested on OMAP3430 but this fix should apply to OMAP2 chips as well, as seen from the TRMs.

What do you think?

Regards,
Jean.

OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

The indication that the mmc host controller is in this error state is that the DATI bit is set in the PSTATE register. This patch checks to see if the DATI bit is set before starting a new command, and if it is set it resets the data state machine to clear the error.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

Regards,
Jean

From 48a40925a4d57f6e7e45809a4b5c09b20f9314d7 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Tue, 16 Dec 2008 19:44:12 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

The indication that the mmc host controller is in this error state is that the DATI bit is set in the PSTATE register. This patch checks to see if the DATI bit is set before starting a new command, and if it is set it resets the data state machine to clear the error.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
drivers/mmc/host/omap_hsmmc.c +11 -0
index 1fcc544..b7d111e 100644
@@ -44,6 +44,7 @@
 #define OMAP_HSMMC_RSP54       0x0118
 #define OMAP_HSMMC_RSP76       0x011C
 #define OMAP_HSMMC_DATA                0x0120
+#define OMAP_HSMMC_PSTATE      0x0124
 #define OMAP_HSMMC_HCTL                0x0128
 #define OMAP_HSMMC_SYSCTL      0x012C
 #define OMAP_HSMMC_STAT                0x0130
@@ -89,6 +90,7 @@
 #define DUAL_VOLT_OCR_BIT      7
 #define SRC                    (1 << 25)
 #define SRD                    (1 << 26)
+#define DATI                   (1 << 1)
 
 /*
  * FIXME: Most likely all the data using these _DEVID defines should come
@@ -273,6 +275,15 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct 
 mmc_command *cmd,
                mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
        host->cmd = cmd;
 
+       if (OMAP_HSMMC_READ(host->base, PSTATE) & DATI) {
+               dev_dbg(mmc_dev(host->mmc), "mmc_omap_start_command: "
+                       " resetting data state machine\n");
+               OMAP_HSMMC_WRITE(host->base, SYSCTL,
+                       OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
+               while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
+                       ;
+       }
+
        /*
         * Clear status bits and enable interrupts
Quoted 2 lines
         */

Why not do the reset in mmc_omap_irq() like the other resets? e.g.

static irqreturn_t mmc_omap_irq(int irq, void *dev_id)

{
	struct mmc_omap_host *host = dev_id;
	struct mmc_data *data;
	int end_cmd = 0, end_trans = 0, status;

	if (host->cmd == NULL && host->data == NULL) {
		OMAP_HSMMC_WRITE(host->base, STAT,
			OMAP_HSMMC_READ(host->base, STAT));
		return IRQ_HANDLED;
	}

	data = host->data;
	status = OMAP_HSMMC_READ(host->base, STAT);
	dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);

	if (status & ERR) {
#ifdef CONFIG_MMC_DEBUG
		mmc_omap_report_irq(host, status);
#endif
		if ((status & CMD_TIMEOUT) ||
			(status & CMD_CRC)) {
			if (host->cmd) {
				if (status & CMD_TIMEOUT) {
					OMAP_HSMMC_WRITE(host->base, SYSCTL,
						OMAP_HSMMC_READ(host->base,
								SYSCTL) | SRC);
					while (OMAP_HSMMC_READ(host->base,
							SYSCTL) & SRC)
						;

					host->cmd->error = -ETIMEDOUT;
				} else {
					host->cmd->error = -EILSEQ;
				}
				end_cmd = 1;
			}
-			if (host->data)
+			if (host->data) {
				mmc_dma_cleanup(host);

+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base,
+ SYSCTL) | SRD);
+ while (OMAP_HSMMC_READ(host->base,
+ SYSCTL) & SRD)
+ ;
+ }

		}
		if ((status & DATA_TIMEOUT) ||
			(status & DATA_CRC)) {
			if (host->data) {
				if (status & DATA_TIMEOUT)
					mmc_dma_cleanup(host);
				else
					host->data->error = -EILSEQ;
				OMAP_HSMMC_WRITE(host->base, SYSCTL,
					OMAP_HSMMC_READ(host->base,
							SYSCTL) | SRD);
				while (OMAP_HSMMC_READ(host->base,
						SYSCTL) & SRD)
					;
				end_trans = 1;
			}
		}
#20 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures

Thanks for the suggestion, it works great (stress tested) and is a cleaner fix.
Here is a patch the latest linux-omap-2.6 tree. Is this OK?

Regards,
Jean

From d143f6b2e705aa4e9d2b032097fd1c82f8163262 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Thu, 8 Jan 2009 12:35:21 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

This patch resets the data state machine to clear the error in case of a command timeout.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/mmc/host/omap_hsmmc.c +8 -1
index d5c1e9d..97150c0 100644
@@ -464,8 +464,15 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                }
                                end_cmd = 1;
                        }
-                       if (host->data)
+                       if (host->data) {
                                mmc_dma_cleanup(host);
+                               OMAP_HSMMC_WRITE(host->base, SYSCTL,
+                                       OMAP_HSMMC_READ(host->base,
+                                                       SYSCTL) | SRD);
+                               while (OMAP_HSMMC_READ(host->base,
+                                               SYSCTL) & SRD)
+                                       ;
+                       }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {

--
1.5.4.4.21.gc4a6c

Quoted 24 lines · On Thursday 08 January 2009 10:02:24 Adrian Hunter wrote:

Why not do the reset in mmc_omap_irq() like the other resets? e.g.

static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
...
                if ((status & CMD_TIMEOUT) ||
                        (status & CMD_CRC)) {
                        if (host->cmd) {
                                if (status & CMD_TIMEOUT) { OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | SRC); while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRC) ;

                                        host->cmd->error = -ETIMEDOUT; } else {
                                        host->cmd->error = -EILSEQ; }
                                end_cmd = 1;
                        }
-                       if (host->data)
+                       if (host->data) { mmc_dma_cleanup(host);
+                               OMAP_HSMMC_WRITE(host->base, SYSCTL, +                                       OMAP_HSMMC_READ(host->base,

Quoted 8 lines

+                                                       SYSCTL) | SRD); +                               while (OMAP_HSMMC_READ(host->base, +                                               SYSCTL) & SRD) +                                       ;
+                       }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {

From d143f6b2e705aa4e9d2b032097fd1c82f8163262 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Thu, 8 Jan 2009 12:35:21 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

This patch resets the data state machine to clear the error in case of a command timeout.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/mmc/host/omap_hsmmc.c +8 -1
index d5c1e9d..97150c0 100644
@@ -464,8 +464,15 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 				}
 				end_cmd = 1;
 			}
-			if (host->data)
+			if (host->data) {
 				mmc_dma_cleanup(host);
+				OMAP_HSMMC_WRITE(host->base, SYSCTL,
+					OMAP_HSMMC_READ(host->base,
+							SYSCTL) | SRD);
+				while (OMAP_HSMMC_READ(host->base,
+						SYSCTL) & SRD)
+					;
+			}
 		}
 		if ((status & DATA_TIMEOUT) ||
 			(status & DATA_CRC)) {
Signature · 1 line
1.5.4.4.21.gc4a6c
#21 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures

Quoted 2 lines · Jean Pihet

Thanks for the suggestion, it works great (stress tested) and is a cleaner fix. Here is a patch the latest linux-omap-2.6 tree. Is this OK?

OK by me.

Quoted 87 lines

Regards,
Jean

From d143f6b2e705aa4e9d2b032097fd1c82f8163262 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Thu, 8 Jan 2009 12:35:21 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

This patch resets the data state machine to clear the error in case of a command timeout.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/mmc/host/omap_hsmmc.c +8 -2
index d5c1e9d..97150c0 100644
@@ -464,8 +464,15 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                }
                                end_cmd = 1;
                        }
-                       if (host->data)
+                       if (host->data) {
                                mmc_dma_cleanup(host);
+                               OMAP_HSMMC_WRITE(host->base, SYSCTL,
+                                       OMAP_HSMMC_READ(host->base,
+                                                       SYSCTL) | SRD);
+                               while (OMAP_HSMMC_READ(host->base,
+                                               SYSCTL) & SRD)
+                                       ;
+                       }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {
--

1.5.4.4.21.gc4a6c

Quoted 32 lines · On Thursday 08 January 2009 10:02:24 Adrian Hunter wrote:

Why not do the reset in mmc_omap_irq() like the other resets? e.g.

static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
...

                if ((status & CMD_TIMEOUT) ||
                        (status & CMD_CRC)) {
                        if (host->cmd) {
                                if (status & CMD_TIMEOUT) {
                                        OMAP_HSMMC_WRITE(host->base,

SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | SRC); while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRC) ;

                                        host->cmd->error = -ETIMEDOUT;
                                } else {
                                        host->cmd->error = -EILSEQ;
                                }
                                end_cmd = 1;
                        }
drivers/mmc/host/omap_hsmmc.c +8 -1
-                       if (host->data)
+                       if (host->data) {
                                mmc_dma_cleanup(host);
+                               OMAP_HSMMC_WRITE(host->base, SYSCTL,
+                                       OMAP_HSMMC_READ(host->base,
+                                                       SYSCTL) | SRD);
+                               while (OMAP_HSMMC_READ(host->base,
+                                               SYSCTL) & SRD)
+                                       ;
+                       }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {
#22 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures

In reply to Jean Pihet

Tony,

Has this patch been applied to the linux-omap tree? Does it need to go the patchwork?

Cf. http://marc.info/?l=linux-omap&m=123141577308177&w=2

Regards,
Jean

Quoted 87 lines · On Thursday 08 January 2009 12:49:19 Jean Pihet wrote:

Thanks for the suggestion, it works great (stress tested) and is a cleaner fix.
Here is a patch the latest linux-omap-2.6 tree. Is this OK?

Regards,
Jean

From d143f6b2e705aa4e9d2b032097fd1c82f8163262 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Thu, 8 Jan 2009 12:35:21 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

This patch resets the data state machine to clear the error in case of a command timeout.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/mmc/host/omap_hsmmc.c +8 -2
index d5c1e9d..97150c0 100644
@@ -464,8 +464,15 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                }
                                end_cmd = 1;
                        }
-                       if (host->data)
+                       if (host->data) {
                                mmc_dma_cleanup(host);
+                               OMAP_HSMMC_WRITE(host->base, SYSCTL,
+                                       OMAP_HSMMC_READ(host->base,
+                                                       SYSCTL) | SRD);
+                               while (OMAP_HSMMC_READ(host->base,
+                                               SYSCTL) & SRD)
+                                       ;
+                       }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {
--

1.5.4.4.21.gc4a6c

Quoted 32 lines · On Thursday 08 January 2009 10:02:24 Adrian Hunter wrote:

Why not do the reset in mmc_omap_irq() like the other resets? e.g.

static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
...
                if ((status & CMD_TIMEOUT) ||
                        (status & CMD_CRC)) {
                        if (host->cmd) {
                                if (status & CMD_TIMEOUT) { OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | SRC); while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRC) ;

                                        host->cmd->error = -ETIMEDOUT; } else {
                                        host->cmd->error = -EILSEQ; }
                                end_cmd = 1;
                        }
-                       if (host->data)
+                       if (host->data) { mmc_dma_cleanup(host);
+                               OMAP_HSMMC_WRITE(host->base, SYSCTL, +                                       OMAP_HSMMC_READ(host->base, +                                                       SYSCTL) | SRD); +                               while (OMAP_HSMMC_READ(host->base, +                                               SYSCTL) & SRD) +                                       ;
+                       }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {

author maintainer
#23 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures

Hi,

Quoted 6 lines · Jean Pihet

Tony,

Has this patch been applied to the linux-omap tree? Does it need to go the patchwork?

Cf. http://marc.info/?l=linux-omap&m=123141577308177&w=2

I'm not applying MMC patches, we need to move that discussion to LKML and keep Pierre involved.

Jarkko Lavinen was planning to set up a git branch against the mainline tree for the omap mmc patches, so until we have that, let's just let the patches float on the list for a while.

But yeah, if you want patchwork to pick up your patch so it does not get lost, just please resend it to the linux-omap list and it should get automatically picked up by patchwork.

Regards,

Tony

Quoted 93 lines

Regards,
Jean

Quoted 87 lines · On Thursday 08 January 2009 12:49:19 Jean Pihet wrote:

Thanks for the suggestion, it works great (stress tested) and is a cleaner fix.
Here is a patch the latest linux-omap-2.6 tree. Is this OK?

Regards,
Jean

From d143f6b2e705aa4e9d2b032097fd1c82f8163262 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Thu, 8 Jan 2009 12:35:21 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

This patch resets the data state machine to clear the error in case of a command timeout.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/mmc/host/omap_hsmmc.c +8 -2
index d5c1e9d..97150c0 100644
@@ -464,8 +464,15 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                }
                                end_cmd = 1;
                        }
-                       if (host->data)
+                       if (host->data) {
                                mmc_dma_cleanup(host);
+                               OMAP_HSMMC_WRITE(host->base, SYSCTL,
+                                       OMAP_HSMMC_READ(host->base,
+                                                       SYSCTL) | SRD);
+                               while (OMAP_HSMMC_READ(host->base,
+                                               SYSCTL) & SRD)
+                                       ;
+                       }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {
--

1.5.4.4.21.gc4a6c

Quoted 32 lines · On Thursday 08 January 2009 10:02:24 Adrian Hunter wrote:

Why not do the reset in mmc_omap_irq() like the other resets? e.g.

static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
...
                if ((status & CMD_TIMEOUT) ||
                        (status & CMD_CRC)) {
                        if (host->cmd) {
                                if (status & CMD_TIMEOUT) { OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | SRC); while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRC) ;

                                        host->cmd->error = -ETIMEDOUT; } else {
                                        host->cmd->error = -EILSEQ; }
                                end_cmd = 1;
                        }
-                       if (host->data)
+                       if (host->data) { mmc_dma_cleanup(host);
+                               OMAP_HSMMC_WRITE(host->base, SYSCTL, +                                       OMAP_HSMMC_READ(host->base, +                                                       SYSCTL) | SRD); +                               while (OMAP_HSMMC_READ(host->base, +                                               SYSCTL) & SRD) +                                       ;
+                       }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#24 lore raw

PATCH 1/1 OMAP: MMC: recover from transfer failures - Resend

Hi,

This is a re-send of the patch that fixes a MMC host controller deadlock. The problem happens when removing the MMC/SD device when a transfer is on-going.

It has been tested on OMAP3430 but this fix should apply to OMAP2 chips as well, as seen from the TRMs.

Regards,
Jean

From d143f6b2e705aa4e9d2b032097fd1c82f8163262 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Thu, 8 Jan 2009 12:35:21 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

This patch resets the data state machine to clear the error in case of a command timeout.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |    9 ++++++++-

 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/mmc/host/omap_hsmmc.c +0 -0
index d5c1e9d..97150c0 100644
@@ -464,8 +464,15 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)

                                }
                                end_cmd = 1;
                        }
-                       if (host->data)
+                       if (host->data) { mmc_dma_cleanup(host);
+                               OMAP_HSMMC_WRITE(host->base, SYSCTL,
+                                       OMAP_HSMMC_READ(host->base,
+                                                       SYSCTL) | SRD);
+                               while (OMAP_HSMMC_READ(host->base,
+                                               SYSCTL) & SRD)
+                                       ;
+                       }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {
--
1.5.4.4.21.gc4a6c

Quoted 17 lines · On Monday 02 February 2009 20:05:06 Tony Lindgren wrote:

Hi,

Quoted 6 lines · Jean Pihet

Tony,

Has this patch been applied to the linux-omap tree? Does it need to go the patchwork?

Cf. http://marc.info/?l=linux-omap&m=123141577308177&w=2

I'm not applying MMC patches, we need to move that discussion to LKML and keep Pierre involved.

Jarkko Lavinen was planning to set up a git branch against the mainline tree for the omap mmc patches, so until we have that, let's just let the patches float on the list for a while.

Quoted 7 lines

But yeah, if you want patchwork to pick up your patch so it does not get lost, just please resend it to the linux-omap list and it should get automatically picked up by patchwork.

Regards,

Tony

From d143f6b2e705aa4e9d2b032097fd1c82f8163262 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Thu, 8 Jan 2009 12:35:21 +0100
Subject: [PATCH] OMAP: MMC: recover from transfer failures

Timeouts during a command that has a data phase can result in the next command issued after the command that failed not being processed, i.e. no interrupt ever occurs to indicate the command has completed. This failure can result in a deadlock.

This patch resets the data state machine to clear the error in case of a command timeout.

Tested on OMAP3430 chip and intensive MMC/SD device removal while transferring data.

---
 drivers/mmc/host/omap_hsmmc.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/mmc/host/omap_hsmmc.c +8 -1
index d5c1e9d..97150c0 100644
@@ -464,8 +464,15 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 				}
 				end_cmd = 1;
 			}
-			if (host->data)
+			if (host->data) {
 				mmc_dma_cleanup(host);
+				OMAP_HSMMC_WRITE(host->base, SYSCTL,
+					OMAP_HSMMC_READ(host->base,
+							SYSCTL) | SRD);
+				while (OMAP_HSMMC_READ(host->base,
+						SYSCTL) & SRD)
+					;
+			}
 		}
 		if ((status & DATA_TIMEOUT) ||
 			(status & DATA_CRC)) {
Signature · 1 line
1.5.4.4.21.gc4a6c
#25 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend

drivers/mmc/host/omap_hsmmc.c static irqreturn_t mmc_omap_irq(int irq, void *dev_id) · line 474

Quoted 3 lines · On Tue, 3 Feb 2009 15:05:58 +0100 Jean Pihet <[email protected]> wrote:
drivers/mmc/host/omap_hsmmc.c +3 -0
+	while (OMAP_HSMMC_READ(host->base,
+ 			SYSCTL) & SRD)
+ 		;

Is a __raw_readl() sufficient to prevent the cpu from burning up here, or should we add cpu_relax()?

An infinite loop which assumes the hardware is perfect is always a worry. But I see the driver already does that, so we're no worse off..

-------------------------------------------------------------------

List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php
maintainer
#26 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend

Quoted 9 lines · Andrew Morton

drivers/mmc/host/omap_hsmmc.c static irqreturn_t mmc_omap_irq(int irq, void *dev_id) · line 474

Quoted 3 lines · On Tue, 3 Feb 2009 15:05:58 +0100 Jean Pihet <[email protected]> wrote:
drivers/mmc/host/omap_hsmmc.c +3 -0
+	while (OMAP_HSMMC_READ(host->base,
+ 			SYSCTL) & SRD)
+ 		;

Is a __raw_readl() sufficient to prevent the cpu from burning up here, or should we add cpu_relax()?

The __raw_readl() should be sufficient. The MMC controller is located on the L4 CORE interconnect, so the round trip latency for the read from MMC is at least 90 ns, while the CPU cycle time is only about 1 to 2 ns.

Quoted 2 lines

An infinite loop which assumes the hardware is perfect is always a worry. But I see the driver already does that, so we're no worse off..

- Paul

#27 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend

Quoted 11 lines · On Thursday 05 February 2009 21:32:03 Paul Walmsley wrote:
Quoted 9 lines · Andrew Morton

On Tue, 3 Feb 2009 15:05:58 +0100

drivers/mmc/host/omap_hsmmc.c static irqreturn_t mmc_omap_irq(int irq, void *dev_id) · line 474

Quoted 3 lines · Jean Pihet
drivers/mmc/host/omap_hsmmc.c +3 -0
+	while (OMAP_HSMMC_READ(host->base,
+ 			SYSCTL) & SRD)
+ 		;

Is a __raw_readl() sufficient to prevent the cpu from burning up here, or should we add cpu_relax()?

Quoted 3 lines

The __raw_readl() should be sufficient. The MMC controller is located on the L4 CORE interconnect, so the round trip latency for the read from MMC is at least 90 ns, while the CPU cycle time is only about 1 to 2 ns.

Ok.

Quoted 3 lines
Quoted 3 lines

An infinite loop which assumes the hardware is perfect is always a worry. But I see the driver already does that, so we're no worse off..

Do you want a finite loop with udelay in it? I located 4 places were this could be used. If so I can generate a new patch for that.

Quoted 2 lines

- Paul

Regards,
Jean

#28 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend

Quoted 7 lines · On Fri, 6 Feb 2009 14:22:32 +0100 Jean Pihet <[email protected]> wrote:
Quoted 3 lines · On Thursday 05 February 2009 21:32:03 Paul Walmsley wrote:
Quoted 2 lines · Andrew Morton

An infinite loop which assumes the hardware is perfect is always a worry. But I see the driver already does that, so we're no worse off..

Do you want a finite loop with udelay in it? I located 4 places were this could be used. If so I can generate a new patch for that.

Even if Andrew doesn't, I'd sure like it. (the finite bit at least) :)

Related, who is the maintainer of this driver? Tony? I'd like to have someone who checks patches before I queue them up.

Rgds

Signature · 9 lines
     -- Pierre Ossman

  Linux kernel, MMC maintainer        http://www.kernel.org
  rdesktop, core developer          http://www.rdesktop.org

  WARNING: This correspondence is being monitored by the
  Swedish government. Make sure your server uses encryption
  for SMTP traffic and consider using PGP for end-to-end
  encryption.
#29 lore raw

PATCH 1/1 OMAP: MMC: replace infinite loops with timeouts (was Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend)

Hi,

Quoted 9 lines
Quoted 7 lines
Quoted 4 lines · Andrew Morton
Quoted 3 lines

An infinite loop which assumes the hardware is perfect is always a worry. But I see the driver already does that, so we're no worse off..

Do you want a finite loop with udelay in it? I located 4 places were this could be used. If so I can generate a new patch for that.

Even if Andrew doesn't, I'd sure like it. (the finite bit at least) :)

Ok here is a patch that replaces the infinite loops with a timeout version. This patch applies on top of the previous one I sent ('[PATCH] OMAP: MMC:
recover from transfer failures - Resend'). Is that OK?

Quoted 5 lines

Related, who is the maintainer of this driver? Tony? I'd like to have someone who checks patches before I queue them up.

Rgds

From 5ee867d09efe22a903ac7373a05e9e047bad6544 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Fri, 6 Feb 2009 16:42:51 +0100
Subject: [PATCH] OMAP: MMC: replace infinite loops with timeouts

Replace the 'while() ;' with a timeout

---
 drivers/mmc/host/omap_hsmmc.c |   56 
+++++++++++++++++++++++++++++++++--------
 1 files changed, 45 insertions(+), 11 deletions(-)
drivers/mmc/host/omap_hsmmc.c +3 -0
index 1ac6918..7ddc77e 100644
@@ -102,6 +102,8 @@
 #define OMAP_MMC_DATADIR_READ  1
 #define OMAP_MMC_DATADIR_WRITE 2
 #define MMC_TIMEOUT_MS         20
+#define MMC_TIMEOUT_WAIT       100     /* Active wait duration, in usec */
+#define MMC_TIMEOUT_WAIT_LOOPS ((MMC_TIMEOUT_MS * 1000) / MMC_TIMEOUT_WAIT)
 #define OMAP_MMC_MASTER_CLOCK  96000000
 #define DRIVER_NAME            "mmci-omap-hs"
 
@@ -384,6 +386,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
        struct mmc_omap_host *host = dev_id;
        struct mmc_data *data;
        int end_cmd = 0, end_trans = 0, status;
+       unsigned long timeout_counter;
 
        if (host->cmd == NULL && host->data == NULL) {
                OMAP_HSMMC_WRITE(host->base, STAT,
@@ -406,9 +409,17 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                        OMAP_HSMMC_WRITE(host->base, SYSCTL,
                                                OMAP_HSMMC_READ(host->base,
                                                                SYSCTL) | 

SRC);
- while (OMAP_HSMMC_READ(host->base,
- SYSCTL) & SRC)
- ;
+ timeout_counter = 0;
+ while ((OMAP_HSMMC_READ(host->base,
+ SYSCTL) & SRC)
+ && (timeout_counter++ <
+
MMC_TIMEOUT_WAIT_LOOPS))
+
udelay(MMC_TIMEOUT_WAIT);
+
+ if (OMAP_HSMMC_READ(host->base,
+ SYSCTL) & SRC)
+ dev_err(mmc_dev(host->mmc),
+ "Timeout waiting on
SRC\n");

                                        host->cmd->error = -ETIMEDOUT;
                                } else {
@@ -421,9 +432,17 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                OMAP_HSMMC_WRITE(host->base, SYSCTL,
                                        OMAP_HSMMC_READ(host->base,
                                                        SYSCTL) | SRD);

- while (OMAP_HSMMC_READ(host->base,
- SYSCTL) & SRD)
- ;
+ timeout_counter = 0;
+ while ((OMAP_HSMMC_READ(host->base,
+ SYSCTL) & SRD)
+ && (timeout_counter++ <
+
MMC_TIMEOUT_WAIT_LOOPS))
+ udelay(MMC_TIMEOUT_WAIT);
+
+ if (OMAP_HSMMC_READ(host->base,
+ SYSCTL) & SRD)
+ dev_err(mmc_dev(host->mmc),

+                                               "Timeout waiting on SRD\n");
                        }
                }
                if ((status & DATA_TIMEOUT) ||
@@ -436,9 +455,17 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                OMAP_HSMMC_WRITE(host->base, SYSCTL,
                                        OMAP_HSMMC_READ(host->base,
                                                        SYSCTL) | SRD);

- while (OMAP_HSMMC_READ(host->base,
- SYSCTL) & SRD)
- ;
+ timeout_counter = 0;
+ while ((OMAP_HSMMC_READ(host->base,
+ SYSCTL) & SRD)
+ && (timeout_counter++ <
+
MMC_TIMEOUT_WAIT_LOOPS))
+ udelay(MMC_TIMEOUT_WAIT);
+
+ if (OMAP_HSMMC_READ(host->base,
+ SYSCTL) & SRD)
+ dev_err(mmc_dev(host->mmc),

+                                               "Timeout waiting on SRD\n");
                                end_trans = 1;
                        }
                }

@@ -524,6 +551,7 @@ static void mmc_omap_detect(struct work_struct *work)
{
struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
mmc_carddetect_work);
+ unsigned long timeout;

        sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
        if (host->carddetect) {
@@ -531,8 +559,14 @@ static void mmc_omap_detect(struct work_struct *work)
        } else {
                OMAP_HSMMC_WRITE(host->base, SYSCTL,
                        OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
-               while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
-                       ;
+               /* Wait till the SRD bit is reset */
+               timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
+               while ((OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)

+ && time_before(jiffies, timeout))
+ msleep(1);
+
+ if (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
+ dev_err(mmc_dev(host->mmc), "Timeout waiting on
SRD\n");

                mmc_detect_change(host->mmc, (HZ * 50) / 1000);
        }

--
1.6.0.1.42.gf8c9c

From 5ee867d09efe22a903ac7373a05e9e047bad6544 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Fri, 6 Feb 2009 16:42:51 +0100
Subject: [PATCH] OMAP: MMC: replace infinite loops with timeouts

Replace the 'while() ;' with a timeout

---
 drivers/mmc/host/omap_hsmmc.c |   56 +++++++++++++++++++++++++++++++++--------
 1 files changed, 45 insertions(+), 11 deletions(-)
drivers/mmc/host/omap_hsmmc.c +45 -11

98 lines not on this page · raw message

Signature · 1 line
1.6.0.1.42.gf8c9c
#30 lore raw

Re: [PATCH] OMAP: MMC: replace infinite loops with timeouts (was Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend)

Quoted 6 lines · Jean Pihet

Hi,

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines · Andrew Morton
Quoted 3 lines

An infinite loop which assumes the hardware is perfect is always a worry. But I see the driver already does that, so we're no worse off..

Quoted 7 lines
Quoted 3 lines
Quoted 2 lines

Do you want a finite loop with udelay in it? I located 4 places were this could be used. If so I can generate a new patch for that.

Even if Andrew doesn't, I'd sure like it. (the finite bit at least) :)

Ok here is a patch that replaces the infinite loops with a timeout version. This patch applies on top of the previous one I sent ('[PATCH] OMAP: MMC:
recover from transfer failures - Resend'). Is that OK?

What about making use of a function like this:

static void reset_host_controller(struct mmc_omap_host *host, unsigned bit)

{
	unsigned long i, limit = loops_per_jiffy;

	OMAP_HSMMC_WRITE(host->base, SYSCTL,
			 OMAP_HSMMC_READ(host->base, SYSCTL) | bit);
	for (i = 0; i < limit; i++) {
		if (!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit))
			return;
		cpu_relax();
	}
	dev_err(mmc_dev(host->mmc), "%s: timeout waiting on software reset\n",
		mmc_hostname(host->mmc));
}

And then just put:

	reset_host_controller(host, SRD);

and

	reset_host_controller(host, SRC);

in the right places.

Quoted 138 lines
Quoted 7 lines

Related, who is the maintainer of this driver? Tony? I'd like to have someone who checks patches before I queue them up.

Rgds

From 5ee867d09efe22a903ac7373a05e9e047bad6544 Mon Sep 17 00:00:00 2001

From: Jean Pihet <[email protected]>
Date: Fri, 6 Feb 2009 16:42:51 +0100
Subject: [PATCH] OMAP: MMC: replace infinite loops with timeouts

Replace the 'while() ;' with a timeout

---
 drivers/mmc/host/omap_hsmmc.c |   56
+++++++++++++++++++++++++++++++++--------
 1 files changed, 45 insertions(+), 11 deletions(-)
drivers/mmc/host/omap_hsmmc.c +14 -3
index 1ac6918..7ddc77e 100644
@@ -102,6 +102,8 @@
 #define OMAP_MMC_DATADIR_READ  1
 #define OMAP_MMC_DATADIR_WRITE 2
 #define MMC_TIMEOUT_MS         20
+#define MMC_TIMEOUT_WAIT       100     /* Active wait duration, in usec */
+#define MMC_TIMEOUT_WAIT_LOOPS ((MMC_TIMEOUT_MS * 1000) / MMC_TIMEOUT_WAIT)
 #define OMAP_MMC_MASTER_CLOCK  96000000
 #define DRIVER_NAME            "mmci-omap-hs"
 
@@ -384,6 +386,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
        struct mmc_omap_host *host = dev_id;
        struct mmc_data *data;
        int end_cmd = 0, end_trans = 0, status;
+       unsigned long timeout_counter;
 
        if (host->cmd == NULL && host->data == NULL) {
                OMAP_HSMMC_WRITE(host->base, STAT,
@@ -406,9 +409,17 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                        OMAP_HSMMC_WRITE(host->base, SYSCTL,
                                                OMAP_HSMMC_READ(host->base,
                                                                SYSCTL) |
 SRC);
-                                       while (OMAP_HSMMC_READ(host->base,
-                                                       SYSCTL) & SRC)
-                                               ;
+                                       timeout_counter = 0;
+                                       while ((OMAP_HSMMC_READ(host->base,
+                                                               SYSCTL) & SRC)
+                                               && (timeout_counter++ <
+
 MMC_TIMEOUT_WAIT_LOOPS))
+
 udelay(MMC_TIMEOUT_WAIT);
+
+                                       if (OMAP_HSMMC_READ(host->base,
+                                                               SYSCTL) & SRC)
+                                               dev_err(mmc_dev(host->mmc),
+                                                       "Timeout waiting on

SRC\n");

                                        host->cmd->error = -ETIMEDOUT;
                                } else {
drivers/mmc/host/omap_hsmmc.c +11 -3
@@ -421,9 +432,17 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                OMAP_HSMMC_WRITE(host->base, SYSCTL,
                                        OMAP_HSMMC_READ(host->base,
                                                        SYSCTL) | SRD);
-                               while (OMAP_HSMMC_READ(host->base,
-                                               SYSCTL) & SRD)
-                                       ;
+                               timeout_counter = 0;
+                               while ((OMAP_HSMMC_READ(host->base,
+                                                       SYSCTL) & SRD)
+                                       && (timeout_counter++ <
+
 MMC_TIMEOUT_WAIT_LOOPS))
+                                       udelay(MMC_TIMEOUT_WAIT);
+
+                               if (OMAP_HSMMC_READ(host->base,
+                                                       SYSCTL) & SRD)
+                                       dev_err(mmc_dev(host->mmc),
+                                               "Timeout waiting on SRD\n");
                        }
                }
                if ((status & DATA_TIMEOUT) ||
drivers/mmc/host/omap_hsmmc.c +11 -3
@@ -436,9 +455,17 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                OMAP_HSMMC_WRITE(host->base, SYSCTL,
                                        OMAP_HSMMC_READ(host->base,
                                                        SYSCTL) | SRD);
-                               while (OMAP_HSMMC_READ(host->base,
-                                               SYSCTL) & SRD)
-                                       ;
+                               timeout_counter = 0;
+                               while ((OMAP_HSMMC_READ(host->base,
+                                                       SYSCTL) & SRD)
+                                       && (timeout_counter++ <
+
 MMC_TIMEOUT_WAIT_LOOPS))
+                                       udelay(MMC_TIMEOUT_WAIT);
+
+                               if (OMAP_HSMMC_READ(host->base,
+                                                       SYSCTL) & SRD)
+                                       dev_err(mmc_dev(host->mmc),
+                                               "Timeout waiting on SRD\n");
                                end_trans = 1;
                        }
                }
drivers/mmc/host/omap_hsmmc.c +9 -2
@@ -524,6 +551,7 @@ static void mmc_omap_detect(struct work_struct *work)
 {
        struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
                                                mmc_carddetect_work);
+       unsigned long timeout;
 
        sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
        if (host->carddetect) {
@@ -531,8 +559,14 @@ static void mmc_omap_detect(struct work_struct *work)
        } else {
                OMAP_HSMMC_WRITE(host->base, SYSCTL,
                        OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
-               while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
-                       ;
+               /* Wait till the SRD bit is reset */
+               timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
+               while ((OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
+                       && time_before(jiffies, timeout))
+                       msleep(1);
+
+               if (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
+                       dev_err(mmc_dev(host->mmc), "Timeout waiting on
 SRD\n");
 
                mmc_detect_change(host->mmc, (HZ * 50) / 1000);
        }

--
1.6.0.1.42.gf8c9c

#31 lore raw

Re: [PATCH] OMAP: MMC: replace infinite loops with timeouts (was Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend)

Hi,

Here is the new version of the patch, which now uses cpu_relax in an inline function. The new function can be used from an irq handler as well.

Regards,
Jean

From 9d1993dcf4d217837437a1cd9f6e9c1b81533549 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Fri, 6 Feb 2009 16:42:51 +0100
Subject: [PATCH] OMAP: MMC: Change while(); loops with finite version

Replace the infinite 'while() ;' loops
with a finite loop version.

---
 drivers/mmc/host/omap_hsmmc.c |   54 ++++++++++++++++++++++------------------
 1 files changed, 30 insertions(+), 24 deletions(-)
drivers/mmc/host/omap_hsmmc.c +0 -0
index 1ac6918..aabf28d 100644
@@ -375,6 +375,32 @@ static void mmc_omap_report_irq(struct mmc_omap_host 

*host, u32 status)
}
#endif /* CONFIG_MMC_DEBUG */

+/*
+ * MMC controller internal state machines reset
+ *
+ * Used to reset command or data internal state machines, using respectively
+ * SRC or SRD bit of SYSCTL register
+ * Can be called from interrupt context
+ */
+static inline void mmc_omap_reset_controller_fsm(struct mmc_omap_host *host,
+ unsigned long bit)
+{
+ unsigned long i = 0;
+ unsigned long limit = (loops_per_jiffy *
+ msecs_to_jiffies(MMC_TIMEOUT_MS));
+
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) | bit);
+
+ while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) &&
+ (i++ < limit))
+ cpu_relax();
+
+ if (OMAP_HSMMC_READ(host->base, SYSCTL) & bit)
+ dev_err(mmc_dev(host->mmc),
+ "Timeout waiting on controller reset in %s\n",
+ __func__);
+}

/*
* MMC controller IRQ handler
@@ -403,13 +429,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)

                        (status & CMD_CRC)) {
                        if (host->cmd) {
                                if (status & CMD_TIMEOUT) {

- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base,
- SYSCTL) |
SRC);
- while (OMAP_HSMMC_READ(host->base,
- SYSCTL) & SRC)
- ;
-
+ mmc_omap_reset_controller_fsm(host,

SRC);
                                        host->cmd->error = -ETIMEDOUT;
                                } else {
                                        host->cmd->error = -EILSEQ;
@@ -418,12 +438,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                        }
                        if (host->data) {
                                mmc_dma_cleanup(host);

- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base,
- SYSCTL) | SRD);
- while (OMAP_HSMMC_READ(host->base,
- SYSCTL) & SRD)
- ;

+                               mmc_omap_reset_controller_fsm(host, SRD);
                        }
                }
                if ((status & DATA_TIMEOUT) ||
@@ -433,12 +448,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                        mmc_dma_cleanup(host);
                                else
                                        host->data->error = -EILSEQ;

- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base,
- SYSCTL) | SRD);
- while (OMAP_HSMMC_READ(host->base,
- SYSCTL) & SRD)
- ;

+                               mmc_omap_reset_controller_fsm(host, SRD);
                                end_trans = 1;
                        }
                }
@@ -529,11 +539,7 @@ static void mmc_omap_detect(struct work_struct *work)
        if (host->carddetect) {
                mmc_detect_change(host->mmc, (HZ * 200) / 1000);
        } else {

- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
- while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
- ;
-

+               mmc_omap_reset_controller_fsm(host, SRD);
                mmc_detect_change(host->mmc, (HZ * 50) / 1000);
        }

}
--
1.6.0.1.42.gf8c9c

Quoted 36 lines · On Monday 09 February 2009 16:58:14 Adrian Hunter wrote:
Quoted 7 lines · Jean Pihet

Hi,

Quoted 5 lines
Quoted 5 lines
Quoted 4 lines · Andrew Morton
Quoted 3 lines

An infinite loop which assumes the hardware is perfect is always a worry. But I see the driver already does that, so we're no worse off..

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

Do you want a finite loop with udelay in it? I located 4 places were this could be used. If so I can generate a new patch for that.

Even if Andrew doesn't, I'd sure like it. (the finite bit at least) :)

Ok here is a patch that replaces the infinite loops with a timeout version. This patch applies on top of the previous one I sent ('[PATCH]
OMAP: MMC: recover from transfer failures - Resend'). Is that OK?

What about making use of a function like this:

static void reset_host_controller(struct mmc_omap_host *host, unsigned bit)

{
	unsigned long i, limit = loops_per_jiffy;

	OMAP_HSMMC_WRITE(host->base, SYSCTL,
			 OMAP_HSMMC_READ(host->base, SYSCTL) | bit);
	for (i = 0; i < limit; i++) {
		if (!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit))
			return;
		cpu_relax();
	}
	dev_err(mmc_dev(host->mmc), "%s: timeout waiting on software reset\n",
		mmc_hostname(host->mmc));
}

And then just put:

Quoted 7 lines
	reset_host_controller(host, SRD);

and

	reset_host_controller(host, SRC);

in the right places.

From 9d1993dcf4d217837437a1cd9f6e9c1b81533549 Mon Sep 17 00:00:00 2001
From: Jean Pihet <[email protected]>
Date: Fri, 6 Feb 2009 16:42:51 +0100
Subject: [PATCH] OMAP: MMC: Change while(); loops with finite version

Replace the infinite 'while() ;' loops
with a finite loop version.

---
 drivers/mmc/host/omap_hsmmc.c |   54 ++++++++++++++++++++++------------------
 1 files changed, 30 insertions(+), 24 deletions(-)
drivers/mmc/host/omap_hsmmc.c +30 -24

84 lines not on this page · raw message

Signature · 1 line
1.6.0.1.42.gf8c9c
#32 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend

In reply to Pierre Ossman
Quoted 2 lines · Pierre Ossman

Related, who is the maintainer of this driver? Tony? I'd like to have someone who checks patches before I queue them up.

I can be. Tony asked me a month ago to set up git tree for OMAP HSMMC and put the workaround for the HSMMC multi-block DMA read corruption there, but hate to admit things have been hanging on todo list.

There are some other fixes waiting. Omap_mmc_set_ios() doesn't handle power off case correctly and resume from suspend can hang if the SDBP bit fails to set.

Cheers
Jarkko

author maintainer
#33 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend

Quoted 8 lines · Jarkko Lavinen
Quoted 2 lines · Pierre Ossman

Related, who is the maintainer of this driver? Tony? I'd like to have someone who checks patches before I queue them up.

I can be. Tony asked me a month ago to set up git tree for OMAP HSMMC and put the workaround for the HSMMC multi-block DMA read corruption there, but hate to admit things have been hanging on todo list.

Yeah it would be great if Jarkkko can queue up all the omap MMC patches from now on.

Quoted 3 lines

There are some other fixes waiting. Omap_mmc_set_ios() doesn't handle power off case correctly and resume from suspend can hang if the SDBP bit fails to set.

And then all your PM patches for the next merge window..

Tony

maintainer
#34 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend

In reply to Jean Pihet
Quoted 2 lines · Jean Pihet

Do you want a finite loop with udelay in it? I located 4 places were this could be used. If so I can generate a new patch for that.

Just as an aside, from the standpoint of minimizing CPU usage, there seems little point in using udelay() here, since it is implemented as a CPU busy-wait.

- Paul

#35 lore raw

Re: [PATCH] OMAP: MMC: recover from transfer failures - Resend

In reply to Paul Walmsley
Quoted 11 lines · Paul Walmsley
Quoted 7 lines
Quoted 4 lines

+   while (OMAP_HSMMC_READ(host->base,
+                   SYSCTL) & SRD)
+           ;

Is a __raw_readl() sufficient to prevent the cpu from burning up here, or should we add cpu_relax()?

The __raw_readl() should be sufficient.  The MMC controller is located on the L4 CORE interconnect, so the round trip latency for the read from MMC is at least 90 ns, while the CPU cycle time is only about 1 to 2 ns.

It's still good policy to have a cpu_relax() in such loops. Not that it'll do much on most ARMs, but empty statements are in general worth avoiding.

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

author maintainer
#36 lore raw

git pull request for omap mmc init changes (Re: [PATCH 0/5] Omap MMC init updates and new controller for 2.6.29 merge window)

In reply to Tony Lindgren
Quoted 6 lines · Tony Lindgren

Hi Pierre & Russell,

This series contains a better platform init for omap MMC as discussed earlier on the linux-omap mailing list. The last patch in the series adds support for a newer omap MMC controller available on 2430 and 34xx omaps.

Quoted 8 lines

The first four patches should get merged via Russell. The last one adding the new controller depends on comments from Pierre, so I can separate that out if desired.

The third patch in the series depends on the "Omap3 updates for 2.6.29 merge window" series for the changes to Pandora board support.

Comments welcome as always!

Russell, here's a pull request for the first four patches in this series for the mmc init changes. This depends on the omap3-upstream pull request posted earlier today.

I'm not including the actual driver in this series, that should go via Pierre. Or at least we should have an ack from Pierre first.

Regards,

Tony

The following changes since commit 2619bc327417f549f1c89d5ef9b4a4aa768f41a2:
Arun KS (1):
ARM: OMAP3: Pin multiplexing updates for 24xx and 34xx

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git hsmmc-init

Kevin Hilman (1):
omap mmc: force MMC module reset on boot

Tony Lindgren (3):
omap mmc: Remove broken MMC init code
omap mmc: Add better MMC low-level init
omap mmc: Add low-level initialization for hsmmc controller

 arch/arm/mach-omap1/board-h2-mmc.c         |   89 +++----
 arch/arm/mach-omap1/board-h2.c             |   25 +-
 arch/arm/mach-omap1/board-h3-mmc.c         |  100 ++-----
 arch/arm/mach-omap1/board-h3.c             |   10 -
 arch/arm/mach-omap1/board-innovator.c      |   50 +++-
 arch/arm/mach-omap1/board-nokia770.c       |   74 ++++-
 arch/arm/mach-omap1/board-palmte.c         |    1 -
 arch/arm/mach-omap1/board-palmz71.c        |   11 -
 arch/arm/mach-omap1/board-sx1-mmc.c        |   80 +-----
 arch/arm/mach-omap1/board-sx1.c            |   10 -
 arch/arm/mach-omap1/board-voiceblue.c      |   10 +-
 arch/arm/mach-omap1/clock.h                |    3 +-
 arch/arm/mach-omap1/devices.c              |   90 ++++++
 arch/arm/mach-omap2/Makefile               |   15 +-
 arch/arm/mach-omap2/board-2430sdp.c        |   48 ++++
 arch/arm/mach-omap2/board-apollon.c        |   11 -
 arch/arm/mach-omap2/board-generic.c        |   11 -
 arch/arm/mach-omap2/board-h4.c             |   11 -
 arch/arm/mach-omap2/board-ldp.c            |   40 +++-
 arch/arm/mach-omap2/board-omap3beagle.c    |   90 ++++++
 arch/arm/mach-omap2/board-omap3pandora.c   |   32 +++
 arch/arm/mach-omap2/board-overo.c          |   43 +++
 arch/arm/mach-omap2/clock24xx.h            |    9 +-
 arch/arm/mach-omap2/clock34xx.h            |   10 +-
 arch/arm/mach-omap2/devices.c              |  169 ++++++++++++
 arch/arm/mach-omap2/mmc-twl4030.c          |  408 ++++++++++++++++++++++++++++
 arch/arm/mach-omap2/mmc-twl4030.h          |   29 ++
 arch/arm/plat-omap/devices.c               |  225 +++-------------
 arch/arm/plat-omap/include/mach/board-h2.h |    6 +-
 arch/arm/plat-omap/include/mach/board.h    |   22 --
 arch/arm/plat-omap/include/mach/control.h  |   17 ++
 arch/arm/plat-omap/include/mach/mmc.h      |   74 +++++-
 drivers/mmc/host/omap.c                    |    7 +-
 33 files changed, 1282 insertions(+), 548 deletions(-)
 create mode 100644 arch/arm/mach-omap2/mmc-twl4030.c
 create mode 100644 arch/arm/mach-omap2/mmc-twl4030.h