linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/22] omap_hsmmc patches
@ 2011-05-05 11:51 Adrian Hunter
  2011-05-05 11:51 ` [PATCH 01/22] OMAP: sDMA: descriptor autoloading feature Adrian Hunter
                   ` (21 more replies)
  0 siblings, 22 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter

Hi

Here are some patches for omap_hsmmc.

Adrian Hunter (10):
      OMAP: DMA: add omap_dma_has_sglist()
      OMAP: DMA: Ensure the sglist registers are cleared
      mmc: omap_hsmmc: fix dma sglist use
      mmc: omap_hsmmc: limit scatterlist size for sDMA autoloading
      mmc: omap_hsmmc: correct debug report error status mnemonics
      OMAP: board-rm680: set MMC nomux flag
      mmc: omap_hsmmc: ensure pbias configuration is always done
      mmc: omap_hsmmc: fix oops in omap_hsmmc_dma_cb
      OMAP: hsmmc: add platform data for eMMC hardware reset gpio
      mmc: omap_hsmmc: add a hardware reset before initialization

Andy Shevchenko (8):
      mmc: omap_hsmmc: move hardcoded frequency constants to definition block
      mmc: omap_hsmmc: reduce a bit the error handlers in probe()
      mmc: omap_hsmmc: split duplicate code to calc_divisor() function
      mmc: omap_hsmmc: introduce start_clock and re-use stop_clock
      mmc: omap_hsmmc: fix few bugs when set the clock divisor
      mmc: omap_hsmmc: split same pieces of code to separate functions
      OMAP: hsmmc: implement clock switcher
      mmc: omap_hsmmc: adjust host controller clock in regard to current OPP

Jarkko Lavinen (1):
      OMAP: hsmmc: Do not mux the slot if non default muxing is already done

Sudhir Bera (1):
      mmc: omap_hsmmc: fix missing mmc_release_host() in no_off case

Venkatraman S (2):
      OMAP: sDMA: descriptor autoloading feature
      mmc: omap hsmmc: adaptation of sdma descriptor

 arch/arm/mach-omap2/board-rm680.c     |    1 +
 arch/arm/mach-omap2/hsmmc.c           |  188 ++++++++++++-
 arch/arm/mach-omap2/hsmmc.h           |    2 +
 arch/arm/plat-omap/dma.c              |  285 ++++++++++++++++++
 arch/arm/plat-omap/include/plat/dma.h |  176 +++++++++++
 arch/arm/plat-omap/include/plat/mmc.h |    9 +
 drivers/mmc/host/omap_hsmmc.c         |  514 ++++++++++++++++++++++----------
 7 files changed, 1012 insertions(+), 163 deletions(-)
 
Regards
Adrian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 01/22] OMAP: sDMA: descriptor autoloading feature
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-06  6:22   ` Tony Lindgren
  2011-05-05 11:51 ` [PATCH 02/22] OMAP: DMA: add omap_dma_has_sglist() Adrian Hunter
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Venkatraman S,
	Shilimkar Santosh, Tony Lindgren, Adrian Hunter

From: Venkatraman S <svenkatr@ti.com>

Add sDMA driver support for descriptor autoloading feature.
 Descriptor autoloading is OMAP sDMA v5 hardware capability that can be exploited for scatter gather
 scenarios, currently available in OMAP3630 and OMAP4430.

  The feature works as described below.
  1) A sDMA channel is programmed to be in 'linked list' mode.
  2) The client (sDMA user) provides a list of descriptors in a linked list format.
  3) Each of the 'descriptor' (element in the linked list) contains an updated set of DMA
  configuration register values.
  4) Client starts DMA transfer.
  5) sDMA controller loads the first element to its register configuration memory and executes the
  transfer.
  6) After completion, loads the next element (in linked list) to configuration memory and executes
  the transfer, without MCU intervention.
  7) Interrupt is generated after all transfers are completed; this can be configured to be done
  differently.

  Configurations and additional features
  1) Fast mode & non-fast mode
        Fast mode/non-fast decides on how the first transfer begins. In non-fast mode, the first
	element in the linked list is loaded only after completing the transfer according to the
	configurations already in the sDMA channel registers. In fast mode, the loading of the first
	element precedes the transfer.

  2) Pause / resume of transfers
	A transfer can be paused after a descriptor set has been loaded, provided the 'pause
	bit' is set in the linked list element.
	An ongoing transfer cannot be paused. If the 'pause bit' is set, transfer is not
	started after loading the register set from memory.
	Such a transfer can be resumed later.

  3) Descriptor types
	3 possible configurations of descriptors (initialized as linked list elements)
	are possible. Type 1 provides the maximum flexibility, which contains most
	register definitions of a DMA logical channel. Fewer options are present in type
	2. Type 3 can just modify source/destinations address of transfers. In all
	transfers, unmodified registers settings are maintained for the next transfer.

	Patch provides options / API for
	    1) Setting up a descriptor loading for DMA channel for sg type transfers
	    2) configuration with linked list elements
	    3) Starting / pause and resume of the said transfers, query state
	    4) Clearing the sglist mode

Signed-off-by: Venkatraman S <svenkatr@ti.com>
CC: Madhusudhan C <madhu.cr@ti.com>
CC: Shilimkar Santosh <santosh.shilimkar@ti.com>
CC: Tony Lindgren <tony@atomide.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 arch/arm/plat-omap/dma.c              |  279 +++++++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/dma.h |  173 ++++++++++++++++++++
 2 files changed, 452 insertions(+), 0 deletions(-)

diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index c22217c..7f64366 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -52,16 +52,37 @@ enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
 enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
 #endif
 
+/* CDP Register bitmaps */
+#define DMA_LIST_CDP_DST_VALID	BIT(0)
+#define DMA_LIST_CDP_SRC_VALID	BIT(2)
+#define DMA_LIST_CDP_TYPE1	BIT(4)
+#define DMA_LIST_CDP_TYPE2	BIT(5)
+#define DMA_LIST_CDP_TYPE3	(BIT(4) | BIT(5))
+#define DMA_LIST_CDP_PAUSEMODE	BIT(7)
+#define DMA_LIST_CDP_LISTMODE	BIT(8)
+#define DMA_LIST_CDP_FASTMODE	BIT(10)
+/* CAPS register bitmaps */
+#define DMA_CAPS_SGLIST_SUPPORT	BIT(20)
+
+#define DMA_LIST_DESC_PAUSE	BIT(0)
+#define DMA_LIST_DESC_SRC_VALID	BIT(24)
+#define DMA_LIST_DESC_DST_VALID	BIT(26)
+#define DMA_LIST_DESC_BLK_END	BIT(28)
+
 #define OMAP_DMA_ACTIVE			0x01
 #define OMAP2_DMA_CSR_CLEAR_MASK	0xffffffff
 
 #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
+#define OMAP_DMA_INVALID_FRAME_COUNT	0xffff
+#define OMAP_DMA_INVALID_ELEM_COUNT	0xffffff
+#define OMAP_DMA_INVALID_DESCRIPTOR_POINTER	0xfffffffc
 
 static struct omap_system_dma_plat_info *p;
 static struct omap_dma_dev_attr *d;
 
 static int enable_1510_mode;
 static u32 errata;
+static int dma_caps0_status;
 
 static struct omap_dma_global_context_registers {
 	u32 dma_irqenable_l0;
@@ -166,6 +187,76 @@ static inline void set_gdma_dev(int req, int dev)
 #define set_gdma_dev(req, dev)	do {} while (0)
 #endif
 
+static inline void omap_dma_list_set_ntype(struct omap_dma_sglist_node *node,
+					   int value)
+{
+	node->num_of_elem |= ((value) << 29);
+}
+
+static void omap_set_dma_sglist_pausebit(
+		struct omap_dma_list_config_params *lcfg, int nelem, int set)
+{
+	struct omap_dma_sglist_node *sgn = lcfg->sghead;
+
+	if (nelem > 0 && nelem < lcfg->num_elem) {
+		lcfg->pausenode = nelem;
+		sgn += nelem;
+
+		if (set)
+			sgn->next_desc_add_ptr |= DMA_LIST_DESC_PAUSE;
+		else
+			sgn->next_desc_add_ptr &= ~(DMA_LIST_DESC_PAUSE);
+	}
+}
+
+static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead,
+		dma_addr_t phyaddr, int nelem)
+{
+	struct omap_dma_sglist_node *sgcurr, *sgprev;
+	dma_addr_t elem_paddr = phyaddr;
+
+	for (sgprev = sghead;
+		sgprev < sghead + nelem;
+		sgprev++) {
+
+		sgcurr = sgprev + 1;
+		sgprev->next = sgcurr;
+		elem_paddr += (int)sizeof(*sgcurr);
+		sgprev->next_desc_add_ptr = elem_paddr;
+
+		switch (sgcurr->desc_type) {
+		case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
+			omap_dma_list_set_ntype(sgprev, 1);
+			break;
+
+		case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
+		/* intentional no break */
+		case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
+			omap_dma_list_set_ntype(sgprev, 2);
+			break;
+
+		case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
+			/* intentional no break */
+		case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
+			omap_dma_list_set_ntype(sgprev, 3);
+			break;
+
+		default:
+			return -EINVAL;
+
+		}
+		if (sgcurr->flags & OMAP_DMA_LIST_SRC_VALID)
+			sgprev->num_of_elem |= DMA_LIST_DESC_SRC_VALID;
+		if (sgcurr->flags & OMAP_DMA_LIST_DST_VALID)
+			sgprev->num_of_elem |= DMA_LIST_DESC_DST_VALID;
+		if (sgcurr->flags & OMAP_DMA_LIST_NOTIFY_BLOCK_END)
+			sgprev->num_of_elem |= DMA_LIST_DESC_BLK_END;
+	}
+	sgprev--;
+	sgprev->next_desc_add_ptr = OMAP_DMA_INVALID_DESCRIPTOR_POINTER;
+	return 0;
+}
+
 void omap_set_dma_priority(int lch, int dst_port, int priority)
 {
 	unsigned long reg;
@@ -778,6 +869,7 @@ void omap_free_dma(int lch)
 		/* Make sure the DMA transfer is stopped. */
 		p->dma_write(0, CCR, lch);
 		omap_clear_dma(lch);
+		omap_clear_dma_sglist_mode(lch);
 	}
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
@@ -1770,6 +1862,192 @@ int omap_get_dma_chain_src_pos(int chain_id)
 EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
 #endif	/* ifndef CONFIG_ARCH_OMAP1 */
 
+int omap_set_dma_sglist_mode(int lch, struct omap_dma_sglist_node *sgparams,
+	dma_addr_t padd, int nelem, struct omap_dma_channel_params *chparams)
+{
+	struct omap_dma_list_config_params *lcfg;
+	int l = DMA_LIST_CDP_LISTMODE; /* Enable Linked list mode in CDP */
+
+	if ((dma_caps0_status & DMA_CAPS_SGLIST_SUPPORT) == 0) {
+		printk(KERN_ERR "omap DMA: sglist feature not supported\n");
+		return -EPERM;
+	}
+	if (dma_chan[lch].flags & OMAP_DMA_ACTIVE) {
+		printk(KERN_ERR "omap DMA: configuring active DMA channel\n");
+		return -EPERM;
+	}
+
+	if (padd == 0) {
+		printk(KERN_ERR "omap DMA: sglist invalid dma_addr\n");
+		return -EINVAL;
+	}
+	lcfg = &dma_chan[lch].list_config;
+
+	lcfg->sghead = sgparams;
+	lcfg->num_elem = nelem;
+	lcfg->sgheadphy = padd;
+	lcfg->pausenode = -1;
+
+
+	if (NULL == chparams)
+		l |= DMA_LIST_CDP_FASTMODE;
+	else
+		omap_set_dma_params(lch, chparams);
+
+	p->dma_write(l, CDP, lch);
+	p->dma_write(0, CCDN, lch); /* Reset List index numbering */
+	/* Initialize frame and element counters to invalid values */
+	p->dma_write(OMAP_DMA_INVALID_FRAME_COUNT, CCFN, lch);
+	p->dma_write(OMAP_DMA_INVALID_ELEM_COUNT, CCEN, lch);
+
+	return dma_sglist_set_phy_params(sgparams, lcfg->sgheadphy, nelem);
+
+}
+EXPORT_SYMBOL(omap_set_dma_sglist_mode);
+
+void omap_clear_dma_sglist_mode(int lch)
+{
+	/* Clear entire CDP which is related to sglist handling */
+	p->dma_write(0, CDP, lch);
+	p->dma_write(0, CCDN, lch);
+	/**
+	 * Put back the original enabled irqs, which
+	 * could have been overwritten by type 1 or type 2
+	 * descriptors
+	 */
+	p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
+	return;
+}
+EXPORT_SYMBOL(omap_clear_dma_sglist_mode);
+
+int omap_start_dma_sglist_transfers(int lch, int pauseafter)
+{
+	struct omap_dma_list_config_params *lcfg;
+	struct omap_dma_sglist_node *sgn;
+	unsigned int l, type_id;
+
+	lcfg = &dma_chan[lch].list_config;
+	sgn = lcfg->sghead;
+
+	lcfg->pausenode = 0;
+	omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1);
+
+	/* Program the head descriptor's properties into CDP */
+	switch (lcfg->sghead->desc_type) {
+	case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
+		type_id = DMA_LIST_CDP_TYPE1;
+		break;
+	case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
+	case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
+		type_id = DMA_LIST_CDP_TYPE2;
+		break;
+	case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
+	case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
+		type_id = DMA_LIST_CDP_TYPE3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	l = p->dma_read(CDP, lch);
+	l |= type_id;
+	if (lcfg->sghead->flags & OMAP_DMA_LIST_SRC_VALID)
+		l |= DMA_LIST_CDP_SRC_VALID;
+	if (lcfg->sghead->flags & OMAP_DMA_LIST_DST_VALID)
+		l |= DMA_LIST_CDP_DST_VALID;
+
+	p->dma_write(l, CDP, lch);
+	p->dma_write((lcfg->sgheadphy), CNDP, lch);
+	/**
+	 * Barrier needed as writes to the
+	 * descriptor memory needs to be flushed
+	 * before it's used by DMA controller
+	 */
+	wmb();
+	omap_start_dma(lch);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_start_dma_sglist_transfers);
+
+int omap_resume_dma_sglist_transfers(int lch, int pauseafter)
+{
+	struct omap_dma_list_config_params *lcfg;
+	struct omap_dma_sglist_node *sgn;
+	int l, sys_cf;
+
+	lcfg = &dma_chan[lch].list_config;
+	sgn = lcfg->sghead;
+
+	/* Maintain the pause state in descriptor */
+	omap_set_dma_sglist_pausebit(lcfg, lcfg->pausenode, 0);
+	omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1);
+
+	/**
+	 * Barrier needed as writes to the
+	 * descriptor memory needs to be flushed
+	 * before it's used by DMA controller
+	 */
+	wmb();
+
+	/* Errata i557 - pausebit should be cleared in no standby mode */
+	sys_cf = p->dma_read(OCP_SYSCONFIG, 0);
+	l = sys_cf;
+	/* Middle mode reg set no Standby */
+	l &= ~(BIT(12) | BIT(13));
+	p->dma_write(l, OCP_SYSCONFIG, 0);
+
+	/* Clear pause bit in CDP */
+	l = p->dma_read(CDP, lch);
+	l &= ~(DMA_LIST_CDP_PAUSEMODE);
+	p->dma_write(l, CDP, lch);
+
+	omap_start_dma(lch);
+
+	/* Errata i557 - put in the old value */
+	p->dma_write(sys_cf, OCP_SYSCONFIG, 0);
+	return 0;
+}
+EXPORT_SYMBOL(omap_resume_dma_sglist_transfers);
+
+void omap_release_dma_sglist(int lch)
+{
+	omap_clear_dma_sglist_mode(lch);
+	omap_free_dma(lch);
+
+	return;
+}
+EXPORT_SYMBOL(omap_release_dma_sglist);
+
+int omap_get_completed_sglist_nodes(int lch)
+{
+	int list_count;
+
+	list_count = p->dma_read(CCDN, lch);
+	return list_count & 0xffff; /* only 16 LSB bits are valid */
+}
+EXPORT_SYMBOL(omap_get_completed_sglist_nodes);
+
+int omap_dma_sglist_is_paused(int lch)
+{
+	int list_state;
+	list_state = p->dma_read(CDP, lch);
+	return (list_state & DMA_LIST_CDP_PAUSEMODE) ? 1 : 0;
+}
+EXPORT_SYMBOL(omap_dma_sglist_is_paused);
+
+void omap_dma_set_sglist_fastmode(int lch, int fastmode)
+{
+	int l = p->dma_read(CDP, lch);
+
+	if (fastmode)
+		l |= DMA_LIST_CDP_FASTMODE;
+	else
+		l &= ~(DMA_LIST_CDP_FASTMODE);
+	p->dma_write(l, CDP, lch);
+}
+EXPORT_SYMBOL(omap_dma_set_sglist_fastmode);
+
 /*----------------------------------------------------------------------------*/
 
 #ifdef CONFIG_ARCH_OMAP1
@@ -1997,6 +2275,7 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 			ret = -ENOMEM;
 			goto exit_dma_lch_fail;
 		}
+		dma_caps0_status = p->dma_read(CAPS_0, 0);
 	}
 
 	spin_lock_init(&dma_chan_lock);
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index d1c916f..4d73eb1 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -401,6 +401,13 @@ struct omap_dma_channel_params {
 #endif
 };
 
+struct omap_dma_list_config_params {
+	unsigned int num_elem;
+	struct omap_dma_sglist_node *sghead;
+	dma_addr_t sgheadphy;
+	unsigned int pausenode;
+};
+
 struct omap_dma_lch {
 	int next_lch;
 	int dev_id;
@@ -416,6 +423,7 @@ struct omap_dma_lch {
 	int state;
 	int chain_id;
 	int status;
+	struct omap_dma_list_config_params list_config;
 };
 
 struct omap_dma_dev_attr {
@@ -437,6 +445,84 @@ struct omap_system_dma_plat_info {
 	u32 (*dma_read)(int reg, int lch);
 };
 
+struct omap_dma_sglist_type1_params {
+	u32 src_addr;
+	u32 dst_addr;
+	u16 cfn_fn;
+	u16 cicr;
+	u16 dst_elem_idx;
+	u16 src_elem_idx;
+	u32 dst_frame_idx_or_pkt_size;
+	u32 src_frame_idx_or_pkt_size;
+	u32 color;
+	u32 csdp;
+	u32 clnk_ctrl;
+	u32 ccr;
+};
+
+struct omap_dma_sglist_type2a_params {
+	u32 src_addr;
+	u32 dst_addr;
+	u16 cfn_fn;
+	u16 cicr;
+	u16 dst_elem_idx;
+	u16 src_elem_idx;
+	u32 dst_frame_idx_or_pkt_size;
+	u32 src_frame_idx_or_pkt_size;
+};
+
+struct omap_dma_sglist_type2b_params {
+	u32 src_or_dest_addr;
+	u16 cfn_fn;
+	u16 cicr;
+	u16 dst_elem_idx;
+	u16 src_elem_idx;
+	u32 dst_frame_idx_or_pkt_size;
+	u32 src_frame_idx_or_pkt_size;
+};
+
+struct omap_dma_sglist_type3a_params {
+	u32 src_addr;
+	u32 dst_addr;
+};
+
+struct omap_dma_sglist_type3b_params {
+	u32 src_or_dest_addr;
+};
+
+enum omap_dma_sglist_descriptor_select {
+	OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1,
+	OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a,
+	OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b,
+	OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a,
+	OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b,
+};
+
+union omap_dma_sglist_node_type {
+	struct omap_dma_sglist_type1_params t1;
+	struct omap_dma_sglist_type2a_params t2a;
+	struct omap_dma_sglist_type2b_params t2b;
+	struct omap_dma_sglist_type3a_params t3a;
+	struct omap_dma_sglist_type3b_params t3b;
+};
+
+struct omap_dma_sglist_node {
+
+	/* Common elements for all descriptors */
+	dma_addr_t next_desc_add_ptr;
+	u32 num_of_elem;
+	/* Type specific elements */
+	union omap_dma_sglist_node_type sg_node;
+	/* Control fields */
+	unsigned short flags;
+	/* Fields that can be set in flags variable */
+	#define OMAP_DMA_LIST_SRC_VALID		BIT(0)
+	#define OMAP_DMA_LIST_DST_VALID		BIT(1)
+	#define OMAP_DMA_LIST_NOTIFY_BLOCK_END	BIT(2)
+	enum omap_dma_sglist_descriptor_select desc_type;
+	struct omap_dma_sglist_node *next;
+};
+
 extern void omap_set_dma_priority(int lch, int dst_port, int priority);
 extern int omap_request_dma(int dev_id, const char *dev_name,
 			void (*callback)(int lch, u16 ch_status, void *data),
@@ -530,4 +616,91 @@ static inline int omap_lcd_dma_running(void)
 }
 #endif
 
+/**
+ * omap_set_dma_sglist_mode()	Switch channel to scatter gather mode
+ * @lch:	Logical channel to switch to sglist mode
+ * @sghead:	Contains the descriptor elements to be executed
+ *		Should be allocated using dma_alloc_coherent
+ * @padd:	The dma address of sghead, as returned by dma_alloc_coherent
+ * @nelem:	Number of elements in sghead
+ * @chparams:	DMA channel transfer parameters. Can be NULL
+ */
+extern int omap_set_dma_sglist_mode(int lch,
+	struct omap_dma_sglist_node *sghead, dma_addr_t padd,
+	int nelem, struct omap_dma_channel_params *chparams);
+
+/**
+ * omap_clear_dma_sglist_mode()	Switch from scatter gather mode
+ *				to normal mode
+ * @lch:	The logical channel to be switched to normal mode
+ *
+ * Switches the requested logical channel to normal mode
+ * from scatter gather mode
+ */
+extern void omap_clear_dma_sglist_mode(int lch);
+
+/**
+ * omap_start_dma_sglist_transfers()	Starts the sglist transfer
+ * @lch:	logical channel on which sglist transfer to be started
+ * @pauseafter:	index of the element on which to pause the transfer
+ *		set to -1 if no pause is needed till end of transfer
+ *
+ * Start the dma transfer in list mode
+ * The index (in pauseafter) is absolute (from the head of the list)
+ * User should have previously called omap_set_dma_sglist_mode()
+ */
+extern int omap_start_dma_sglist_transfers(int lch, int pauseafter);
+
+/**
+ * omap_resume_dma_sglist_transfers()	Resumes a previously paused
+ *					sglist transfer
+ * @lch:	The logical channel to be resumed
+ * @pauseafter:	The index of sglist to be paused again
+ *		set to -1 if no pause is needed till end of transfer
+ *
+ * Resume the previously paused transfer
+ * The index (in pauseafter) is absolute (from the head of the list)
+ */
+extern int omap_resume_dma_sglist_transfers(int lch, int pauseafter);
+
+/**
+ * omap_release_dma_sglist()	Releases a previously requested
+ *				DMA channel which is in sglist mode
+ * @lch:	The logical channel to be released
+ */
+extern void omap_release_dma_sglist(int lch);
+
+/**
+ * omap_get_completed_sglist_nodes()	Returns a list of completed
+ *					sglist nodes
+ * @lch:	The logical on which the query is to be made
+ *
+ * Returns the number of completed elements in the linked list
+ * The value is transient if the API is invoked for an ongoing transfer
+ */
+int omap_get_completed_sglist_nodes(int lch);
+
+/**
+ * omap_dma_sglist_is_paused()	Query is the logical channel in
+ *				sglist mode is paused or note
+ * @lch:	The logical on which the query is to be made
+ *
+ * Returns non zero if the linked list is currently in pause state
+ */
+int omap_dma_sglist_is_paused(int lch);
+
+/**
+ * omap_dma_set_sglist_fastmode() Set the sglist transfer to fastmode
+ * @lch:	The logical channel which is to be changed to fastmode
+ * @fastmode:	Set or clear the fastmode status
+ *		1 = set fastmode
+ *		0 = clear fastmode
+ *
+ * In fastmode, DMA register settings are updated from the first element
+ * of the linked list, before initiating the tranfer.
+ * In non-fastmode, the first element is used only after completing the
+ * transfer as already configured in the registers
+ */
+void omap_dma_set_sglist_fastmode(int lch, int fastmode);
+
 #endif /* __ASM_ARCH_DMA_H */
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 02/22] OMAP: DMA: add omap_dma_has_sglist()
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
  2011-05-05 11:51 ` [PATCH 01/22] OMAP: sDMA: descriptor autoloading feature Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 03/22] OMAP: DMA: Ensure the sglist registers are cleared Adrian Hunter
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter,
	Venkatraman S, Shilimkar Santosh, Tony Lindgren

Simplify detection of the sglist feature and add a
define for the super block end event that occurs
with sglist transfers.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
CC: Venkatraman S <svenkatr@ti.com>
CC: Madhusudhan C <madhu.cr@ti.com>
CC: Shilimkar Santosh <santosh.shilimkar@ti.com>
CC: Tony Lindgren <tony@atomide.com>
---
 arch/arm/plat-omap/dma.c              |    5 +++++
 arch/arm/plat-omap/include/plat/dma.h |    3 +++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 7f64366..32a923a 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -1862,6 +1862,11 @@ int omap_get_dma_chain_src_pos(int chain_id)
 EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
 #endif	/* ifndef CONFIG_ARCH_OMAP1 */
 
+int omap_dma_has_sglist_mode(void)
+{
+	return dma_caps0_status & DMA_CAPS_SGLIST_SUPPORT;
+}
+
 int omap_set_dma_sglist_mode(int lch, struct omap_dma_sglist_node *sgparams,
 	dma_addr_t padd, int nelem, struct omap_dma_channel_params *chparams)
 {
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 4d73eb1..3536eb4 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -209,6 +209,7 @@
 #define OMAP2_DMA_SECURE_ERR_IRQ	(1 << 9)
 #define OMAP2_DMA_SUPERVISOR_ERR_IRQ	(1 << 10)
 #define OMAP2_DMA_MISALIGNED_ERR_IRQ	(1 << 11)
+#define OMAP2_DMA_SUPER_BLOCK_IRQ	(1 << 14)
 
 #define OMAP_DMA_CCR_EN			(1 << 7)
 #define OMAP_DMA_CCR_RD_ACTIVE		(1 << 9)
@@ -616,6 +617,8 @@ static inline int omap_lcd_dma_running(void)
 }
 #endif
 
+extern int omap_dma_has_sglist_mode(void);
+
 /**
  * omap_set_dma_sglist_mode()	Switch channel to scatter gather mode
  * @lch:	Logical channel to switch to sglist mode
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 03/22] OMAP: DMA: Ensure the sglist registers are cleared
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
  2011-05-05 11:51 ` [PATCH 01/22] OMAP: sDMA: descriptor autoloading feature Adrian Hunter
  2011-05-05 11:51 ` [PATCH 02/22] OMAP: DMA: add omap_dma_has_sglist() Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 04/22] mmc: omap hsmmc: adaptation of sdma descriptor Adrian Hunter
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter,
	Venkatraman S, Shilimkar Santosh, Tony Lindgren

The new DMA descriptor auto-loading feature (referred to
as sglist in the code) uses new registers.  Ensure they
are cleared.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
CC: Venkatraman S <svenkatr@ti.com>
CC: Madhusudhan C <madhu.cr@ti.com>
CC: Shilimkar Santosh <santosh.shilimkar@ti.com>
CC: Tony Lindgren <tony@atomide.com>
---
 arch/arm/plat-omap/dma.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 32a923a..a8264a0 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -1914,13 +1914,14 @@ void omap_clear_dma_sglist_mode(int lch)
 {
 	/* Clear entire CDP which is related to sglist handling */
 	p->dma_write(0, CDP, lch);
+	p->dma_write(0, CNDP, lch);
 	p->dma_write(0, CCDN, lch);
-	/**
-	 * Put back the original enabled irqs, which
-	 * could have been overwritten by type 1 or type 2
-	 * descriptors
+	/*
+	 * CICR could have been overwritten by type 1 or type 2
+	 * descriptors.  It is set up in omap_start_dma() anyway
+	 * so just clear it to be on the safe side.
 	 */
-	p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
+	p->dma_write(0, CICR, lch);
 	return;
 }
 EXPORT_SYMBOL(omap_clear_dma_sglist_mode);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 04/22] mmc: omap hsmmc: adaptation of sdma descriptor
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (2 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 03/22] OMAP: DMA: Ensure the sglist registers are cleared Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 05/22] mmc: omap_hsmmc: fix dma sglist use Adrian Hunter
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Venkatraman S,
	Shilimkar Santosh, Tony Lindgren, Adrian Hunter

From: Venkatraman S <svenkatr@ti.com>

autoloading feature

Start to use the sDMA descriptor autoloading feature.
For large datablocks, the MMC driver has to repeatedly setup,
program and teardown the dma channel for each element of the
sglist received in omap_hsmmc_request.

By using descriptor autoloading, transfers from / to each element of
the sglist is pre programmed into a linked list. The sDMA driver
completes the entire transaction and provides a single interrupt.

Due to this, number of dma interrupts for a typical 100MB transfer on the MMC is
reduced from 25000 to about 400 (approximate). Transfer speeds are improved by ~5%.
(Though it varies on the size of read / write & improves on huge transfers)

Descriptor autoloading is available only in 3630 and 4430 (as of now).
Hence normal DMA mode is also retained.

Signed-off-by: Venkatraman S <svenkatr@ti.com>
CC: Madhusudhan C <madhu.cr@ti.com>
CC: Shilimkar Santosh <santosh.shilimkar@ti.com>
CC: Tony Lindgren <tony@atomide.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |  147 ++++++++++++++++++++++++++++++++++------
 1 files changed, 125 insertions(+), 22 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 259ece0..ebcef31 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -104,6 +104,8 @@
 #define SRD			(1 << 26)
 #define SOFTRESET		(1 << 1)
 #define RESETDONE		(1 << 0)
+/* End of superblock indicator for sglist transfers */
+#define DMA_ICR_SGLIST_END	0x4D00
 
 /*
  * FIXME: Most likely all the data using these _DEVID defines should come
@@ -120,6 +122,12 @@
 #define OMAP_MMC_MASTER_CLOCK	96000000
 #define DRIVER_NAME		"omap_hsmmc"
 
+#define DMA_TYPE_NODMA	0
+#define DMA_TYPE_SDMA	1
+#define DMA_TYPE_SDMA_DLOAD 2
+
+#define DMA_CTRL_BUF_SIZE	(PAGE_SIZE * 3)
+
 /* Timeouts for entering power saving states on inactivity, msec */
 #define OMAP_MMC_DISABLED_TIMEOUT	100
 #define OMAP_MMC_SLEEP_TIMEOUT		1000
@@ -172,7 +180,11 @@ struct omap_hsmmc_host {
 	u32			bytesleft;
 	int			suspended;
 	int			irq;
-	int			use_dma, dma_ch;
+	int			dma_caps;
+	int			dma_in_use;
+	int			dma_ch;
+	void			*dma_ctrl_buf;
+	dma_addr_t		dma_ctrl_buf_phy;
 	int			dma_line_tx, dma_line_rx;
 	int			slot_id;
 	int			got_dbclk;
@@ -561,7 +573,7 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
 {
 	unsigned int irq_mask;
 
-	if (host->use_dma)
+	if (host->dma_in_use)
 		irq_mask = INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE);
 	else
 		irq_mask = INT_EN_MASK;
@@ -851,7 +863,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
 			cmdreg &= ~(DDIR);
 	}
 
-	if (host->use_dma)
+	if (host->dma_in_use)
 		cmdreg |= DMA_EN;
 
 	host->req_in_progress = 1;
@@ -880,7 +892,7 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
 
 	omap_hsmmc_disable_irq(host);
 	/* Do not complete the request if DMA is still in progress */
-	if (mrq->data && host->use_dma && dma_ch != -1)
+	if (mrq->data && host->dma_in_use && dma_ch != -1)
 		return;
 	host->mrq = NULL;
 	mmc_request_done(host->mmc, mrq);
@@ -958,7 +970,7 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
 	host->dma_ch = -1;
 	spin_unlock(&host->irq_lock);
 
-	if (host->use_dma && dma_ch != -1) {
+	if (host->dma_in_use && dma_ch != -1) {
 		dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
 			omap_hsmmc_get_dma_dir(host, host->data));
 		omap_free_dma(dma_ch);
@@ -1310,7 +1322,6 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host,
 			omap_hsmmc_get_dma_sync_dev(host, data),
 			!(data->flags & MMC_DATA_WRITE));
 
-	omap_start_dma(dma_ch);
 }
 
 /*
@@ -1334,13 +1345,16 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
 		return;
 	}
 
-	host->dma_sg_idx++;
-	if (host->dma_sg_idx < host->dma_len) {
-		/* Fire up the next transfer. */
-		omap_hsmmc_config_dma_params(host, data,
-					   data->sg + host->dma_sg_idx);
-		spin_unlock(&host->irq_lock);
-		return;
+	if (host->dma_in_use == DMA_TYPE_SDMA) {
+		host->dma_sg_idx++;
+		if (host->dma_sg_idx < host->dma_len) {
+			/* Fire up the next transfer. */
+			omap_hsmmc_config_dma_params(host, data,
+						   data->sg + host->dma_sg_idx);
+			omap_start_dma(host->dma_ch);
+			spin_unlock(&host->irq_lock);
+			return;
+		}
 	}
 
 	dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
@@ -1362,10 +1376,19 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
 	}
 }
 
+static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host)
+{
+	if (host->dma_in_use == DMA_TYPE_SDMA)
+		omap_start_dma(host->dma_ch);
+	else if (host->dma_in_use == DMA_TYPE_SDMA_DLOAD)
+		return omap_start_dma_sglist_transfers(host->dma_ch, -1);
+
+	return 0;
+}
 /*
- * Routine to configure and start DMA for the MMC card
+ * Routine to configure DMA for the MMC card
  */
-static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
+static int omap_hsmmc_configure_sdma(struct omap_hsmmc_host *host,
 					struct mmc_request *req)
 {
 	int dma_ch = 0, ret = 0, i;
@@ -1406,6 +1429,56 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
 	return 0;
 }
 
+static int omap_hsmmc_configure_sdma_sglist(struct omap_hsmmc_host *host,
+		struct mmc_request *req)
+{
+	int i;
+	struct omap_dma_sglist_node *sglist, *snode;
+	struct mmc_data *data = req->data;
+	int blksz;
+	int dmadir = omap_hsmmc_get_dma_dir(host, data);
+	struct omap_dma_sglist_type2a_params *t2p;
+
+	sglist = (struct omap_dma_sglist_node *) host->dma_ctrl_buf;
+	snode = sglist;
+	blksz = host->data->blksz;
+
+	if ((host->dma_len * sizeof(*snode)) > DMA_CTRL_BUF_SIZE) {
+		dev_err(mmc_dev(host->mmc), "not enough sglist memory %d\n",
+			host->dma_len);
+		return -ENOMEM;
+	}
+	for (i = 0; i < host->dma_len; snode++, i++) {
+		snode->desc_type = OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a;
+		snode->num_of_elem = blksz / 4;
+		t2p = &snode->sg_node.t2a;
+
+		if (dmadir == DMA_FROM_DEVICE) {
+			t2p->src_addr = host->mapbase + OMAP_HSMMC_DATA;
+			t2p->dst_addr = sg_dma_address(data->sg + i);
+		} else {
+			t2p->dst_addr = host->mapbase + OMAP_HSMMC_DATA;
+			t2p->src_addr = sg_dma_address(data->sg + i);
+		}
+		snode->flags =
+			OMAP_DMA_LIST_DST_VALID | OMAP_DMA_LIST_SRC_VALID;
+
+		t2p->cfn_fn = sg_dma_len(data->sg + i) / host->data->blksz;
+		t2p->cicr = DMA_ICR_SGLIST_END;
+
+		t2p->dst_frame_idx_or_pkt_size = 0;
+		t2p->src_frame_idx_or_pkt_size = 0;
+		t2p->dst_elem_idx = 0;
+		t2p->src_elem_idx = 0;
+	}
+	dev_dbg(mmc_dev(host->mmc), "new sglist %x len =%d\n",
+			host->dma_ctrl_buf_phy, i);
+	omap_set_dma_sglist_mode(host->dma_ch, sglist,
+			host->dma_ctrl_buf_phy, i, NULL);
+	omap_dma_set_sglist_fastmode(host->dma_ch, 1);
+	return 0;
+}
+
 static void set_data_timeout(struct omap_hsmmc_host *host,
 			     unsigned int timeout_ns,
 			     unsigned int timeout_clks)
@@ -1467,14 +1540,23 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
 					| (req->data->blocks << 16));
 	set_data_timeout(host, req->data->timeout_ns, req->data->timeout_clks);
 
-	if (host->use_dma) {
-		ret = omap_hsmmc_start_dma_transfer(host, req);
-		if (ret != 0) {
-			dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n");
+	if (host->dma_caps & DMA_TYPE_SDMA) {
+		ret = omap_hsmmc_configure_sdma(host, req);
+		if (ret)
 			return ret;
-		}
+		host->dma_in_use = DMA_TYPE_SDMA;
 	}
-	return 0;
+	if ((host->dma_caps & DMA_TYPE_SDMA_DLOAD) &&
+		host->data->sg_len > 4) {
+		ret = omap_hsmmc_configure_sdma_sglist(host, req);
+		if (ret)
+			return ret;
+		host->dma_in_use = DMA_TYPE_SDMA_DLOAD;
+
+	}
+	ret = omap_hsmmc_start_dma_transfer(host);
+	return ret;
+
 }
 
 /*
@@ -2065,7 +2147,9 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	host->mmc	= mmc;
 	host->pdata	= pdata;
 	host->dev	= &pdev->dev;
-	host->use_dma	= 1;
+	host->dma_caps	= DMA_TYPE_SDMA;
+	host->dma_in_use	= DMA_TYPE_NODMA;
+	host->dma_ctrl_buf = NULL;
 	host->dev->dma_mask = &pdata->dma_mask;
 	host->dma_ch	= -1;
 	host->irq	= irq;
@@ -2146,6 +2230,15 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 							" clk failed\n");
 	}
 
+	if (cpu_is_omap44xx() || cpu_is_omap3630()) {
+		host->dma_ctrl_buf = dma_alloc_coherent(NULL,
+					DMA_CTRL_BUF_SIZE,
+					&host->dma_ctrl_buf_phy,
+					0);
+		if (host->dma_ctrl_buf != NULL)
+			host->dma_caps |= DMA_TYPE_SDMA_DLOAD;
+	}
+
 	/* Since we do only SG emulation, we can have as many segs
 	 * as we want. */
 	mmc->max_segs = 1024;
@@ -2271,6 +2364,10 @@ err_reg:
 err_irq_cd_init:
 	free_irq(host->irq, host);
 err_irq:
+	if (host->dma_ctrl_buf)
+		dma_free_coherent(NULL, DMA_CTRL_BUF_SIZE,
+				host->dma_ctrl_buf,
+				host->dma_ctrl_buf_phy);
 	mmc_host_disable(host->mmc);
 	clk_disable(host->iclk);
 	clk_put(host->fclk);
@@ -2298,6 +2395,12 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 	if (host) {
 		mmc_host_enable(host->mmc);
 		mmc_remove_host(host->mmc);
+
+		if (host->dma_ctrl_buf != NULL) {
+			dma_free_coherent(NULL, DMA_CTRL_BUF_SIZE,
+				host->dma_ctrl_buf,
+				host->dma_ctrl_buf_phy);
+		}
 		if (host->use_reg)
 			omap_hsmmc_reg_put(host);
 		if (host->pdata->cleanup)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 05/22] mmc: omap_hsmmc: fix dma sglist use
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (3 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 04/22] mmc: omap hsmmc: adaptation of sdma descriptor Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 06/22] mmc: omap_hsmmc: limit scatterlist size for sDMA autoloading Adrian Hunter
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter,
	Venkatraman S, Shilimkar Santosh, Tony Lindgren

Allow for the super block end event used by sglist
DMA transfers and tidy the detection of the DMA
sglist feature.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
CC: Venkatraman S <svenkatr@ti.com>
CC: Madhusudhan C <madhu.cr@ti.com>
CC: Shilimkar Santosh <santosh.shilimkar@ti.com>
CC: Tony Lindgren <tony@atomide.com>
---
 drivers/mmc/host/omap_hsmmc.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index ebcef31..114cd68 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1333,7 +1333,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
 	struct mmc_data *data = host->mrq->data;
 	int dma_ch, req_in_progress;
 
-	if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) {
+	if (!(ch_status & (OMAP_DMA_BLOCK_IRQ | OMAP2_DMA_SUPER_BLOCK_IRQ))) {
 		dev_warn(mmc_dev(host->mmc), "unexpected dma status %x\n",
 			ch_status);
 		return;
@@ -2230,7 +2230,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 							" clk failed\n");
 	}
 
-	if (cpu_is_omap44xx() || cpu_is_omap3630()) {
+	if (omap_dma_has_sglist_mode()) {
 		host->dma_ctrl_buf = dma_alloc_coherent(NULL,
 					DMA_CTRL_BUF_SIZE,
 					&host->dma_ctrl_buf_phy,
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 06/22] mmc: omap_hsmmc: limit scatterlist size for sDMA autoloading
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (4 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 05/22] mmc: omap_hsmmc: fix dma sglist use Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 07/22] mmc: omap_hsmmc: fix missing mmc_release_host() in no_off case Adrian Hunter
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter

The sDMA descriptor autoloading feature uses a fixed size
buffer to store descriptors for scatterlist segments.
That limits the scatterlist size to the maximum number
of descriptors that fit in the buffer.  The driver must
set this limit for upper layers to obey.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   15 ++++++++++++---
 1 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 114cd68..bab25ff 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -2239,9 +2239,18 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 			host->dma_caps |= DMA_TYPE_SDMA_DLOAD;
 	}
 
-	/* Since we do only SG emulation, we can have as many segs
-	 * as we want. */
-	mmc->max_segs = 1024;
+	if (host->dma_caps & DMA_TYPE_SDMA_DLOAD) {
+		unsigned int max = DMA_CTRL_BUF_SIZE /
+				   sizeof(struct omap_dma_sglist_node);
+
+		mmc->max_segs = 1 << (fls(max) - 1);
+	} else {
+		/*
+		 * Since we do only SG emulation, we can have as many segs as we
+		 * want.
+		 */
+		mmc->max_segs = 1024;
+	}
 
 	mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
 	mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 07/22] mmc: omap_hsmmc: fix missing mmc_release_host() in no_off case
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (5 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 06/22] mmc: omap_hsmmc: limit scatterlist size for sDMA autoloading Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 13:08   ` Sergei Shtylyov
  2011-05-05 11:51 ` [PATCH 08/22] mmc: omap_hsmmc: correct debug report error status mnemonics Adrian Hunter
                   ` (14 subsequent siblings)
  21 siblings, 1 reply; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Sudhir Bera,
	Adrian Hunter

From: Sudhir Bera <ext-sudhir.bera@nokia.com>

In fact the no_off check here will not be hit because
'omap_hsmmc_disabled_to_sleep()' won't schedule a
deeper disable in the no_off case.

Signed-off-by: Sudhir Bera <ext-sudhir.bera@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index bab25ff..bd52849 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1852,14 +1852,13 @@ static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host)
 		return 0;
 
 	if (mmc_slot(host).no_off)
-		return 0;
+		goto out;
 
 	if (!((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
 	      mmc_slot(host).card_detect ||
 	      (mmc_slot(host).get_cover_state &&
 	       mmc_slot(host).get_cover_state(host->dev, host->slot_id)))) {
-		mmc_release_host(host->mmc);
-		return 0;
+		goto out;
 	}
 
 	mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
@@ -1870,7 +1869,7 @@ static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host)
 		host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP");
 
 	host->dpm_state = OFF;
-
+out:
 	mmc_release_host(host->mmc);
 
 	return 0;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 08/22] mmc: omap_hsmmc: correct debug report error status mnemonics
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (6 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 07/22] mmc: omap_hsmmc: fix missing mmc_release_host() in no_off case Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-06  8:35   ` S, Venkatraman
  2011-05-05 11:51 ` [PATCH 09/22] mmc: omap_hsmmc: move hardcoded frequency constants to definition block Adrian Hunter
                   ` (13 subsequent siblings)
  21 siblings, 1 reply; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter

CERR and BADA were in the wrong place and there are only
32 not 35.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index bd52849..a1a1101 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -982,14 +982,14 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
  * Readable error output
  */
 #ifdef CONFIG_MMC_DEBUG
-static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status)
+static void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, u32 status)
 {
 	/* --- means reserved bit without definition at documentation */
 	static const char *omap_hsmmc_status_bits[] = {
-		"CC", "TC", "BGE", "---", "BWR", "BRR", "---", "---", "CIRQ",
-		"OBI", "---", "---", "---", "---", "---", "ERRI", "CTO", "CCRC",
-		"CEB", "CIE", "DTO", "DCRC", "DEB", "---", "ACE", "---",
-		"---", "---", "---", "CERR", "CERR", "BADA", "---", "---", "---"
+		"CC"  , "TC"  , "BGE", "---", "BWR" , "BRR" , "---" , "---" ,
+		"CIRQ",	"OBI" , "---", "---", "---" , "---" , "---" , "ERRI",
+		"CTO" , "CCRC", "CEB", "CIE", "DTO" , "DCRC", "DEB" , "---" ,
+		"ACE" , "---" , "---", "---", "CERR", "BADA", "---" , "---"
 	};
 	char res[256];
 	char *buf = res;
@@ -1006,6 +1006,11 @@ static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status)
 
 	dev_dbg(mmc_dev(host->mmc), "%s\n", res);
 }
+#else
+static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host,
+					     u32 status)
+{
+}
 #endif  /* CONFIG_MMC_DEBUG */
 
 /*
@@ -1064,9 +1069,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
 	dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
 
 	if (status & ERR) {
-#ifdef CONFIG_MMC_DEBUG
-		omap_hsmmc_report_irq(host, status);
-#endif
+		omap_hsmmc_dbg_report_irq(host, status);
 		if ((status & CMD_TIMEOUT) ||
 			(status & CMD_CRC)) {
 			if (host->cmd) {
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 09/22] mmc: omap_hsmmc: move hardcoded frequency constants to definition block
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (7 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 08/22] mmc: omap_hsmmc: correct debug report error status mnemonics Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 10/22] mmc: omap_hsmmc: reduce a bit the error handlers in probe() Adrian Hunter
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Andy Shevchenko,
	Adrian Hunter

From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>

Move the min and max frequency constants to the definition block in the source
file.

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index a1a1101..a727bf8 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -120,6 +120,8 @@
 
 #define MMC_TIMEOUT_MS		20
 #define OMAP_MMC_MASTER_CLOCK	96000000
+#define OMAP_MMC_MIN_CLOCK	400000
+#define OMAP_MMC_MAX_CLOCK	52000000
 #define DRIVER_NAME		"omap_hsmmc"
 
 #define DMA_TYPE_NODMA	0
@@ -2176,8 +2178,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	if (mmc_slot(host).vcc_aux_disable_is_sleep)
 		mmc_slot(host).no_off = 1;
 
-	mmc->f_min	= 400000;
-	mmc->f_max	= 52000000;
+	mmc->f_min	= OMAP_MMC_MIN_CLOCK;
+	mmc->f_max	= OMAP_MMC_MAX_CLOCK;
 
 	spin_lock_init(&host->irq_lock);
 
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 10/22] mmc: omap_hsmmc: reduce a bit the error handlers in probe()
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (8 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 09/22] mmc: omap_hsmmc: move hardcoded frequency constants to definition block Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 11/22] mmc: omap_hsmmc: split duplicate code to calc_divisor() function Adrian Hunter
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Andy Shevchenko,
	Adrian Hunter

From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   17 ++++++-----------
 1 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index a727bf8..7a153af 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -2204,18 +2204,11 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	/* we start off in DISABLED state */
 	host->dpm_state = DISABLED;
 
-	if (clk_enable(host->iclk) != 0) {
-		clk_put(host->iclk);
-		clk_put(host->fclk);
-		goto err1;
-	}
+	if (clk_enable(host->iclk) != 0)
+		goto err2;
 
-	if (mmc_host_enable(host->mmc) != 0) {
-		clk_disable(host->iclk);
-		clk_put(host->iclk);
-		clk_put(host->fclk);
-		goto err1;
-	}
+	if (mmc_host_enable(host->mmc) != 0)
+		goto err3;
 
 	if (cpu_is_omap2430()) {
 		host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
@@ -2382,7 +2375,9 @@ err_irq:
 				host->dma_ctrl_buf,
 				host->dma_ctrl_buf_phy);
 	mmc_host_disable(host->mmc);
+err3:
 	clk_disable(host->iclk);
+err2:
 	clk_put(host->fclk);
 	clk_put(host->iclk);
 	if (host->got_dbclk) {
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 11/22] mmc: omap_hsmmc: split duplicate code to calc_divisor() function
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (9 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 10/22] mmc: omap_hsmmc: reduce a bit the error handlers in probe() Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 12/22] mmc: omap_hsmmc: introduce start_clock and re-use stop_clock Adrian Hunter
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Andy Shevchenko,
	Adrian Hunter

From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>

There are two places where the same calculations are done. Let's split them to
separate function.

In addition the new function is simplified by usage DIV_ROUND_UP kernel macro.

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   45 ++++++++++++++++------------------------
 1 files changed, 18 insertions(+), 27 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 7a153af..045c581 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -596,6 +596,20 @@ static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
 	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 }
 
+/* Calculate divisor for the given clock frequency */
+static u16 calc_divisor(struct mmc_ios *ios)
+{
+	u16 dsor = 0;
+
+	if (ios->clock) {
+		dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, ios->clock);
+		if (dsor > 250)
+			dsor = 250;
+	}
+
+	return dsor;
+}
+
 #ifdef CONFIG_PM
 
 /*
@@ -608,7 +622,6 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 	struct omap_mmc_platform_data *pdata = host->pdata;
 	int context_loss = 0;
 	u32 hctl, capa, con;
-	u16 dsor = 0;
 	unsigned long timeout;
 
 	if (pdata->get_context_loss_count) {
@@ -687,21 +700,10 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 		break;
 	}
 
-	if (ios->clock) {
-		dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
-		if (dsor < 1)
-			dsor = 1;
-
-		if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
-			dsor++;
-
-		if (dsor > 250)
-			dsor = 250;
-	}
-
 	OMAP_HSMMC_WRITE(host->base, SYSCTL,
 		OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN);
-	OMAP_HSMMC_WRITE(host->base, SYSCTL, (dsor << 6) | (DTO << 16));
+	OMAP_HSMMC_WRITE(host->base, SYSCTL,
+		(calc_divisor(ios) << 6) | (DTO << 16));
 	OMAP_HSMMC_WRITE(host->base, SYSCTL,
 		OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
 
@@ -1612,7 +1614,6 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
 static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
-	u16 dsor = 0;
 	unsigned long regval;
 	unsigned long timeout;
 	u32 con;
@@ -1676,21 +1677,11 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		}
 	}
 
-	if (ios->clock) {
-		dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
-		if (dsor < 1)
-			dsor = 1;
-
-		if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
-			dsor++;
-
-		if (dsor > 250)
-			dsor = 250;
-	}
 	omap_hsmmc_stop_clock(host);
+
 	regval = OMAP_HSMMC_READ(host->base, SYSCTL);
 	regval = regval & ~(CLKD_MASK);
-	regval = regval | (dsor << 6) | (DTO << 16);
+	regval = regval | (calc_divisor(ios) << 6) | (DTO << 16);
 	OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
 	OMAP_HSMMC_WRITE(host->base, SYSCTL,
 		OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 12/22] mmc: omap_hsmmc: introduce start_clock and re-use stop_clock
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (10 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 11/22] mmc: omap_hsmmc: split duplicate code to calc_divisor() function Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 13/22] mmc: omap_hsmmc: fix few bugs when set the clock divisor Adrian Hunter
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Andy Shevchenko,
	Adrian Hunter

From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>

There is similar piece of code in two functions which enables clock. Split this
code to omap_hsmmc_start_clock(). Re-use omap_hsmmc_stop_clock() in
omap_hsmmc_context_restore() as well.

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 045c581..ae6d204 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -560,6 +560,15 @@ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
 }
 
 /*
+ * Start clock to the card
+ */
+static void omap_hsmmc_start_clock(struct omap_hsmmc_host *host)
+{
+	OMAP_HSMMC_WRITE(host->base, SYSCTL,
+		OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
+}
+
+/*
  * Stop clock to the card
  */
 static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host)
@@ -700,8 +709,8 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 		break;
 	}
 
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN);
+	omap_hsmmc_stop_clock(host);
+
 	OMAP_HSMMC_WRITE(host->base, SYSCTL,
 		(calc_divisor(ios) << 6) | (DTO << 16));
 	OMAP_HSMMC_WRITE(host->base, SYSCTL,
@@ -712,8 +721,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 		&& time_before(jiffies, timeout))
 		;
 
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
+	omap_hsmmc_start_clock(host);
 
 	con = OMAP_HSMMC_READ(host->base, CON);
 	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
@@ -1692,8 +1700,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		&& time_before(jiffies, timeout))
 		msleep(1);
 
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
+	omap_hsmmc_start_clock(host);
 
 	if (do_send_init_stream)
 		send_init_stream(host);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 13/22] mmc: omap_hsmmc: fix few bugs when set the clock divisor
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (11 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 12/22] mmc: omap_hsmmc: introduce start_clock and re-use stop_clock Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 12:53   ` Grazvydas Ignotas
  2011-05-05 11:51 ` [PATCH 14/22] mmc: omap_hsmmc: split same pieces of code to separate functions Adrian Hunter
                   ` (8 subsequent siblings)
  21 siblings, 1 reply; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Andy Shevchenko,
	Adrian Hunter

From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>

There are two pieces of code which similar, but not the same. Each of them
contains a bug.

The SYSCTL register should be read before write in the
omap_hsmmc_context_restore() to remain the state of the reserved bits.

Before set the clock divisor and DTO bits the value from the SYSCTL register
should be masked properly. We were lucky to have no problems with DTO bits. So,
make sure we have clear DTO bits properly in the omap_hsmmc_set_ios().

Additionally get rid of msleep(1). The actual time rare higher than 30us on
OMAP 3630.

The result pieces of code are split to omap_hsmmc_set_clock() function.

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   59 +++++++++++++++++++---------------------
 1 files changed, 28 insertions(+), 31 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index ae6d204..3c76911 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -619,6 +619,32 @@ static u16 calc_divisor(struct mmc_ios *ios)
 	return dsor;
 }
 
+static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
+{
+	struct mmc_ios *ios = &host->mmc->ios;
+	unsigned long regval;
+	unsigned long timeout;
+
+	dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
+
+	omap_hsmmc_stop_clock(host);
+
+	regval = OMAP_HSMMC_READ(host->base, SYSCTL);
+	regval = regval & ~(CLKD_MASK | DTO_MASK);
+	regval = regval | (calc_divisor(ios) << 6) | (DTO << 16);
+	OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
+	OMAP_HSMMC_WRITE(host->base, SYSCTL,
+		OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
+
+	/* Wait till the ICS bit is set */
+	timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
+	while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
+		&& time_before(jiffies, timeout))
+		;
+
+	omap_hsmmc_start_clock(host);
+}
+
 #ifdef CONFIG_PM
 
 /*
@@ -709,19 +735,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 		break;
 	}
 
-	omap_hsmmc_stop_clock(host);
-
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		(calc_divisor(ios) << 6) | (DTO << 16));
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
-
-	timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
-	while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
-		&& time_before(jiffies, timeout))
-		;
-
-	omap_hsmmc_start_clock(host);
+	omap_hsmmc_set_clock(host);
 
 	con = OMAP_HSMMC_READ(host->base, CON);
 	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
@@ -1622,8 +1636,6 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
 static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
-	unsigned long regval;
-	unsigned long timeout;
 	u32 con;
 	int do_send_init_stream = 0;
 
@@ -1685,22 +1697,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		}
 	}
 
-	omap_hsmmc_stop_clock(host);
-
-	regval = OMAP_HSMMC_READ(host->base, SYSCTL);
-	regval = regval & ~(CLKD_MASK);
-	regval = regval | (calc_divisor(ios) << 6) | (DTO << 16);
-	OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
-
-	/* Wait till the ICS bit is set */
-	timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
-	while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
-		&& time_before(jiffies, timeout))
-		msleep(1);
-
-	omap_hsmmc_start_clock(host);
+	omap_hsmmc_set_clock(host);
 
 	if (do_send_init_stream)
 		send_init_stream(host);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 14/22] mmc: omap_hsmmc: split same pieces of code to separate functions
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (12 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 13/22] mmc: omap_hsmmc: fix few bugs when set the clock divisor Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 15/22] OMAP: hsmmc: Do not mux the slot if non default muxing is already done Adrian Hunter
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Andy Shevchenko,
	Adrian Hunter

From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>

There are few places with the same functionality. This patch creates two
functions omap_hsmmc_set_bus_width() and omap_hsmmc_set_bus_mode() to do the
job.

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   85 ++++++++++++++++++++---------------------
 1 files changed, 41 insertions(+), 44 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 3c76911..e7c181a 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -645,6 +645,41 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
 	omap_hsmmc_start_clock(host);
 }
 
+static void omap_hsmmc_set_bus_width(struct omap_hsmmc_host *host)
+{
+	struct mmc_ios *ios = &host->mmc->ios;
+	u32 con;
+
+	con = OMAP_HSMMC_READ(host->base, CON);
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_8:
+		OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
+		break;
+	case MMC_BUS_WIDTH_4:
+		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
+		OMAP_HSMMC_WRITE(host->base, HCTL,
+			OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
+		break;
+	case MMC_BUS_WIDTH_1:
+		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
+		OMAP_HSMMC_WRITE(host->base, HCTL,
+			OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
+		break;
+	}
+}
+
+static void omap_hsmmc_set_bus_mode(struct omap_hsmmc_host *host)
+{
+	struct mmc_ios *ios = &host->mmc->ios;
+	u32 con;
+
+	con = OMAP_HSMMC_READ(host->base, CON);
+	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
+		OMAP_HSMMC_WRITE(host->base, CON, con | OD);
+	else
+		OMAP_HSMMC_WRITE(host->base, CON, con & ~OD);
+}
+
 #ifdef CONFIG_PM
 
 /*
@@ -656,7 +691,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 	struct mmc_ios *ios = &host->mmc->ios;
 	struct omap_mmc_platform_data *pdata = host->pdata;
 	int context_loss = 0;
-	u32 hctl, capa, con;
+	u32 hctl, capa;
 	unsigned long timeout;
 
 	if (pdata->get_context_loss_count) {
@@ -718,30 +753,12 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 	if (host->power_mode == MMC_POWER_OFF)
 		goto out;
 
-	con = OMAP_HSMMC_READ(host->base, CON);
-	switch (ios->bus_width) {
-	case MMC_BUS_WIDTH_8:
-		OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
-		break;
-	case MMC_BUS_WIDTH_4:
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
-		OMAP_HSMMC_WRITE(host->base, HCTL,
-			OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
-		break;
-	case MMC_BUS_WIDTH_1:
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
-		OMAP_HSMMC_WRITE(host->base, HCTL,
-			OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
-		break;
-	}
+	omap_hsmmc_set_bus_width(host);
 
 	omap_hsmmc_set_clock(host);
 
-	con = OMAP_HSMMC_READ(host->base, CON);
-	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-		OMAP_HSMMC_WRITE(host->base, CON, con | OD);
-	else
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~OD);
+	omap_hsmmc_set_bus_mode(host);
+
 out:
 	host->context_loss = context_loss;
 
@@ -1636,7 +1653,6 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
 static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
-	u32 con;
 	int do_send_init_stream = 0;
 
 	mmc_host_enable(host->mmc);
@@ -1662,22 +1678,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	/* FIXME: set registers based only on changes to ios */
 
-	con = OMAP_HSMMC_READ(host->base, CON);
-	switch (mmc->ios.bus_width) {
-	case MMC_BUS_WIDTH_8:
-		OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
-		break;
-	case MMC_BUS_WIDTH_4:
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
-		OMAP_HSMMC_WRITE(host->base, HCTL,
-			OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
-		break;
-	case MMC_BUS_WIDTH_1:
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
-		OMAP_HSMMC_WRITE(host->base, HCTL,
-			OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
-		break;
-	}
+	omap_hsmmc_set_bus_width(host);
 
 	if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
 		/* Only MMC1 can interface at 3V without some flavor
@@ -1702,11 +1703,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	if (do_send_init_stream)
 		send_init_stream(host);
 
-	con = OMAP_HSMMC_READ(host->base, CON);
-	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-		OMAP_HSMMC_WRITE(host->base, CON, con | OD);
-	else
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~OD);
+	omap_hsmmc_set_bus_mode(host);
 
 	if (host->power_mode == MMC_POWER_OFF)
 		mmc_host_disable(host->mmc);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 15/22] OMAP: hsmmc: Do not mux the slot if non default muxing is already done
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (13 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 14/22] mmc: omap_hsmmc: split same pieces of code to separate functions Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 16/22] OMAP: board-rm680: set MMC nomux flag Adrian Hunter
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Jarkko Lavinen,
	Adrian Hunter

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>

Allow the bootloader do all the muxing.

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 arch/arm/mach-omap2/hsmmc.c |    3 ++-
 arch/arm/mach-omap2/hsmmc.h |    1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index b2f30be..6b97fae 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -440,7 +440,8 @@ void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
 		pr_err("%s fails!\n", __func__);
 		goto done;
 	}
-	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
+	if (!hsmmcinfo->nomux)
+		omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
 
 	name = "omap_hsmmc";
 	ohl = omap_hsmmc_latency;
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index f119348..0f2a87e 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -19,6 +19,7 @@ struct omap2_hsmmc_info {
 	bool	power_saving;	/* Try to sleep or power off when possible */
 	bool	no_off;		/* power_saving and power is not to go off */
 	bool	vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */
+	bool    nomux;          /* No default muxing for this slot */
 	int	gpio_cd;	/* or -EINVAL */
 	int	gpio_wp;	/* or -EINVAL */
 	char	*name;		/* or NULL for default */
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 16/22] OMAP: board-rm680: set MMC nomux flag
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (14 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 15/22] OMAP: hsmmc: Do not mux the slot if non default muxing is already done Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 17/22] mmc: omap_hsmmc: ensure pbias configuration is always done Adrian Hunter
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter

Let the bootloader do all the pad configuration.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 arch/arm/mach-omap2/board-rm680.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 2af8b05..2dba9d0 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -125,6 +125,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.nomux		= true,
 	},
 	{ /* Terminator */ }
 };
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 17/22] mmc: omap_hsmmc: ensure pbias configuration is always done
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (15 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 16/22] OMAP: board-rm680: set MMC nomux flag Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 18/22] mmc: omap_hsmmc: fix oops in omap_hsmmc_dma_cb Adrian Hunter
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter

Go through the driver's set_power() functions rather than
calling regulator_enable/disable() directly because otherwise
pbias configuration for MMC1 is not done.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   17 ++++++++---------
 1 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index e7c181a..de7f15c 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -457,15 +457,14 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 		* framework is fixed, we need a workaround like this
 		* (which is safe for MMC, but not in general).
 		*/
-		if (regulator_is_enabled(host->vcc) > 0) {
-			regulator_enable(host->vcc);
-			regulator_disable(host->vcc);
-		}
-		if (host->vcc_aux) {
-			if (regulator_is_enabled(reg) > 0) {
-				regulator_enable(reg);
-				regulator_disable(reg);
-			}
+		if (regulator_is_enabled(host->vcc) > 0 ||
+		    (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) {
+			int vdd = ffs(mmc_slot(host).ocr_mask) - 1;
+
+			mmc_slot(host).set_power(host->dev, host->slot_id,
+						 1, vdd);
+			mmc_slot(host).set_power(host->dev, host->slot_id,
+						 0, 0);
 		}
 	}
 
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 18/22] mmc: omap_hsmmc: fix oops in omap_hsmmc_dma_cb
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (16 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 17/22] mmc: omap_hsmmc: ensure pbias configuration is always done Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 19/22] OMAP: hsmmc: implement clock switcher Adrian Hunter
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter

In the case of an I/O error, the DMA will have been
cleaned up in the MMC interrupt and the request
structure pointer will be null.

In that case, it is essential to check if the DMA
DMA is over before dereferencing host->mrq->data.

Oops as follows:

<3>[ 2293.695281] wl1271: ERROR sdio read failed (-110)
<1>[ 2293.695739] Unable to handle kernel NULL pointer dereference at virtual
address 00000004
<1>[ 2293.703094] pgd = b0004000
<1>[ 2293.705780] [00000004] *pgd=00000000
<0>[ 2293.709381] Internal error: Oops: 17 [#1] PREEMPT
<0>[ 2293.714080] last sysfs file:
/sys/devices/platform/omapdss/manager0/cpr_enable
<4>[ 2293.721313] Modules linked in: ext2 dm_crypt xt_NFLOG xt_rateest
xt_RATEEST xt_condition iptable_filter ip_tables dm_mod xt_IDLETIMER
nfnetlink_log nfnetlink as3645a ad58xx smiapp smiapp_power omap3_isp iovmm
omap3_iommu iommu2 iommu wl12xx_spi bnep omaplfb bridgedriver g_file_storage
cmt_speech ssi_protocol phonet hsi_char wl12xx_sdio wl12xx pvrsrvkm omap_ssi
mailbox_mach vibra_spi radio_wl1273 mailbox bcm4751_gps lis3lv02d_i2c ak8975
lis3lv02d leds_lp5521 apds990x pn544 rtc_twl4030 twl4030_keypad
twl4030_pwrbutton cmt twl5031_aci hci_h4p
<4>[ 2293.769287] CPU: 0    Not tainted  (2.6.32.36-dfl61-20111603 #1)
<4>[ 2293.775329] PC is at omap_hsmmc_dma_cb+0x18/0x140
<4>[ 2293.780029] LR is at omap2_dma_irq_handler+0x244/0x28c
<4>[ 2293.785156] pc : [<b024e180>]    lr : [<b0049ed0>]    psr: a00001d3
<4>[ 2293.785186] sp : edfb3c48  ip : edfb3bf8  fp : edfb3d3c
<4>[ 2293.796661] r10: fa05632c  r9 : fa056000  r8 : ee4889c0
<4>[ 2293.801910] r7 : 00000020  r6 : 00000001  r5 : edfb2000  r4 : ee53e1c0
<4>[ 2293.808441] r3 : 00000000  r2 : edfb3c48  r1 : 00000020  r0 : 00000007
<4>[ 2293.814971] Flags: NzCv  IRQs off  FIQs off  Mode SVC_32  ISA ARM
Segment kernel
<4>[ 2293.822479] Control: 10c5387d  Table: bc9f4019  DAC: 00000017
<0>[ 2293.828247] Process phy0 (pid: 313, stack limit = 0xedfb22e8)
<0>[ 2293.833984] Stack: (0xedfb3c48 to 0xedfb4000)
...
<4>[ 2294.084320] [<b024e180>] (omap_hsmmc_dma_cb+0x18/0x140) from [<b0049ed0>]
(omap2_dma_irq_handler+0x244/0x28c)
<4>[ 2294.094268] [<b0049ed0>] (omap2_dma_irq_handler+0x244/0x28c) from
[<b0093d44>] (handle_IRQ_event+0x34/0xf0)
<4>[ 2294.104034] [<b0093d44>] (handle_IRQ_event+0x34/0xf0) from [<b0095bec>]
(handle_level_irq+0xcc/0x170)
<4>[ 2294.113250] [<b0095bec>] (handle_level_irq+0xcc/0x170) from [<b002c068>]
(asm_do_IRQ+0x68/0x84)
<4>[ 2294.121978] [<b002c068>] (asm_do_IRQ+0x68/0x84) from [<b002ca84>]
(__irq_svc+0x44/0xa8)
<4>[ 2294.129974] Exception stack(0xedfb3cc0 to 0xedfb3d08)
<4>[ 2294.135040] 3cc0: 0021d5cd 00000000 3d20cc2d 00000002 edf7dd40 edfb2000
edf7dee8 edf7ddd8
<4>[ 2294.143249] 3ce0: 00000001 00000000 ee516080 edfb3d3c b04880b8 edfb3d08
b0059e5c b0344184
<4>[ 2294.151428] 3d00: 00000053 ffffffff
<4>[ 2294.154968] [<b002ca84>] (__irq_svc+0x44/0xa8) from [<b0344184>]
(schedule+0x248/0x3a8)
<4>[ 2294.162963] [<b0344184>] (schedule+0x248/0x3a8) from [<b03448ac>]
(schedule_timeout+0x1c/0x224)
<4>[ 2294.171691] [<b03448ac>] (schedule_timeout+0x1c/0x224) from [<b0344738>]
(wait_for_common+0xe8/0x1a8)
<4>[ 2294.180938] [<b0344738>] (wait_for_common+0xe8/0x1a8) from [<b02459f8>]
(mmc_wait_for_req+0x110/0x120)
<4>[ 2294.190277] [<b02459f8>] (mmc_wait_for_req+0x110/0x120) from [<b0249bac>]
(mmc_io_rw_extended+0x178/0x1e0)
<4>[ 2294.199951] [<b0249bac>] (mmc_io_rw_extended+0x178/0x1e0) from
[<b024ab54>] (sdio_io_rw_ext_helper+0x164/0x190)
<4>[ 2294.210052] [<b024ab54>] (sdio_io_rw_ext_helper+0x164/0x190) from
[<b024aba0>] (sdio_writesb+0x20/0x24)
<4>[ 2294.219512] [<b024aba0>] (sdio_writesb+0x20/0x24) from [<af0d50e0>]
(wl1271_sdio_raw_write+0x64/0xa4 [wl12xx_sdio])
<4>[ 2294.230041] [<af0d50e0>] (wl1271_sdio_raw_write+0x64/0xa4 [wl12xx_sdio])
from [<af0bd4bc>] (wl1271_tx_work_locked+0x548/0x5fc [wl12xx])
<4>[ 2294.242218] [<af0bd4bc>] (wl1271_tx_work_locked+0x548/0x5fc [wl12xx])
from [<af0ba944>] (wl1271_irq_work+0x230/0x314 [wl12xx])
<4>[ 2294.253631] [<af0ba944>] (wl1271_irq_work+0x230/0x314 [wl12xx]) from
[<b00725ac>] (worker_thread+0x174/0x224)
<4>[ 2294.263519] [<b00725ac>] (worker_thread+0x174/0x224) from [<b0075bac>]
(kthread+0x7c/0x84)
<4>[ 2294.271820] [<b0075bac>] (kthread+0x7c/0x84) from [<b002d950>]
(kernel_thread_exit+0x0/0x8)
<0>[ 2294.280181] Code: e5923008 e1a0200d e3c25d7f e3c5503f (e5936004)
<4>[ 2294.286529] ---[ end trace e8fb05c679bd87ff ]---

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index de7f15c..2c8fa01 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1375,7 +1375,7 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host,
 static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
 {
 	struct omap_hsmmc_host *host = cb_data;
-	struct mmc_data *data = host->mrq->data;
+	struct mmc_data *data;
 	int dma_ch, req_in_progress;
 
 	if (!(ch_status & (OMAP_DMA_BLOCK_IRQ | OMAP2_DMA_SUPER_BLOCK_IRQ))) {
@@ -1390,6 +1390,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
 		return;
 	}
 
+	data = host->mrq->data;
 	if (host->dma_in_use == DMA_TYPE_SDMA) {
 		host->dma_sg_idx++;
 		if (host->dma_sg_idx < host->dma_len) {
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 19/22] OMAP: hsmmc: implement clock switcher
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (17 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 18/22] mmc: omap_hsmmc: fix oops in omap_hsmmc_dma_cb Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 13:34   ` Grazvydas Ignotas
  2011-05-05 11:51 ` [PATCH 20/22] mmc: omap_hsmmc: adjust host controller clock in regard to current OPP Adrian Hunter
                   ` (2 subsequent siblings)
  21 siblings, 1 reply; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Andy Shevchenko,
	Adrian Hunter

From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>

There are 3 new platform data methods which should help us to do a clock
switching when notification is happened or request is started.

The purpose of the patch is to avoid high frequency of MMC controller on low
OPPs due to an HW bug in OMAP 3630.

The algorithm:
 - the PM governor switches the clock of L3 (and therefore L4) bus on demand
 - the MMC controller clock should follow the change

We have considered two OPPs for L3/L4 bus. Thus, we have corresponding flow:
 - OPP1 -> OPP2 (in case of abort - OPP1)
 - OPP2 -> OPP1 (in case of abort - OPP2)

During idle the MMC gates functional clock and we don't care about the
frequency. Most important to get proper solution when notification comes during
request. Then:
 - in case of OPP1 -> OPP2 we update frequency limit and it will be used for
   new coming requests (it assumes the current frequency of the controller is
   lower then new one)
 - otherwise we wait until no device has used higher frequency then upcoming
   one

Known issues and limitations:
 - originally a clock notifier was used for the core L4 iclk but for upstream
   Adrian changed to a cpufreq notifier where we assume OPP1 below 400MHz and
   OPP2 above 400MHz

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 arch/arm/mach-omap2/hsmmc.c           |  180 ++++++++++++++++++++++++++++++++-
 arch/arm/plat-omap/include/plat/mmc.h |    8 ++
 2 files changed, 187 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 6b97fae..34cba89 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -10,10 +10,15 @@
  * published by the Free Software Foundation.
  */
 #include <linux/kernel.h>
+#include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/card.h>
 #include <mach/hardware.h>
+#include <plat/clock.h>
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
 #include <plat/mux.h>
@@ -23,6 +28,8 @@
 #include "hsmmc.h"
 #include "control.h"
 
+#define HSMMC_MAX_FREQ	48000000
+
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
 static u16 control_pbias_offset;
@@ -203,6 +210,155 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on,
 	return 0;
 }
 
+#ifdef CONFIG_ARCH_OMAP3
+static struct hsmmc_max_freq_info {
+	struct device *dev;
+	int freq;
+	int high_speed;
+} hsmmc_max_freq_info[OMAP34XX_NR_MMC];
+
+static unsigned int hsmmc_max_freq = HSMMC_MAX_FREQ;
+static DEFINE_SPINLOCK(hsmmc_max_freq_lock);
+
+static DECLARE_WAIT_QUEUE_HEAD(hsmmc_max_freq_wq);
+
+static int hsmmc_high_speed(struct device *dev)
+{
+	void *drvdata = platform_get_drvdata(to_platform_device(dev));
+	struct mmc_host *mmc = container_of(drvdata, struct mmc_host, private);
+
+	return mmc->card ? mmc_card_highspeed(mmc->card) : 0;
+}
+
+static unsigned int hsmmc_get_max_freq_hs(struct device *dev, int high_speed)
+{
+	return high_speed ? hsmmc_max_freq : hsmmc_max_freq >> 1;
+}
+
+static unsigned int hsmmc_get_max_freq(struct device *dev)
+{
+	return hsmmc_get_max_freq_hs(dev, hsmmc_high_speed(dev));
+}
+
+static unsigned int hsmmc_active(struct device *dev, unsigned int target_freq)
+{
+	int high_speed = hsmmc_high_speed(dev);
+	int i;
+	unsigned int max_freq, freq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsmmc_max_freq_lock, flags);
+	max_freq = hsmmc_get_max_freq_hs(dev, high_speed);
+	freq = min(target_freq, max_freq);
+	for (i = 0; i < ARRAY_SIZE(hsmmc_max_freq_info); i++) {
+		if (!hsmmc_max_freq_info[i].dev) {
+			hsmmc_max_freq_info[i].dev = dev;
+			hsmmc_max_freq_info[i].freq = freq;
+			hsmmc_max_freq_info[i].high_speed = high_speed;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&hsmmc_max_freq_lock, flags);
+	return freq;
+}
+
+static void hsmmc_inactive(struct device *dev)
+{
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsmmc_max_freq_lock, flags);
+	for (i = 0; i < ARRAY_SIZE(hsmmc_max_freq_info); i++) {
+		if (hsmmc_max_freq_info[i].dev == dev) {
+			hsmmc_max_freq_info[i].dev = NULL;
+			spin_unlock_irqrestore(&hsmmc_max_freq_lock, flags);
+			/*
+			 * Wake up the queue only in case we deactivated a
+			 * device.
+			 */
+			wake_up(&hsmmc_max_freq_wq);
+			return;
+		}
+	}
+	spin_unlock_irqrestore(&hsmmc_max_freq_lock, flags);
+}
+
+static bool hsmmc_max_freq_ok(void)
+{
+	int i;
+	bool ret = true;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsmmc_max_freq_lock, flags);
+	for (i = 0; i < ARRAY_SIZE(hsmmc_max_freq_info); i++) {
+		if (hsmmc_max_freq_info[i].dev) {
+			unsigned int max_freq;
+
+			if (hsmmc_max_freq_info[i].high_speed)
+				max_freq = HSMMC_MAX_FREQ >> 1;
+			else
+				max_freq = HSMMC_MAX_FREQ >> 2;
+
+			if (hsmmc_max_freq_info[i].freq > max_freq) {
+				ret = false;
+				break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&hsmmc_max_freq_lock, flags);
+	return ret;
+}
+
+static int hsmmc_clk_notifier(struct notifier_block *nb, unsigned long event,
+			      void *data)
+{
+	struct cpufreq_freqs *freqs = data;
+	unsigned int threshold = 400000; /* between opp1 and opp2 */
+
+	switch (event) {
+	case CPUFREQ_PRECHANGE:
+		if (freqs->new < threshold && freqs->old > threshold) {
+			/* opp2 -> opp1 */
+			hsmmc_max_freq = HSMMC_MAX_FREQ >> 1;
+
+			/* Timeout is 1 sec */
+			if (!wait_event_timeout(hsmmc_max_freq_wq,
+						hsmmc_max_freq_ok(),
+						msecs_to_jiffies(1000)))
+				pr_err("MMC violates maximum frequency "
+				       "constraint\n");
+		}
+		break;
+	case CPUFREQ_POSTCHANGE:
+		if (freqs->old < threshold && freqs->new > threshold) {
+			/* opp1 -> opp2 */
+			hsmmc_max_freq = HSMMC_MAX_FREQ;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block hsmmc_notifier_block = {
+	.notifier_call	= hsmmc_clk_notifier,
+	.priority	= INT_MAX,
+};
+
+static int __init hsmmc_init_notifier(void)
+{
+	return cpufreq_register_notifier(&hsmmc_notifier_block,
+					 CPUFREQ_TRANSITION_NOTIFIER);
+}
+#else
+static inline int hsmmc_init_notifier(void)
+{
+	return 0;
+}
+#endif
+
 static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
 			int controller_nr)
 {
@@ -401,6 +557,17 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 		kfree(hc_name);
 		return -ENODEV;
 	}
+
+	/*
+	 * The 3630's host controller cannot guarantee setup times at all
+	 * frequencies, so notification and control of frequency changes
+	 * is necessary.
+	 */
+	if (cpu_is_omap3630()) {
+		mmc->get_max_freq = hsmmc_get_max_freq;
+		mmc->active = hsmmc_active;
+		mmc->inactive = hsmmc_inactive;
+	}
 	return 0;
 }
 
@@ -507,9 +674,20 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 		omap4_ctrl_pad_writel(reg, control_mmc1);
 	}
 
+	/*
+	 * The 3630's host controller cannot guarantee setup times at all
+	 * frequencies, so notification and control of frequency changes
+	 * is necessary.
+	 */
+	if (cpu_is_omap3630()) {
+		if (hsmmc_init_notifier()) {
+			pr_err("Can't setup clock notifier for mmc driver!\n");
+			return;
+		}
+	}
+
 	for (; controllers->mmc; controllers++)
 		omap_init_hsmmc(controllers, controllers->mmc);
-
 }
 
 #endif
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index f38fef9..e3c9b20 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -27,6 +27,8 @@
 #define OMAP2420_MMC_SIZE	OMAP1_MMC_SIZE
 #define OMAP2_MMC1_BASE		0x4809c000
 
+#define OMAP34XX_NR_MMC		3
+
 #define OMAP4_MMC_REG_OFFSET	0x100
 
 #define OMAP_MMC_MAX_SLOTS	2
@@ -63,6 +65,12 @@ struct omap_mmc_platform_data {
 	/* Return context loss count due to PM states changing */
 	int (*get_context_loss_count)(struct device *dev);
 
+	/* Return max controller frequency for current OPP */
+	unsigned int (*get_max_freq)(struct device *dev);
+
+	unsigned int (*active)(struct device *dev, unsigned int target_freq);
+	void (*inactive)(struct device *dev);
+
 	u64 dma_mask;
 
 	/* Integrating attributes from the omap_hwmod layer */
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 20/22] mmc: omap_hsmmc: adjust host controller clock in regard to current OPP
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (18 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 19/22] OMAP: hsmmc: implement clock switcher Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 21/22] OMAP: hsmmc: add platform data for eMMC hardware reset gpio Adrian Hunter
  2011-05-05 11:51 ` [PATCH 22/22] mmc: omap_hsmmc: add a hardware reset before initialization Adrian Hunter
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Andy Shevchenko,
	Adrian Hunter

From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>

We should like to adjust MMC host controller clock whenever the OPP is changed.
OPP affects to L3/L4 bus frequency. Due to this we update the maximum frequency
limits before each upcoming request and when the divisor is calculated.

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   65 +++++++++++++++++++++++++++++++++++++----
 1 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 2c8fa01..8c5e7d3 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -199,6 +199,9 @@ struct omap_hsmmc_host {
 	int			use_reg;
 	int			req_in_progress;
 
+	/* Actual output frequency of host controller */
+	unsigned int		freq;
+
 	struct	omap_mmc_platform_data	*pdata;
 };
 
@@ -604,13 +607,31 @@ static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
 	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 }
 
+/*
+ * Recalculate desired clock frequency with regard to maximum possible
+ * frequency at current OPP.
+ *
+ * Choose either target frequency (ios->clock) or maximum possible frequency at
+ * current OPP (get_max_freq() returns this limit)
+ */
+static void omap_hsmmc_recalc_freq(struct omap_hsmmc_host *host,
+				   struct mmc_ios *ios)
+{
+	struct omap_mmc_platform_data *pdata = host->pdata;
+
+	if (pdata->get_max_freq)
+		host->freq = min(ios->clock, pdata->get_max_freq(host->dev));
+	else
+		host->freq = ios->clock;
+}
+
 /* Calculate divisor for the given clock frequency */
-static u16 calc_divisor(struct mmc_ios *ios)
+static u16 calc_divisor(struct omap_hsmmc_host *host)
 {
 	u16 dsor = 0;
 
-	if (ios->clock) {
-		dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, ios->clock);
+	if (host->freq) {
+		dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, host->freq);
 		if (dsor > 250)
 			dsor = 250;
 	}
@@ -620,17 +641,16 @@ static u16 calc_divisor(struct mmc_ios *ios)
 
 static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
 {
-	struct mmc_ios *ios = &host->mmc->ios;
 	unsigned long regval;
 	unsigned long timeout;
 
-	dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
+	dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", host->freq);
 
 	omap_hsmmc_stop_clock(host);
 
 	regval = OMAP_HSMMC_READ(host->base, SYSCTL);
 	regval = regval & ~(CLKD_MASK | DTO_MASK);
-	regval = regval | (calc_divisor(ios) << 6) | (DTO << 16);
+	regval = regval | (calc_divisor(host) << 6) | (DTO << 16);
 	OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
 	OMAP_HSMMC_WRITE(host->base, SYSCTL,
 		OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
@@ -754,6 +774,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 
 	omap_hsmmc_set_bus_width(host);
 
+	omap_hsmmc_recalc_freq(host, ios);
 	omap_hsmmc_set_clock(host);
 
 	omap_hsmmc_set_bus_mode(host);
@@ -937,6 +958,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
 	if (mrq->data && host->dma_in_use && dma_ch != -1)
 		return;
 	host->mrq = NULL;
+	if (host->pdata->inactive)
+		host->pdata->inactive(host->dev);
 	mmc_request_done(host->mmc, mrq);
 }
 
@@ -996,6 +1019,9 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd)
 	}
 	if ((host->data == NULL && !host->response_busy) || cmd->error)
 		omap_hsmmc_request_done(host, cmd->mrq);
+	else if (host->data == NULL && host->response_busy &&
+		 host->pdata->inactive)
+		host->pdata->inactive(host->dev);
 }
 
 /*
@@ -1418,6 +1444,8 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
 		struct mmc_request *mrq = host->mrq;
 
 		host->mrq = NULL;
+		if (host->pdata->inactive)
+			host->pdata->inactive(host->dev);
 		mmc_request_done(host->mmc, mrq);
 	}
 }
@@ -1615,6 +1643,26 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
 
 	BUG_ON(host->req_in_progress);
 	BUG_ON(host->dma_ch != -1);
+
+	if (host->pdata->active) {
+		unsigned int new_freq;
+
+		/*
+		 * active() returns minimum of two (target, maximum)
+		 * frequencies.
+		 */
+		new_freq = host->pdata->active(host->dev, mmc->ios.clock);
+
+		/*
+		 * We need to update actual frequency if it is not equal to the
+		 * minimum of two (target and maximum) frequencies
+		 */
+		if (host->freq != new_freq) {
+			host->freq = new_freq;
+			omap_hsmmc_set_clock(host);
+		}
+	}
+
 	if (host->protect_card) {
 		if (host->reqs_blocked < 3) {
 			/*
@@ -1630,6 +1678,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
 		if (req->data)
 			req->data->error = -EBADF;
 		req->cmd->retries = 0;
+		if (host->pdata->inactive)
+			host->pdata->inactive(host->dev);
 		mmc_request_done(mmc, req);
 		return;
 	} else if (host->reqs_blocked)
@@ -1642,6 +1692,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
 		if (req->data)
 			req->data->error = err;
 		host->mrq = NULL;
+		if (host->pdata->inactive)
+			host->pdata->inactive(host->dev);
 		mmc_request_done(mmc, req);
 		return;
 	}
@@ -1698,6 +1750,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		}
 	}
 
+	omap_hsmmc_recalc_freq(host, ios);
 	omap_hsmmc_set_clock(host);
 
 	if (do_send_init_stream)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 21/22] OMAP: hsmmc: add platform data for eMMC hardware reset gpio
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (19 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 20/22] mmc: omap_hsmmc: adjust host controller clock in regard to current OPP Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  2011-05-05 11:51 ` [PATCH 22/22] mmc: omap_hsmmc: add a hardware reset before initialization Adrian Hunter
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter

eMMC may have a hardware reset line connected to a gpio,
so pass it to the driver.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 arch/arm/mach-omap2/hsmmc.c           |    5 +++++
 arch/arm/mach-omap2/hsmmc.h           |    1 +
 arch/arm/plat-omap/include/plat/mmc.h |    1 +
 3 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 34cba89..85f27af 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -472,6 +472,11 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 	mmc->slots[0].switch_pin = c->gpio_cd;
 	mmc->slots[0].gpio_wp = c->gpio_wp;
 
+	if (c->gpio_hw_reset)
+		mmc->slots[0].gpio_hw_reset = c->gpio_hw_reset;
+	else
+		mmc->slots[0].gpio_hw_reset = -EINVAL;
+
 	mmc->slots[0].remux = c->remux;
 	mmc->slots[0].init_card = c->init_card;
 
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index 0f2a87e..b78ed41 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -22,6 +22,7 @@ struct omap2_hsmmc_info {
 	bool    nomux;          /* No default muxing for this slot */
 	int	gpio_cd;	/* or -EINVAL */
 	int	gpio_wp;	/* or -EINVAL */
+	int     gpio_hw_reset;  /* hardware reset */
 	char	*name;		/* or NULL for default */
 	struct device *dev;	/* returned: pointer to mmc adapter */
 	int	ocr_mask;	/* temporary HACK */
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index e3c9b20..9b69b7e 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -119,6 +119,7 @@ struct omap_mmc_platform_data {
 
 		int switch_pin;			/* gpio (card detect) */
 		int gpio_wp;			/* gpio (write protect) */
+		int gpio_hw_reset;              /* gpio (hardware reset) */
 
 		int (*set_bus_mode)(struct device *dev, int slot, int bus_mode);
 		int (*set_power)(struct device *dev, int slot,
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 22/22] mmc: omap_hsmmc: add a hardware reset before initialization
  2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
                   ` (20 preceding siblings ...)
  2011-05-05 11:51 ` [PATCH 21/22] OMAP: hsmmc: add platform data for eMMC hardware reset gpio Adrian Hunter
@ 2011-05-05 11:51 ` Adrian Hunter
  21 siblings, 0 replies; 28+ messages in thread
From: Adrian Hunter @ 2011-05-05 11:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Adrian Hunter

After a warm restart, an eMMC which cannot be powered off is
in an unknown state, so reset it to be sure it will initialize.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   38 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 37 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 8c5e7d3..c791230 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -542,10 +542,25 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
 	} else
 		pdata->slots[0].gpio_wp = -EINVAL;
 
+	if (gpio_is_valid(pdata->slots[0].gpio_hw_reset)) {
+		ret = gpio_request(pdata->slots[0].gpio_hw_reset,
+				   "mmc_hw_reset");
+		if (ret)
+			goto err_free_wp;
+		ret = gpio_direction_output(pdata->slots[0].gpio_hw_reset, 1);
+		if (ret)
+			goto err_free_hw_reset;
+	} else
+		pdata->slots[0].gpio_hw_reset = -EINVAL;
+
 	return 0;
 
+
+err_free_hw_reset:
+	gpio_free(pdata->slots[0].gpio_hw_reset);
 err_free_wp:
-	gpio_free(pdata->slots[0].gpio_wp);
+	if (gpio_is_valid(pdata->slots[0].gpio_wp))
+		gpio_free(pdata->slots[0].gpio_wp);
 err_free_cd:
 	if (gpio_is_valid(pdata->slots[0].switch_pin))
 err_free_sp:
@@ -555,6 +570,8 @@ err_free_sp:
 
 static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
 {
+	if (gpio_is_valid(pdata->slots[0].gpio_hw_reset))
+		gpio_free(pdata->slots[0].gpio_hw_reset);
 	if (gpio_is_valid(pdata->slots[0].gpio_wp))
 		gpio_free(pdata->slots[0].gpio_wp);
 	if (gpio_is_valid(pdata->slots[0].switch_pin))
@@ -815,6 +832,18 @@ static void omap_hsmmc_context_save(struct omap_hsmmc_host *host)
 
 #endif
 
+static void omap_hsmmc_do_hw_reset(struct omap_hsmmc_host *host)
+{
+	if (!gpio_is_valid(mmc_slot(host).gpio_hw_reset))
+		return;
+
+	gpio_set_value_cansleep(mmc_slot(host).gpio_hw_reset, 0);
+	udelay(9);
+	gpio_set_value_cansleep(mmc_slot(host).gpio_hw_reset, 1);
+	usleep_range(1000, 2000);
+	printk(KERN_INFO "%s: hardware reset done\n", mmc_hostname(host->mmc));
+}
+
 /*
  * Send init stream sequence to card
  * before sending IDLE command
@@ -827,6 +856,13 @@ static void send_init_stream(struct omap_hsmmc_host *host)
 	if (host->protect_card)
 		return;
 
+	/*
+	 * After a warm restart, an eMMC which cannot be powered off is in an
+	 * unknown state so reset it to be sure it will initialize.
+	 */
+	if (mmc_slot(host).no_off)
+		omap_hsmmc_do_hw_reset(host);
+
 	disable_irq(host->irq);
 
 	OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 13/22] mmc: omap_hsmmc: fix few bugs when set the clock divisor
  2011-05-05 11:51 ` [PATCH 13/22] mmc: omap_hsmmc: fix few bugs when set the clock divisor Adrian Hunter
@ 2011-05-05 12:53   ` Grazvydas Ignotas
  0 siblings, 0 replies; 28+ messages in thread
From: Grazvydas Ignotas @ 2011-05-05 12:53 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Tony Lindgren, Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Andy Shevchenko

On Thu, May 5, 2011 at 2:51 PM, Adrian Hunter <adrian.hunter@nokia.com> wrote:
> From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
>
> There are two pieces of code which similar, but not the same. Each of them
> contains a bug.
>
> The SYSCTL register should be read before write in the
> omap_hsmmc_context_restore() to remain the state of the reserved bits.
>
> Before set the clock divisor and DTO bits the value from the SYSCTL register
> should be masked properly. We were lucky to have no problems with DTO bits. So,
> make sure we have clear DTO bits properly in the omap_hsmmc_set_ios().
>
> Additionally get rid of msleep(1). The actual time rare higher than 30us on
> OMAP 3630.
>
> The result pieces of code are split to omap_hsmmc_set_clock() function.
>
> Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
> Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
> ---
>  drivers/mmc/host/omap_hsmmc.c |   59 +++++++++++++++++++---------------------
>  1 files changed, 28 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index ae6d204..3c76911 100644
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c
> @@ -619,6 +619,32 @@ static u16 calc_divisor(struct mmc_ios *ios)
>        return dsor;
>  }
>
> +static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
> +{
> +       struct mmc_ios *ios = &host->mmc->ios;
> +       unsigned long regval;
> +       unsigned long timeout;
> +
> +       dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
> +
> +       omap_hsmmc_stop_clock(host);
> +
> +       regval = OMAP_HSMMC_READ(host->base, SYSCTL);
> +       regval = regval & ~(CLKD_MASK | DTO_MASK);
> +       regval = regval | (calc_divisor(ios) << 6) | (DTO << 16);
> +       OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
> +       OMAP_HSMMC_WRITE(host->base, SYSCTL,
> +               OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
> +
> +       /* Wait till the ICS bit is set */
> +       timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
> +       while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
> +               && time_before(jiffies, timeout))
> +               ;

Since you are busywaiting now, cpu_relax() is advisable I guess.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 07/22] mmc: omap_hsmmc: fix missing mmc_release_host() in no_off case
  2011-05-05 11:51 ` [PATCH 07/22] mmc: omap_hsmmc: fix missing mmc_release_host() in no_off case Adrian Hunter
@ 2011-05-05 13:08   ` Sergei Shtylyov
  0 siblings, 0 replies; 28+ messages in thread
From: Sergei Shtylyov @ 2011-05-05 13:08 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Tony Lindgren, linux-mmc Mailing List, Sudhir Bera,
	Madhusudhan Chikkature, linux-omap Mailing List,
	linux-arm Mailing List

Hello.

On 05-05-2011 15:51, Adrian Hunter wrote:

> From: Sudhir Bera <ext-sudhir.bera@nokia.com>

> In fact the no_off check here will not be hit because
> 'omap_hsmmc_disabled_to_sleep()' won't schedule a
> deeper disable in the no_off case.

> Signed-off-by: Sudhir Bera <ext-sudhir.bera@nokia.com>
> Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
> ---
>   drivers/mmc/host/omap_hsmmc.c |    7 +++----
>   1 files changed, 3 insertions(+), 4 deletions(-)

> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index bab25ff..bd52849 100644
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c
> @@ -1852,14 +1852,13 @@ static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host)
>   		return 0;
>
>   	if (mmc_slot(host).no_off)
> -		return 0;
> +		goto out;
>
>   	if (!((host->mmc->caps&  MMC_CAP_NONREMOVABLE) ||
>   	      mmc_slot(host).card_detect ||
>   	      (mmc_slot(host).get_cover_state &&
> 	       mmc_slot(host).get_cover_state(host->dev, host->slot_id)))) {
> -		mmc_release_host(host->mmc);
> -		return 0;
> +		goto out;
>   	}

    This has become a single statement, so {} shpould be removed, no? 
checkpatch.pl probably warns here?..

WBR, Sergei

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 19/22] OMAP: hsmmc: implement clock switcher
  2011-05-05 11:51 ` [PATCH 19/22] OMAP: hsmmc: implement clock switcher Adrian Hunter
@ 2011-05-05 13:34   ` Grazvydas Ignotas
  0 siblings, 0 replies; 28+ messages in thread
From: Grazvydas Ignotas @ 2011-05-05 13:34 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Tony Lindgren, Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Andy Shevchenko

On Thu, May 5, 2011 at 2:51 PM, Adrian Hunter <adrian.hunter@nokia.com> wrote:
> From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
>
> There are 3 new platform data methods which should help us to do a clock
> switching when notification is happened or request is started.
>
> The purpose of the patch is to avoid high frequency of MMC controller on low
> OPPs due to an HW bug in OMAP 3630.
>
> The algorithm:
>  - the PM governor switches the clock of L3 (and therefore L4) bus on demand
>  - the MMC controller clock should follow the change
>
> We have considered two OPPs for L3/L4 bus. Thus, we have corresponding flow:
>  - OPP1 -> OPP2 (in case of abort - OPP1)
>  - OPP2 -> OPP1 (in case of abort - OPP2)
>
> During idle the MMC gates functional clock and we don't care about the
> frequency. Most important to get proper solution when notification comes during
> request. Then:
>  - in case of OPP1 -> OPP2 we update frequency limit and it will be used for
>   new coming requests (it assumes the current frequency of the controller is
>   lower then new one)
>  - otherwise we wait until no device has used higher frequency then upcoming
>   one
>
> Known issues and limitations:
>  - originally a clock notifier was used for the core L4 iclk but for upstream
>   Adrian changed to a cpufreq notifier where we assume OPP1 below 400MHz and
>   OPP2 above 400MHz
>
> Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
> Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
> ---
>  arch/arm/mach-omap2/hsmmc.c           |  180 ++++++++++++++++++++++++++++++++-
>  arch/arm/plat-omap/include/plat/mmc.h |    8 ++
>  2 files changed, 187 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
> index 6b97fae..34cba89 100644
> --- a/arch/arm/mach-omap2/hsmmc.c
> +++ b/arch/arm/mach-omap2/hsmmc.c

<snip>

> +
> +static int hsmmc_clk_notifier(struct notifier_block *nb, unsigned long event,
> +                             void *data)
> +{
> +       struct cpufreq_freqs *freqs = data;
> +       unsigned int threshold = 400000; /* between opp1 and opp2 */
> +
> +       switch (event) {
> +       case CPUFREQ_PRECHANGE:
> +               if (freqs->new < threshold && freqs->old > threshold) {

What if we go from 400000 to, say, 200000?

> +                       /* opp2 -> opp1 */
> +                       hsmmc_max_freq = HSMMC_MAX_FREQ >> 1;
> +
> +                       /* Timeout is 1 sec */
> +                       if (!wait_event_timeout(hsmmc_max_freq_wq,
> +                                               hsmmc_max_freq_ok(),
> +                                               msecs_to_jiffies(1000)))
> +                               pr_err("MMC violates maximum frequency "
> +                                      "constraint\n");
> +               }
> +               break;
> +       case CPUFREQ_POSTCHANGE:
> +               if (freqs->old < threshold && freqs->new > threshold) {

Same here, you could go from 200000 to 400000 and then 600000 and code
would never notice it.

> +                       /* opp1 -> opp2 */
> +                       hsmmc_max_freq = HSMMC_MAX_FREQ;
> +               }
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/22] OMAP: sDMA: descriptor autoloading feature
  2011-05-05 11:51 ` [PATCH 01/22] OMAP: sDMA: descriptor autoloading feature Adrian Hunter
@ 2011-05-06  6:22   ` Tony Lindgren
  0 siblings, 0 replies; 28+ messages in thread
From: Tony Lindgren @ 2011-05-06  6:22 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Madhusudhan Chikkature, linux-omap Mailing List,
	linux-mmc Mailing List, linux-arm Mailing List, Venkatraman S,
	Shilimkar Santosh

Hi,

* Adrian Hunter <adrian.hunter@nokia.com> [110505 14:48]:
> From: Venkatraman S <svenkatr@ti.com>
> 
> Add sDMA driver support for descriptor autoloading feature.
>  Descriptor autoloading is OMAP sDMA v5 hardware capability that can be exploited for scatter gather
>  scenarios, currently available in OMAP3630 and OMAP4430.

I think we should not add this feature until after we've
converted omap DMA to use the common dmaengine for the
basic features.

Adding this will make it harder for us to do the converions.

Can you please separate out the DMA descriptor autoloading
patches?

Regards,

Tony

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 08/22] mmc: omap_hsmmc: correct debug report error status mnemonics
  2011-05-05 11:51 ` [PATCH 08/22] mmc: omap_hsmmc: correct debug report error status mnemonics Adrian Hunter
@ 2011-05-06  8:35   ` S, Venkatraman
  0 siblings, 0 replies; 28+ messages in thread
From: S, Venkatraman @ 2011-05-06  8:35 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Tony Lindgren, linux-omap Mailing List, linux-mmc Mailing List,
	linux-arm Mailing List, Madhusudhan Chikkature

On Thu, May 5, 2011 at 5:21 PM, Adrian Hunter <adrian.hunter@nokia.com> wrote:
> CERR and BADA were in the wrong place and there are only
> 32 not 35.
>
> Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
> ---
>  drivers/mmc/host/omap_hsmmc.c |   19 +++++++++++--------
>  1 files changed, 11 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index bd52849..a1a1101 100644
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c
> @@ -982,14 +982,14 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
>  * Readable error output
>  */
>  #ifdef CONFIG_MMC_DEBUG
> -static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status)
> +static void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, u32 status)
>  {
>        /* --- means reserved bit without definition at documentation */
>        static const char *omap_hsmmc_status_bits[] = {
> -               "CC", "TC", "BGE", "---", "BWR", "BRR", "---", "---", "CIRQ",
> -               "OBI", "---", "---", "---", "---", "---", "ERRI", "CTO", "CCRC",
> -               "CEB", "CIE", "DTO", "DCRC", "DEB", "---", "ACE", "---",
> -               "---", "---", "---", "CERR", "CERR", "BADA", "---", "---", "---"
> +               "CC"  , "TC"  , "BGE", "---", "BWR" , "BRR" , "---" , "---" ,
> +               "CIRQ", "OBI" , "---", "---", "---" , "---" , "---" , "ERRI",
> +               "CTO" , "CCRC", "CEB", "CIE", "DTO" , "DCRC", "DEB" , "---" ,
> +               "ACE" , "---" , "---", "---", "CERR", "BADA", "---" , "---"
>        };
>        char res[256];
>        char *buf = res;
> @@ -1006,6 +1006,11 @@ static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status)
>
>        dev_dbg(mmc_dev(host->mmc), "%s\n", res);
>  }
> +#else
> +static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host,
> +                                            u32 status)
> +{
> +}
>  #endif  /* CONFIG_MMC_DEBUG */
>
>  /*
> @@ -1064,9 +1069,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
>        dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
>
>        if (status & ERR) {
> -#ifdef CONFIG_MMC_DEBUG
> -               omap_hsmmc_report_irq(host, status);
> -#endif
> +               omap_hsmmc_dbg_report_irq(host, status);
>                if ((status & CMD_TIMEOUT) ||
>                        (status & CMD_CRC)) {
>                        if (host->cmd) {
> --
> 1.7.0.4
>
I checked against the TRM and you are right.
FWIW,
 Reviewed-by: Venkatraman S <svenkatr@ti.com>

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2011-05-06  8:35 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter
2011-05-05 11:51 ` [PATCH 01/22] OMAP: sDMA: descriptor autoloading feature Adrian Hunter
2011-05-06  6:22   ` Tony Lindgren
2011-05-05 11:51 ` [PATCH 02/22] OMAP: DMA: add omap_dma_has_sglist() Adrian Hunter
2011-05-05 11:51 ` [PATCH 03/22] OMAP: DMA: Ensure the sglist registers are cleared Adrian Hunter
2011-05-05 11:51 ` [PATCH 04/22] mmc: omap hsmmc: adaptation of sdma descriptor Adrian Hunter
2011-05-05 11:51 ` [PATCH 05/22] mmc: omap_hsmmc: fix dma sglist use Adrian Hunter
2011-05-05 11:51 ` [PATCH 06/22] mmc: omap_hsmmc: limit scatterlist size for sDMA autoloading Adrian Hunter
2011-05-05 11:51 ` [PATCH 07/22] mmc: omap_hsmmc: fix missing mmc_release_host() in no_off case Adrian Hunter
2011-05-05 13:08   ` Sergei Shtylyov
2011-05-05 11:51 ` [PATCH 08/22] mmc: omap_hsmmc: correct debug report error status mnemonics Adrian Hunter
2011-05-06  8:35   ` S, Venkatraman
2011-05-05 11:51 ` [PATCH 09/22] mmc: omap_hsmmc: move hardcoded frequency constants to definition block Adrian Hunter
2011-05-05 11:51 ` [PATCH 10/22] mmc: omap_hsmmc: reduce a bit the error handlers in probe() Adrian Hunter
2011-05-05 11:51 ` [PATCH 11/22] mmc: omap_hsmmc: split duplicate code to calc_divisor() function Adrian Hunter
2011-05-05 11:51 ` [PATCH 12/22] mmc: omap_hsmmc: introduce start_clock and re-use stop_clock Adrian Hunter
2011-05-05 11:51 ` [PATCH 13/22] mmc: omap_hsmmc: fix few bugs when set the clock divisor Adrian Hunter
2011-05-05 12:53   ` Grazvydas Ignotas
2011-05-05 11:51 ` [PATCH 14/22] mmc: omap_hsmmc: split same pieces of code to separate functions Adrian Hunter
2011-05-05 11:51 ` [PATCH 15/22] OMAP: hsmmc: Do not mux the slot if non default muxing is already done Adrian Hunter
2011-05-05 11:51 ` [PATCH 16/22] OMAP: board-rm680: set MMC nomux flag Adrian Hunter
2011-05-05 11:51 ` [PATCH 17/22] mmc: omap_hsmmc: ensure pbias configuration is always done Adrian Hunter
2011-05-05 11:51 ` [PATCH 18/22] mmc: omap_hsmmc: fix oops in omap_hsmmc_dma_cb Adrian Hunter
2011-05-05 11:51 ` [PATCH 19/22] OMAP: hsmmc: implement clock switcher Adrian Hunter
2011-05-05 13:34   ` Grazvydas Ignotas
2011-05-05 11:51 ` [PATCH 20/22] mmc: omap_hsmmc: adjust host controller clock in regard to current OPP Adrian Hunter
2011-05-05 11:51 ` [PATCH 21/22] OMAP: hsmmc: add platform data for eMMC hardware reset gpio Adrian Hunter
2011-05-05 11:51 ` [PATCH 22/22] mmc: omap_hsmmc: add a hardware reset before initialization Adrian Hunter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).