public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring
@ 2011-03-09  7:21 Tomi Valkeinen
  2011-03-09  7:21 ` [PATCH 1/6] OMAP: DSS2: DSI: Restructure IRQ handler Tomi Valkeinen
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Tomi Valkeinen @ 2011-03-09  7:21 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Hi,

In the future we will have more features using the DSI interrupts, like ULPS
handling, and making use-case specific hooks into the main IRQ handler would
become burdensome.

This patch set cleans up the DSI IRQ handling a bit by implementing a generic
way to register/unregister interrupt service routines. This allows us to remove
the use-case specific callbacks from the main IRQ handler.

 Tomi

Tomi Valkeinen (6):
  OMAP: DSS2: DSI: Restructure IRQ handler
  OMAP: DSS2: DSI: Add ISR support
  OMAP: DSS2: DSI: use ISR in send_bta_sync
  OMAP: DSS2: DSI: use ISR for BTA in framedone
  OMAP: DSS2: DSI: catch DSI errors in send_bta_sync
  OMAP: DSS2: DSI: fix IRQ debug prints

 drivers/video/omap2/dss/dsi.c |  523 ++++++++++++++++++++++++++++++++---------
 1 files changed, 408 insertions(+), 115 deletions(-)


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

* [PATCH 1/6] OMAP: DSS2: DSI: Restructure IRQ handler
  2011-03-09  7:21 [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring Tomi Valkeinen
@ 2011-03-09  7:21 ` Tomi Valkeinen
  2011-03-09  7:21 ` [PATCH 2/6] OMAP: DSS2: DSI: Add ISR support Tomi Valkeinen
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Tomi Valkeinen @ 2011-03-09  7:21 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Clean up the IRQ handler a bit by separating collection of IRQ stats and
handling of IRQ errors to separate functions.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |  123 ++++++++++++++++++++++++-----------------
 1 files changed, 73 insertions(+), 50 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index be7694f..a0881da 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -480,26 +480,33 @@ static void print_irq_status_cio(u32 status)
 	printk("\n");
 }
 
-static int debug_irq;
-
-/* called from dss */
-static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+static void dsi_collect_irq_stats(u32 irqstatus, u32 *vcstatus, u32 ciostatus)
 {
-	u32 irqstatus, vcstatus, ciostatus;
 	int i;
 
-	irqstatus = dsi_read_reg(DSI_IRQSTATUS);
-
-	/* IRQ is not for us */
-	if (!irqstatus)
-		return IRQ_NONE;
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
 	spin_lock(&dsi.irq_stats_lock);
+
 	dsi.irq_stats.irq_count++;
 	dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs);
+
+	for (i = 0; i < 4; ++i)
+		dss_collect_irq_stats(vcstatus[i], dsi.irq_stats.vc_irqs[i]);
+
+	dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs);
+
+	spin_unlock(&dsi.irq_stats_lock);
+}
+#else
+#define dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus)
 #endif
 
+static int debug_irq;
+
+static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus)
+{
+	int i;
+
 	if (irqstatus & DSI_IRQ_ERROR_MASK) {
 		DSSERR("DSI error, irqstatus %x\n", irqstatus);
 		print_irq_status(irqstatus);
@@ -510,37 +517,48 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
 		print_irq_status(irqstatus);
 	}
 
-#ifdef DSI_CATCH_MISSING_TE
-	if (irqstatus & DSI_IRQ_TE_TRIGGER)
-		del_timer(&dsi.te_timer);
-#endif
-
 	for (i = 0; i < 4; ++i) {
-		if ((irqstatus & (1<<i)) == 0)
-			continue;
+		if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) {
+			DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
+				       i, vcstatus[i]);
+			print_irq_status_vc(i, vcstatus[i]);
+		} else if (debug_irq) {
+			print_irq_status_vc(i, vcstatus[i]);
+		}
+	}
 
-		vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+	if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
+		DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
+		print_irq_status_cio(ciostatus);
+	} else if (debug_irq) {
+		print_irq_status_cio(ciostatus);
+	}
+}
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-		dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]);
-#endif
+static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
+{
+	u32 irqstatus, vcstatus[4], ciostatus;
+	int i;
 
-		if (vcstatus & DSI_VC_IRQ_BTA) {
-			complete(&dsi.bta_completion);
+	irqstatus = dsi_read_reg(DSI_IRQSTATUS);
 
-			if (dsi.bta_callback)
-				dsi.bta_callback();
-		}
+	/* IRQ is not for us */
+	if (!irqstatus)
+		return IRQ_NONE;
 
-		if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
-			DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
-				       i, vcstatus);
-			print_irq_status_vc(i, vcstatus);
-		} else if (debug_irq) {
-			print_irq_status_vc(i, vcstatus);
+	dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
+	/* flush posted write */
+	dsi_read_reg(DSI_IRQSTATUS);
+
+	for (i = 0; i < 4; ++i) {
+		if ((irqstatus & (1 << i)) == 0) {
+			vcstatus[i] = 0;
+			continue;
 		}
 
-		dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
+		vcstatus[i] = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+
+		dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus[i]);
 		/* flush posted write */
 		dsi_read_reg(DSI_VC_IRQSTATUS(i));
 	}
@@ -548,29 +566,34 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
 	if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
 		ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-		dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs);
-#endif
-
 		dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
 		/* flush posted write */
 		dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
+	} else {
+		ciostatus = 0;
+	}
 
-		if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
-			DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
-			print_irq_status_cio(ciostatus);
-		} else if (debug_irq) {
-			print_irq_status_cio(ciostatus);
+#ifdef DSI_CATCH_MISSING_TE
+	if (irqstatus & DSI_IRQ_TE_TRIGGER)
+		del_timer(&dsi.te_timer);
+#endif
+
+	for (i = 0; i < 4; ++i) {
+		if (vcstatus[i] == 0)
+			continue;
+
+		if (vcstatus[i] & DSI_VC_IRQ_BTA) {
+			complete(&dsi.bta_completion);
+
+			if (dsi.bta_callback)
+				dsi.bta_callback();
 		}
 	}
 
-	dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
-	/* flush posted write */
-	dsi_read_reg(DSI_IRQSTATUS);
+	dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus);
+
+	dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus);
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	spin_unlock(&dsi.irq_stats_lock);
-#endif
 	return IRQ_HANDLED;
 }
 
-- 
1.7.1


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

* [PATCH 2/6] OMAP: DSS2: DSI: Add ISR support
  2011-03-09  7:21 [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring Tomi Valkeinen
  2011-03-09  7:21 ` [PATCH 1/6] OMAP: DSS2: DSI: Restructure IRQ handler Tomi Valkeinen
@ 2011-03-09  7:21 ` Tomi Valkeinen
  2011-03-09  7:21 ` [PATCH 3/6] OMAP: DSS2: DSI: use ISR in send_bta_sync Tomi Valkeinen
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Tomi Valkeinen @ 2011-03-09  7:21 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Add generic ISR support for DSI interrupts. ISRs can be used instead of
custom hooks in the interrupt handler.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |  325 ++++++++++++++++++++++++++++++++++++++---
 1 files changed, 301 insertions(+), 24 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index a0881da..9aea9a7 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -193,6 +193,16 @@ struct dsi_reg { u16 idx; };
 #define REGM_DSI_MAX (1 << 4)
 #define LP_DIV_MAX ((1 << 13) - 1)
 
+typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
+
+#define DSI_MAX_NR_ISRS                2
+
+struct dsi_isr_data {
+	omap_dsi_isr_t	isr;
+	void		*arg;
+	u32		mask;
+};
+
 enum fifo_size {
 	DSI_FIFO_SIZE_0		= 0,
 	DSI_FIFO_SIZE_32	= 1,
@@ -219,6 +229,12 @@ struct dsi_irq_stats {
 	unsigned cio_irqs[32];
 };
 
+struct dsi_isr_tables {
+	struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS];
+	struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS];
+	struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
+};
+
 static struct
 {
 	struct platform_device *pdev;
@@ -244,6 +260,11 @@ static struct
 	struct completion bta_completion;
 	void (*bta_callback)(void);
 
+	spinlock_t irq_lock;
+	struct dsi_isr_tables isr_tables;
+	/* space for a copy used by the interrupt handler */
+	struct dsi_isr_tables isr_tables_copy;
+
 	int update_channel;
 	struct dsi_update_region update_region;
 
@@ -535,11 +556,49 @@ static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus)
 	}
 }
 
+static void dsi_call_isrs(struct dsi_isr_data *isr_array,
+		unsigned isr_array_size, u32 irqstatus)
+{
+	struct dsi_isr_data *isr_data;
+	int i;
+
+	for (i = 0; i < isr_array_size; i++) {
+		isr_data = &isr_array[i];
+		if (isr_data->isr && isr_data->mask & irqstatus)
+			isr_data->isr(isr_data->arg, irqstatus);
+	}
+}
+
+static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables,
+		u32 irqstatus, u32 *vcstatus, u32 ciostatus)
+{
+	int i;
+
+	dsi_call_isrs(isr_tables->isr_table,
+			ARRAY_SIZE(isr_tables->isr_table),
+			irqstatus);
+
+	for (i = 0; i < 4; ++i) {
+		if (vcstatus[i] == 0)
+			continue;
+		dsi_call_isrs(isr_tables->isr_table_vc[i],
+				ARRAY_SIZE(isr_tables->isr_table_vc[i]),
+				vcstatus[i]);
+	}
+
+	if (ciostatus != 0)
+		dsi_call_isrs(isr_tables->isr_table_cio,
+				ARRAY_SIZE(isr_tables->isr_table_cio),
+				ciostatus);
+}
+
 static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
 {
 	u32 irqstatus, vcstatus[4], ciostatus;
 	int i;
 
+	spin_lock(&dsi.irq_lock);
+
 	irqstatus = dsi_read_reg(DSI_IRQSTATUS);
 
 	/* IRQ is not for us */
@@ -590,6 +649,14 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
 		}
 	}
 
+	/* make a copy and unlock, so that isrs can unregister
+	 * themselves */
+	memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables));
+
+	spin_unlock(&dsi.irq_lock);
+
+	dsi_handle_isrs(&dsi.isr_tables_copy, irqstatus, vcstatus, ciostatus);
+
 	dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus);
 
 	dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus);
@@ -597,42 +664,251 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
-static void _dsi_initialize_irq(void)
+/* dsi.irq_lock has to be locked by the caller */
+static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array,
+		unsigned isr_array_size, u32 default_mask,
+		const struct dsi_reg enable_reg,
+		const struct dsi_reg status_reg)
 {
-	u32 l;
+	struct dsi_isr_data *isr_data;
+	u32 mask;
+	u32 old_mask;
 	int i;
 
-	/* disable all interrupts */
-	dsi_write_reg(DSI_IRQENABLE, 0);
-	for (i = 0; i < 4; ++i)
-		dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
-	dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
+	mask = default_mask;
 
-	/* clear interrupt status */
-	l = dsi_read_reg(DSI_IRQSTATUS);
-	dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
+	for (i = 0; i < isr_array_size; i++) {
+		isr_data = &isr_array[i];
 
-	for (i = 0; i < 4; ++i) {
-		l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
-		dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
+		if (isr_data->isr == NULL)
+			continue;
+
+		mask |= isr_data->mask;
 	}
 
-	l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
-	dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
+	old_mask = dsi_read_reg(enable_reg);
+	/* clear the irqstatus for newly enabled irqs */
+	dsi_write_reg(status_reg, (mask ^ old_mask) & mask);
+	dsi_write_reg(enable_reg, mask);
+
+	/* flush posted writes */
+	dsi_read_reg(enable_reg);
+	dsi_read_reg(status_reg);
+}
 
-	/* enable error irqs */
-	l = DSI_IRQ_ERROR_MASK;
+/* dsi.irq_lock has to be locked by the caller */
+static void _omap_dsi_set_irqs(void)
+{
+	u32 mask = DSI_IRQ_ERROR_MASK;
 #ifdef DSI_CATCH_MISSING_TE
-	l |= DSI_IRQ_TE_TRIGGER;
+	mask |= DSI_IRQ_TE_TRIGGER;
 #endif
-	dsi_write_reg(DSI_IRQENABLE, l);
+	_omap_dsi_configure_irqs(dsi.isr_tables.isr_table,
+			ARRAY_SIZE(dsi.isr_tables.isr_table), mask,
+			DSI_IRQENABLE, DSI_IRQSTATUS);
+}
 
-	l = DSI_VC_IRQ_ERROR_MASK;
-	for (i = 0; i < 4; ++i)
-		dsi_write_reg(DSI_VC_IRQENABLE(i), l);
+/* dsi.irq_lock has to be locked by the caller */
+static void _omap_dsi_set_irqs_vc(int vc)
+{
+	_omap_dsi_configure_irqs(dsi.isr_tables.isr_table_vc[vc],
+			ARRAY_SIZE(dsi.isr_tables.isr_table_vc[vc]),
+			DSI_VC_IRQ_ERROR_MASK,
+			DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc));
+}
+
+/* dsi.irq_lock has to be locked by the caller */
+static void _omap_dsi_set_irqs_cio(void)
+{
+	_omap_dsi_configure_irqs(dsi.isr_tables.isr_table_cio,
+			ARRAY_SIZE(dsi.isr_tables.isr_table_cio),
+			DSI_CIO_IRQ_ERROR_MASK,
+			DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS);
+}
+
+static void _dsi_initialize_irq(void)
+{
+	unsigned long flags;
+	int vc;
+
+	spin_lock_irqsave(&dsi.irq_lock, flags);
+
+	memset(&dsi.isr_tables, 0, sizeof(dsi.isr_tables));
+
+	_omap_dsi_set_irqs();
+	for (vc = 0; vc < 4; ++vc)
+		_omap_dsi_set_irqs_vc(vc);
+	_omap_dsi_set_irqs_cio();
+
+	spin_unlock_irqrestore(&dsi.irq_lock, flags);
+}
+
+static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
+		struct dsi_isr_data *isr_array, unsigned isr_array_size)
+{
+	struct dsi_isr_data *isr_data;
+	int free_idx;
+	int i;
+
+	BUG_ON(isr == NULL);
+
+	/* check for duplicate entry and find a free slot */
+	free_idx = -1;
+	for (i = 0; i < isr_array_size; i++) {
+		isr_data = &isr_array[i];
+
+		if (isr_data->isr == isr && isr_data->arg == arg &&
+				isr_data->mask == mask) {
+			return -EINVAL;
+		}
+
+		if (isr_data->isr == NULL && free_idx == -1)
+			free_idx = i;
+	}
+
+	if (free_idx == -1)
+		return -EBUSY;
+
+	isr_data = &isr_array[free_idx];
+	isr_data->isr = isr;
+	isr_data->arg = arg;
+	isr_data->mask = mask;
+
+	return 0;
+}
+
+static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
+		struct dsi_isr_data *isr_array, unsigned isr_array_size)
+{
+	struct dsi_isr_data *isr_data;
+	int i;
+
+	for (i = 0; i < isr_array_size; i++) {
+		isr_data = &isr_array[i];
+		if (isr_data->isr != isr || isr_data->arg != arg ||
+				isr_data->mask != mask)
+			continue;
+
+		isr_data->isr = NULL;
+		isr_data->arg = NULL;
+		isr_data->mask = 0;
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi.irq_lock, flags);
+
+	r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table,
+			ARRAY_SIZE(dsi.isr_tables.isr_table));
+
+	if (r == 0)
+		_omap_dsi_set_irqs();
+
+	spin_unlock_irqrestore(&dsi.irq_lock, flags);
+
+	return r;
+}
+
+static int dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi.irq_lock, flags);
+
+	r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table,
+			ARRAY_SIZE(dsi.isr_tables.isr_table));
+
+	if (r == 0)
+		_omap_dsi_set_irqs();
+
+	spin_unlock_irqrestore(&dsi.irq_lock, flags);
+
+	return r;
+}
+
+static int dsi_register_isr_vc(int channel, omap_dsi_isr_t isr, void *arg,
+		u32 mask)
+{
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi.irq_lock, flags);
+
+	r = _dsi_register_isr(isr, arg, mask,
+			dsi.isr_tables.isr_table_vc[channel],
+			ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel]));
+
+	if (r == 0)
+		_omap_dsi_set_irqs_vc(channel);
 
-	l = DSI_CIO_IRQ_ERROR_MASK;
-	dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l);
+	spin_unlock_irqrestore(&dsi.irq_lock, flags);
+
+	return r;
+}
+
+static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg,
+		u32 mask)
+{
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi.irq_lock, flags);
+
+	r = _dsi_unregister_isr(isr, arg, mask,
+			dsi.isr_tables.isr_table_vc[channel],
+			ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel]));
+
+	if (r == 0)
+		_omap_dsi_set_irqs_vc(channel);
+
+	spin_unlock_irqrestore(&dsi.irq_lock, flags);
+
+	return r;
+}
+
+static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi.irq_lock, flags);
+
+	r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio,
+			ARRAY_SIZE(dsi.isr_tables.isr_table_cio));
+
+	if (r == 0)
+		_omap_dsi_set_irqs_cio();
+
+	spin_unlock_irqrestore(&dsi.irq_lock, flags);
+
+	return r;
+}
+
+static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi.irq_lock, flags);
+
+	r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio,
+			ARRAY_SIZE(dsi.isr_tables.isr_table_cio));
+
+	if (r == 0)
+		_omap_dsi_set_irqs_cio();
+
+	spin_unlock_irqrestore(&dsi.irq_lock, flags);
+
+	return r;
 }
 
 static u32 dsi_get_errors(void)
@@ -3362,6 +3638,7 @@ static int dsi_init(struct platform_device *pdev)
 	int r, i;
 	struct resource *dsi_mem;
 
+	spin_lock_init(&dsi.irq_lock);
 	spin_lock_init(&dsi.errors_lock);
 	dsi.errors = 0;
 
-- 
1.7.1


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

* [PATCH 3/6] OMAP: DSS2: DSI: use ISR in send_bta_sync
  2011-03-09  7:21 [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring Tomi Valkeinen
  2011-03-09  7:21 ` [PATCH 1/6] OMAP: DSS2: DSI: Restructure IRQ handler Tomi Valkeinen
  2011-03-09  7:21 ` [PATCH 2/6] OMAP: DSS2: DSI: Add ISR support Tomi Valkeinen
@ 2011-03-09  7:21 ` Tomi Valkeinen
  2011-03-09  7:21 ` [PATCH 4/6] OMAP: DSS2: DSI: use ISR for BTA in framedone Tomi Valkeinen
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Tomi Valkeinen @ 2011-03-09  7:21 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Remove bta_completion handling from the interrupt handler, and use ISR
support instead.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   32 ++++++++++++++++++--------------
 1 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 9aea9a7..a4d47dd 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -257,7 +257,6 @@ static struct
 
 	unsigned pll_locked;
 
-	struct completion bta_completion;
 	void (*bta_callback)(void);
 
 	spinlock_t irq_lock;
@@ -341,6 +340,11 @@ static bool dsi_bus_is_locked(void)
 	return dsi.bus_lock.count == 0;
 }
 
+static void dsi_completion_handler(void *data, u32 mask)
+{
+	complete((struct completion *)data);
+}
+
 static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
 		int value)
 {
@@ -642,8 +646,6 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
 			continue;
 
 		if (vcstatus[i] & DSI_VC_IRQ_BTA) {
-			complete(&dsi.bta_completion);
-
 			if (dsi.bta_callback)
 				dsi.bta_callback();
 		}
@@ -2251,33 +2253,37 @@ static int dsi_vc_send_bta(int channel)
 
 int dsi_vc_send_bta_sync(int channel)
 {
+	DECLARE_COMPLETION_ONSTACK(completion);
 	int r = 0;
 	u32 err;
 
-	INIT_COMPLETION(dsi.bta_completion);
-
-	dsi_vc_enable_bta_irq(channel);
+	r = dsi_register_isr_vc(channel, dsi_completion_handler,
+			&completion, DSI_VC_IRQ_BTA);
+	if (r)
+		goto err0;
 
 	r = dsi_vc_send_bta(channel);
 	if (r)
-		goto err;
+		goto err1;
 
-	if (wait_for_completion_timeout(&dsi.bta_completion,
+	if (wait_for_completion_timeout(&completion,
 				msecs_to_jiffies(500)) == 0) {
 		DSSERR("Failed to receive BTA\n");
 		r = -EIO;
-		goto err;
+		goto err1;
 	}
 
 	err = dsi_get_errors();
 	if (err) {
 		DSSERR("Error while sending BTA: %x\n", err);
 		r = -EIO;
-		goto err;
+		goto err1;
 	}
-err:
-	dsi_vc_disable_bta_irq(channel);
 
+err1:
+	dsi_unregister_isr_vc(channel, dsi_completion_handler,
+			&completion, DSI_VC_IRQ_BTA);
+err0:
 	return r;
 }
 EXPORT_SYMBOL(dsi_vc_send_bta_sync);
@@ -3647,8 +3653,6 @@ static int dsi_init(struct platform_device *pdev)
 	dsi.irq_stats.last_reset = jiffies;
 #endif
 
-	init_completion(&dsi.bta_completion);
-
 	mutex_init(&dsi.lock);
 	sema_init(&dsi.bus_lock, 1);
 
-- 
1.7.1


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

* [PATCH 4/6] OMAP: DSS2: DSI: use ISR for BTA in framedone
  2011-03-09  7:21 [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring Tomi Valkeinen
                   ` (2 preceding siblings ...)
  2011-03-09  7:21 ` [PATCH 3/6] OMAP: DSS2: DSI: use ISR in send_bta_sync Tomi Valkeinen
@ 2011-03-09  7:21 ` Tomi Valkeinen
  2011-03-09  7:21 ` [PATCH 5/6] OMAP: DSS2: DSI: catch DSI errors in send_bta_sync Tomi Valkeinen
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Tomi Valkeinen @ 2011-03-09  7:21 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Remove bta_callback from the interrupt handler, and use ISR support
instead.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   57 +++++++++++------------------------------
 1 files changed, 15 insertions(+), 42 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index a4d47dd..5672e40 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -257,8 +257,6 @@ static struct
 
 	unsigned pll_locked;
 
-	void (*bta_callback)(void);
-
 	spinlock_t irq_lock;
 	struct dsi_isr_tables isr_tables;
 	/* space for a copy used by the interrupt handler */
@@ -641,16 +639,6 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
 		del_timer(&dsi.te_timer);
 #endif
 
-	for (i = 0; i < 4; ++i) {
-		if (vcstatus[i] == 0)
-			continue;
-
-		if (vcstatus[i] & DSI_VC_IRQ_BTA) {
-			if (dsi.bta_callback)
-				dsi.bta_callback();
-		}
-	}
-
 	/* make a copy and unlock, so that isrs can unregister
 	 * themselves */
 	memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables));
@@ -924,26 +912,6 @@ static u32 dsi_get_errors(void)
 	return e;
 }
 
-static void dsi_vc_enable_bta_irq(int channel)
-{
-	u32 l;
-
-	dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
-
-	l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
-	l |= DSI_VC_IRQ_BTA;
-	dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
-}
-
-static void dsi_vc_disable_bta_irq(int channel)
-{
-	u32 l;
-
-	l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
-	l &= ~DSI_VC_IRQ_BTA;
-	dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
-}
-
 /* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
 static inline void enable_clocks(bool enable)
 {
@@ -3097,19 +3065,20 @@ static void dsi_te_timeout(unsigned long arg)
 }
 #endif
 
+static void dsi_framedone_bta_callback(void *data, u32 mask);
+
 static void dsi_handle_framedone(int error)
 {
 	const int channel = dsi.update_channel;
 
-	cancel_delayed_work(&dsi.framedone_timeout_work);
+	dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
+			NULL, DSI_VC_IRQ_BTA);
 
-	dsi_vc_disable_bta_irq(channel);
+	cancel_delayed_work(&dsi.framedone_timeout_work);
 
 	/* SIDLEMODE back to smart-idle */
 	dispc_enable_sidle();
 
-	dsi.bta_callback = NULL;
-
 	if (dsi.te_enabled) {
 		/* enable LP_RX_TO again after the TE */
 		REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
@@ -3143,7 +3112,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
 	dsi_handle_framedone(-ETIMEDOUT);
 }
 
-static void dsi_framedone_bta_callback(void)
+static void dsi_framedone_bta_callback(void *data, u32 mask)
 {
 	dsi_handle_framedone(0);
 
@@ -3183,15 +3152,19 @@ static void dsi_framedone_irq_callback(void *data, u32 mask)
 	 * asynchronously.
 	 * */
 
-	dsi.bta_callback = dsi_framedone_bta_callback;
-
-	barrier();
-
-	dsi_vc_enable_bta_irq(channel);
+	r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback,
+			NULL, DSI_VC_IRQ_BTA);
+	if (r) {
+		DSSERR("Failed to register BTA ISR\n");
+		dsi_handle_framedone(-EIO);
+		return;
+	}
 
 	r = dsi_vc_send_bta(channel);
 	if (r) {
 		DSSERR("BTA after framedone failed\n");
+		dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
+				NULL, DSI_VC_IRQ_BTA);
 		dsi_handle_framedone(-EIO);
 	}
 }
-- 
1.7.1


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

* [PATCH 5/6] OMAP: DSS2: DSI: catch DSI errors in send_bta_sync
  2011-03-09  7:21 [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring Tomi Valkeinen
                   ` (3 preceding siblings ...)
  2011-03-09  7:21 ` [PATCH 4/6] OMAP: DSS2: DSI: use ISR for BTA in framedone Tomi Valkeinen
@ 2011-03-09  7:21 ` Tomi Valkeinen
  2011-03-09  7:21 ` [PATCH 6/6] OMAP: DSS2: DSI: fix IRQ debug prints Tomi Valkeinen
  2011-03-09 13:54 ` [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring archit taneja
  6 siblings, 0 replies; 9+ messages in thread
From: Tomi Valkeinen @ 2011-03-09  7:21 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

dsi_vc_send_bta_sync() waits for BTA interrupt with a 500ms timeout. If
a DSI error happens, no BTA is received and the timeout triggers. This
could be handled much faster by listening to DSI errors also.

This patch uses the ISR support to notice DSI errors while waiting for
the BTA, thus speeding up the fail-path considerably.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 5672e40..ec5b879 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -2230,24 +2230,31 @@ int dsi_vc_send_bta_sync(int channel)
 	if (r)
 		goto err0;
 
-	r = dsi_vc_send_bta(channel);
+	r = dsi_register_isr(dsi_completion_handler, &completion,
+			DSI_IRQ_ERROR_MASK);
 	if (r)
 		goto err1;
 
+	r = dsi_vc_send_bta(channel);
+	if (r)
+		goto err2;
+
 	if (wait_for_completion_timeout(&completion,
 				msecs_to_jiffies(500)) == 0) {
 		DSSERR("Failed to receive BTA\n");
 		r = -EIO;
-		goto err1;
+		goto err2;
 	}
 
 	err = dsi_get_errors();
 	if (err) {
 		DSSERR("Error while sending BTA: %x\n", err);
 		r = -EIO;
-		goto err1;
+		goto err2;
 	}
-
+err2:
+	dsi_unregister_isr(dsi_completion_handler, &completion,
+			DSI_IRQ_ERROR_MASK);
 err1:
 	dsi_unregister_isr_vc(channel, dsi_completion_handler,
 			&completion, DSI_VC_IRQ_BTA);
-- 
1.7.1


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

* [PATCH 6/6] OMAP: DSS2: DSI: fix IRQ debug prints
  2011-03-09  7:21 [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring Tomi Valkeinen
                   ` (4 preceding siblings ...)
  2011-03-09  7:21 ` [PATCH 5/6] OMAP: DSS2: DSI: catch DSI errors in send_bta_sync Tomi Valkeinen
@ 2011-03-09  7:21 ` Tomi Valkeinen
  2011-03-09 13:54 ` [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring archit taneja
  6 siblings, 0 replies; 9+ messages in thread
From: Tomi Valkeinen @ 2011-03-09  7:21 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

print_irq_status functions can be called with empty irq status when full
irq debugging is enabled. This patch makes print_irq_status functions
return immediately when given an empty irq status to lessen the debug
spam slightly.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index ec5b879..f6733b5 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -412,6 +412,9 @@ static void dsi_perf_show(const char *name)
 
 static void print_irq_status(u32 status)
 {
+	if (status == 0)
+		return;
+
 #ifndef VERBOSE_IRQ
 	if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
 		return;
@@ -447,6 +450,9 @@ static void print_irq_status(u32 status)
 
 static void print_irq_status_vc(int channel, u32 status)
 {
+	if (status == 0)
+		return;
+
 #ifndef VERBOSE_IRQ
 	if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
 		return;
@@ -473,6 +479,9 @@ static void print_irq_status_vc(int channel, u32 status)
 
 static void print_irq_status_cio(u32 status)
 {
+	if (status == 0)
+		return;
+
 	printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
 
 #define PIS(x) \
-- 
1.7.1


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

* Re: [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring
  2011-03-09  7:21 [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring Tomi Valkeinen
                   ` (5 preceding siblings ...)
  2011-03-09  7:21 ` [PATCH 6/6] OMAP: DSS2: DSI: fix IRQ debug prints Tomi Valkeinen
@ 2011-03-09 13:54 ` archit taneja
  2011-03-09 14:45   ` Tomi Valkeinen
  6 siblings, 1 reply; 9+ messages in thread
From: archit taneja @ 2011-03-09 13:54 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: linux-omap@vger.kernel.org, linux-fbdev@vger.kernel.org

On Wednesday 09 March 2011 12:51 PM, Valkeinen, Tomi wrote:
> Hi,
>
> In the future we will have more features using the DSI interrupts, like ULPS
> handling, and making use-case specific hooks into the main IRQ handler would
> become burdensome.
>
> This patch set cleans up the DSI IRQ handling a bit by implementing a generic
> way to register/unregister interrupt service routines. This allows us to remove
> the use-case specific callbacks from the main IRQ handler.
>

Would this make it more easy/difficult to migrate to irq_chip(if needed) 
later on? I guess it will atleast bring dispc and dsi irq 
requesting/handling in a similar state, hence the changes needed to move 
to irq_chip would be the same for both.

Archit

>   Tomi
>
> Tomi Valkeinen (6):
>    OMAP: DSS2: DSI: Restructure IRQ handler
>    OMAP: DSS2: DSI: Add ISR support
>    OMAP: DSS2: DSI: use ISR in send_bta_sync
>    OMAP: DSS2: DSI: use ISR for BTA in framedone
>    OMAP: DSS2: DSI: catch DSI errors in send_bta_sync
>    OMAP: DSS2: DSI: fix IRQ debug prints
>
>   drivers/video/omap2/dss/dsi.c |  523 ++++++++++++++++++++++++++++++++---------
>   1 files changed, 408 insertions(+), 115 deletions(-)
>
> --
> 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] 9+ messages in thread

* Re: [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring
  2011-03-09 13:54 ` [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring archit taneja
@ 2011-03-09 14:45   ` Tomi Valkeinen
  0 siblings, 0 replies; 9+ messages in thread
From: Tomi Valkeinen @ 2011-03-09 14:45 UTC (permalink / raw)
  To: Taneja, Archit; +Cc: linux-omap@vger.kernel.org, linux-fbdev@vger.kernel.org

On Wed, 2011-03-09 at 07:54 -0600, Taneja, Archit wrote:
> On Wednesday 09 March 2011 12:51 PM, Valkeinen, Tomi wrote:
> > Hi,
> >
> > In the future we will have more features using the DSI interrupts, like ULPS
> > handling, and making use-case specific hooks into the main IRQ handler would
> > become burdensome.
> >
> > This patch set cleans up the DSI IRQ handling a bit by implementing a generic
> > way to register/unregister interrupt service routines. This allows us to remove
> > the use-case specific callbacks from the main IRQ handler.
> >
> 
> Would this make it more easy/difficult to migrate to irq_chip(if needed) 
> later on? I guess it will atleast bring dispc and dsi irq 
> requesting/handling in a similar state, hence the changes needed to move 
> to irq_chip would be the same for both.

Well, I'm not really familiar with irq_chip, but I don't see how this
could make it more difficult. It divides the code in cleaner way,
removing irq specific callbacks in the irq handler, so it should make
migrating easier, if anything.

 Tomi



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

end of thread, other threads:[~2011-03-09 14:45 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-09  7:21 [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring Tomi Valkeinen
2011-03-09  7:21 ` [PATCH 1/6] OMAP: DSS2: DSI: Restructure IRQ handler Tomi Valkeinen
2011-03-09  7:21 ` [PATCH 2/6] OMAP: DSS2: DSI: Add ISR support Tomi Valkeinen
2011-03-09  7:21 ` [PATCH 3/6] OMAP: DSS2: DSI: use ISR in send_bta_sync Tomi Valkeinen
2011-03-09  7:21 ` [PATCH 4/6] OMAP: DSS2: DSI: use ISR for BTA in framedone Tomi Valkeinen
2011-03-09  7:21 ` [PATCH 5/6] OMAP: DSS2: DSI: catch DSI errors in send_bta_sync Tomi Valkeinen
2011-03-09  7:21 ` [PATCH 6/6] OMAP: DSS2: DSI: fix IRQ debug prints Tomi Valkeinen
2011-03-09 13:54 ` [PATCH 0/6] OMAP: DSS2: DSI: IRQ restructuring archit taneja
2011-03-09 14:45   ` Tomi Valkeinen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox