Commit 755cbfd8 authored by Tony Lindgren's avatar Tony Lindgren
Browse files

ARM: OMAP2+: Drop sdma interrupt handling for mach-omap2



All device tree probing omap SoCs only have device drivers that are using
Linux dmaengine API with the IRQENABLE_L1 interrupts. Only omap1 is still
using old legacy dma.

This means we can remove the legacy sdma interrupt handling for
IRQENABLE_L0, and only rely on the dmaengine driver using IRQENABLE_L1.

The legacy code still allocates the channels, but that will be deal with
in the following patches.

Cc: Aaro Koskinen <aaro.koskinen@iki.fi>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
Cc: Vinod Koul <vkoul@kernel.org>
Acked-by: default avatarPeter Ujfalusi <peter.ujfalusi@ti.com>
Tested-by: default avatarPeter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 28b5afcd
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -272,9 +272,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
		d->dev_caps |= HS_CHANNELS_RESERVED;

	if (platform_get_irq_byname(pdev, "0") < 0)
		d->dev_caps |= DMA_ENGINE_HANDLE_IRQ;

	/* Check the capabilities register for descriptor loading feature */
	if (dma_read(CAPS_0, 0) & DMA_HAS_DESCRIPTOR_CAPS)
		dma_common_ch_end = CCDN;
+8 −237
Original line number Diff line number Diff line
@@ -88,22 +88,6 @@ struct dma_link_info {

};

static struct dma_link_info *dma_linked_lch;

#ifndef CONFIG_ARCH_OMAP1

/* Chain handling macros */
#define OMAP_DMA_CHAIN_QEMPTY(chain_id)					\
		(0 == dma_linked_lch[chain_id].q_count)
#define __OMAP_DMA_CHAIN_INCQ(end)					\
	((end) = ((end)+1) % dma_linked_lch[chain_id].no_of_lchs_linked)
#define OMAP_DMA_CHAIN_INCQHEAD(chain_id)				\
	do {								\
		__OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_head);	\
		dma_linked_lch[chain_id].q_count--;			\
	} while (0)
#endif

static int dma_lch_count;
static int dma_chan_count;
static int omap_dma_reserve_channels;
@@ -469,12 +453,6 @@ static inline void enable_lnk(int lch)
	if (dma_chan[lch].next_lch != -1)
		l = dma_chan[lch].next_lch | (1 << 15);

#ifndef CONFIG_ARCH_OMAP1
	if (dma_omap2plus())
		if (dma_chan[lch].next_linked_ch != -1)
			l = dma_chan[lch].next_linked_ch | (1 << 15);
#endif

	p->dma_write(l, CLNK_CTRL, lch);
}

@@ -501,42 +479,6 @@ static inline void disable_lnk(int lch)
	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
}

static inline void omap2_enable_irq_lch(int lch)
{
	u32 val;
	unsigned long flags;

	if (dma_omap1())
		return;

	spin_lock_irqsave(&dma_chan_lock, flags);
	/* clear IRQ STATUS */
	p->dma_write(1 << lch, IRQSTATUS_L0, lch);
	/* Enable interrupt */
	val = p->dma_read(IRQENABLE_L0, lch);
	val |= 1 << lch;
	p->dma_write(val, IRQENABLE_L0, lch);
	spin_unlock_irqrestore(&dma_chan_lock, flags);
}

static inline void omap2_disable_irq_lch(int lch)
{
	u32 val;
	unsigned long flags;

	if (dma_omap1())
		return;

	spin_lock_irqsave(&dma_chan_lock, flags);
	/* Disable interrupt */
	val = p->dma_read(IRQENABLE_L0, lch);
	val &= ~(1 << lch);
	p->dma_write(val, IRQENABLE_L0, lch);
	/* clear IRQ STATUS */
	p->dma_write(1 << lch, IRQSTATUS_L0, lch);
	spin_unlock_irqrestore(&dma_chan_lock, flags);
}

int omap_request_dma(int dev_id, const char *dev_name,
		     void (*callback)(int lch, u16 ch_status, void *data),
		     void *data, int *dma_ch_out)
@@ -565,9 +507,6 @@ int omap_request_dma(int dev_id, const char *dev_name,
	if (p->clear_lch_regs)
		p->clear_lch_regs(free_ch);

	if (dma_omap2plus())
		omap_clear_dma(free_ch);

	spin_unlock_irqrestore(&dma_chan_lock, flags);

	chan->dev_name = dev_name;
@@ -575,20 +514,10 @@ int omap_request_dma(int dev_id, const char *dev_name,
	chan->data = data;
	chan->flags = 0;

#ifndef CONFIG_ARCH_OMAP1
	if (dma_omap2plus()) {
		chan->chain_id = -1;
		chan->next_linked_ch = -1;
	}
#endif

	chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;

	if (dma_omap1())
		chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ;
	else if (dma_omap2plus())
		chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ |
			OMAP2_DMA_TRANS_ERR_IRQ;

	if (dma_omap16xx()) {
		/* If the sync device is set, configure it dynamically. */
@@ -605,11 +534,6 @@ int omap_request_dma(int dev_id, const char *dev_name,
		p->dma_write(dev_id, CCR, free_ch);
	}

	if (dma_omap2plus()) {
		omap_enable_channel_irq(free_ch);
		omap2_enable_irq_lch(free_ch);
	}

	*dma_ch_out = free_ch;

	return 0;
@@ -626,20 +550,12 @@ void omap_free_dma(int lch)
		return;
	}

	/* Disable interrupt for logical channel */
	if (dma_omap2plus())
		omap2_disable_irq_lch(lch);

	/* Disable all DMA interrupts for the channel. */
	omap_disable_channel_irq(lch);

	/* Make sure the DMA transfer is stopped. */
	p->dma_write(0, CCR, lch);

	/* Clear registers */
	if (dma_omap2plus())
		omap_clear_dma(lch);

	spin_lock_irqsave(&dma_chan_lock, flags);
	dma_chan[lch].dev_id = -1;
	dma_chan[lch].next_lch = -1;
@@ -989,109 +905,6 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
#define omap1_dma_irq_handler	NULL
#endif

#ifdef CONFIG_ARCH_OMAP2PLUS

static int omap2_dma_handle_ch(int ch)
{
	u32 status = p->dma_read(CSR, ch);

	if (!status) {
		if (printk_ratelimit())
			pr_warn("Spurious DMA IRQ for lch %d\n", ch);
		p->dma_write(1 << ch, IRQSTATUS_L0, ch);
		return 0;
	}
	if (unlikely(dma_chan[ch].dev_id == -1)) {
		if (printk_ratelimit())
			pr_warn("IRQ %04x for non-allocated DMA channel %d\n",
				status, ch);
		return 0;
	}
	if (unlikely(status & OMAP_DMA_DROP_IRQ))
		pr_info("DMA synchronization event drop occurred with device %d\n",
			dma_chan[ch].dev_id);
	if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
		printk(KERN_INFO "DMA transaction error with device %d\n",
		       dma_chan[ch].dev_id);
		if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
			u32 ccr;

			ccr = p->dma_read(CCR, ch);
			ccr &= ~OMAP_DMA_CCR_EN;
			p->dma_write(ccr, CCR, ch);
			dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
		}
	}
	if (unlikely(status & OMAP2_DMA_SECURE_ERR_IRQ))
		printk(KERN_INFO "DMA secure error with device %d\n",
		       dma_chan[ch].dev_id);
	if (unlikely(status & OMAP2_DMA_MISALIGNED_ERR_IRQ))
		printk(KERN_INFO "DMA misaligned error with device %d\n",
		       dma_chan[ch].dev_id);

	p->dma_write(status, CSR, ch);
	p->dma_write(1 << ch, IRQSTATUS_L0, ch);
	/* read back the register to flush the write */
	p->dma_read(IRQSTATUS_L0, ch);

	/* If the ch is not chained then chain_id will be -1 */
	if (dma_chan[ch].chain_id != -1) {
		int chain_id = dma_chan[ch].chain_id;
		dma_chan[ch].state = DMA_CH_NOTSTARTED;
		if (p->dma_read(CLNK_CTRL, ch) & (1 << 15))
			dma_chan[dma_chan[ch].next_linked_ch].state =
							DMA_CH_STARTED;
		if (dma_linked_lch[chain_id].chain_mode ==
						OMAP_DMA_DYNAMIC_CHAIN)
			disable_lnk(ch);

		if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
			OMAP_DMA_CHAIN_INCQHEAD(chain_id);

		status = p->dma_read(CSR, ch);
		p->dma_write(status, CSR, ch);
	}

	if (likely(dma_chan[ch].callback != NULL))
		dma_chan[ch].callback(ch, status, dma_chan[ch].data);

	return 0;
}

/* STATUS register count is from 1-32 while our is 0-31 */
static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
{
	u32 val, enable_reg;
	int i;

	val = p->dma_read(IRQSTATUS_L0, 0);
	if (val == 0) {
		if (printk_ratelimit())
			printk(KERN_WARNING "Spurious DMA IRQ\n");
		return IRQ_HANDLED;
	}
	enable_reg = p->dma_read(IRQENABLE_L0, 0);
	val &= enable_reg; /* Dispatch only relevant interrupts */
	for (i = 0; i < dma_lch_count && val != 0; i++) {
		if (val & 1)
			omap2_dma_handle_ch(i);
		val >>= 1;
	}

	return IRQ_HANDLED;
}

static struct irqaction omap24xx_dma_irq = {
	.name = "DMA",
	.handler = omap2_dma_irq_handler,
};

#else
static struct irqaction omap24xx_dma_irq;
#endif

/*----------------------------------------------------------------------------*/

/*
 * Note that we are currently using only IRQENABLE_L0 and L1.
 * As the DSP may be using IRQENABLE_L2 and L3, let's not
@@ -1139,7 +952,6 @@ static int omap_system_dma_probe(struct platform_device *pdev)
	int ch, ret = 0;
	int dma_irq;
	char irq_name[4];
	int irq_rel;

	p = pdev->dev.platform_data;
	if (!p) {
@@ -1165,21 +977,9 @@ static int omap_system_dma_probe(struct platform_device *pdev)
	if (!dma_chan)
		return -ENOMEM;

	if (dma_omap2plus()) {
		dma_linked_lch = kcalloc(dma_lch_count,
					 sizeof(*dma_linked_lch),
					 GFP_KERNEL);
		if (!dma_linked_lch) {
			ret = -ENOMEM;
			goto exit_dma_lch_fail;
		}
	}

	spin_lock_init(&dma_chan_lock);
	for (ch = 0; ch < dma_chan_count; ch++) {
		omap_clear_dma(ch);
		if (dma_omap2plus())
			omap2_disable_irq_lch(ch);

		dma_chan[ch].dev_id = -1;
		dma_chan[ch].next_lch = -1;
@@ -1216,22 +1016,6 @@ static int omap_system_dma_probe(struct platform_device *pdev)
		omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
				DMA_DEFAULT_FIFO_DEPTH, 0);

	if (dma_omap2plus() && !(d->dev_caps & DMA_ENGINE_HANDLE_IRQ)) {
		strcpy(irq_name, "0");
		dma_irq = platform_get_irq_byname(pdev, irq_name);
		if (dma_irq < 0) {
			dev_err(&pdev->dev, "failed: request IRQ %d", dma_irq);
			ret = dma_irq;
			goto exit_dma_lch_fail;
		}
		ret = setup_irq(dma_irq, &omap24xx_dma_irq);
		if (ret) {
			dev_err(&pdev->dev, "set_up failed for IRQ %d for DMA (error %d)\n",
				dma_irq, ret);
			goto exit_dma_lch_fail;
		}
	}

	/* reserve dma channels 0 and 1 in high security devices on 34xx */
	if (d->dev_caps & HS_CHANNELS_RESERVED) {
		pr_info("Reserving DMA channels 0 and 1 for HS ROM code\n");
@@ -1242,34 +1026,21 @@ static int omap_system_dma_probe(struct platform_device *pdev)
	return 0;

exit_dma_irq_fail:
	dev_err(&pdev->dev, "unable to request IRQ %d for DMA (error %d)\n",
		dma_irq, ret);
	for (irq_rel = 0; irq_rel < ch;	irq_rel++) {
		dma_irq = platform_get_irq(pdev, irq_rel);
		free_irq(dma_irq, (void *)(irq_rel + 1));
	}

exit_dma_lch_fail:
	return ret;
}

static int omap_system_dma_remove(struct platform_device *pdev)
{
	int dma_irq;
	int dma_irq, irq_rel = 0;

	if (dma_omap2plus())
		return 0;

	if (dma_omap2plus()) {
		char irq_name[4];
		strcpy(irq_name, "0");
		dma_irq = platform_get_irq_byname(pdev, irq_name);
		if (dma_irq >= 0)
			remove_irq(dma_irq, &omap24xx_dma_irq);
	} else {
		int irq_rel = 0;
	for ( ; irq_rel < dma_chan_count; irq_rel++) {
		dma_irq = platform_get_irq(pdev, irq_rel);
		free_irq(dma_irq, (void *)(irq_rel + 1));
	}
	}

	return 0;
}

+0 −4
Original line number Diff line number Diff line
@@ -129,7 +129,6 @@
#define IS_WORD_16			BIT(0xd)
#define ENABLE_16XX_MODE		BIT(0xe)
#define HS_CHANNELS_RESERVED		BIT(0xf)
#define DMA_ENGINE_HANDLE_IRQ		BIT(0x10)

/* Defines for DMA Capabilities */
#define DMA_HAS_TRANSPARENT_CAPS	(0x1 << 18)
@@ -239,9 +238,6 @@ struct omap_dma_lch {
	void (*callback)(int lch, u16 ch_status, void *data);
	void *data;
	long flags;
	/* required for Dynamic chaining */
	int prev_linked_ch;
	int next_linked_ch;
	int state;
	int chain_id;
	int status;