From dfdf5f63b4380b9e719145c7cb2cb450a3d06ac4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 11 Feb 2014 09:28:09 +0100 Subject: ARM: 7956/1: mmci: rename some extended flags These four (so far unused) flags are only found in the ST Micro versions of MMCI, so infix them properly with the _ST_ infix. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- drivers/mmc/host/mmci.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 168bc72f7a94..84c0e59b792a 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -38,10 +38,11 @@ #define MCI_CPSM_INTERRUPT (1 << 8) #define MCI_CPSM_PENDING (1 << 9) #define MCI_CPSM_ENABLE (1 << 10) -#define MCI_SDIO_SUSP (1 << 11) -#define MCI_ENCMD_COMPL (1 << 12) -#define MCI_NIEN (1 << 13) -#define MCI_CE_ATACMD (1 << 14) +/* Argument flag extenstions in the ST Micro versions */ +#define MCI_ST_SDIO_SUSP (1 << 11) +#define MCI_ST_ENCMD_COMPL (1 << 12) +#define MCI_ST_NIEN (1 << 13) +#define MCI_ST_CE_ATACMD (1 << 14) #define MMCIRESPCMD 0x010 #define MMCIRESPONSE0 0x014 -- cgit v1.2.3 From f210c53a82ab9ba10574f8121a300d78e618febd Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 12 Feb 2014 14:06:43 +0100 Subject: ARM: 7958/1: amba: Let runtime PM callbacks be available for CONFIG_PM Convert to the SET_PM_RUNTIME_PM macro while defining the runtime PM callbacks. This means the callbacks becomes available for both CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME, which is needed by drivers and power domains. Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/amba/bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 9e6029105607..3cf61a127ee5 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -83,7 +83,7 @@ static struct device_attribute amba_dev_attrs[] = { __ATTR_NULL, }; -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM /* * Hooks to provide runtime PM of the pclk (bus clock). It is safe to * enable/disable the bus clock at runtime PM suspend/resume as this @@ -123,7 +123,7 @@ static const struct dev_pm_ops amba_pm = { .thaw = pm_generic_thaw, .poweroff = pm_generic_poweroff, .restore = pm_generic_restore, - SET_RUNTIME_PM_OPS( + SET_PM_RUNTIME_PM_OPS( amba_pm_runtime_suspend, amba_pm_runtime_resume, NULL -- cgit v1.2.3 From 74c4137b2a9c73e7e6887ea1bac93d7012827012 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 24 Feb 2014 16:48:26 +0100 Subject: ARM: 7989/1: Delete asm/system.h Delete ARM's asm/system.h. It's the last holdout and should be got rid of. This builds for defconfig, lpc32xx_defconfig, exynos_defconfig + XEN, the previous changed to a Gemini system and an omap3 config with TI_DAVINCI_EMAC. Signed-off-by: David Howells Acked-by: Arnd Bergmann Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Russell King --- arch/arm/include/asm/jump_label.h | 1 - arch/arm/include/asm/sync_bitops.h | 1 - arch/arm/include/asm/system.h | 7 ------- arch/arm/mach-gemini/idle.c | 2 +- arch/arm/mach-omap2/am35xx-emac.c | 1 - drivers/usb/gadget/lpc32xx_udc.c | 1 - 6 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 arch/arm/include/asm/system.h (limited to 'drivers') diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h index 863c892b4aaa..70f9b9bfb1f9 100644 --- a/arch/arm/include/asm/jump_label.h +++ b/arch/arm/include/asm/jump_label.h @@ -4,7 +4,6 @@ #ifdef __KERNEL__ #include -#include #define JUMP_LABEL_NOP_SIZE 4 diff --git a/arch/arm/include/asm/sync_bitops.h b/arch/arm/include/asm/sync_bitops.h index 63479eecbf76..9732b8e11e63 100644 --- a/arch/arm/include/asm/sync_bitops.h +++ b/arch/arm/include/asm/sync_bitops.h @@ -2,7 +2,6 @@ #define __ASM_SYNC_BITOPS_H__ #include -#include /* sync_bitops functions are equivalent to the SMP implementation of the * original functions, independently from CONFIG_SMP being defined. diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h deleted file mode 100644 index 368165e33c1c..000000000000 --- a/arch/arm/include/asm/system.h +++ /dev/null @@ -1,7 +0,0 @@ -/* FILE TO BE DELETED. DO NOT ADD STUFF HERE! */ -#include -#include -#include -#include -#include -#include diff --git a/arch/arm/mach-gemini/idle.c b/arch/arm/mach-gemini/idle.c index 87dff4f5059e..ddf8ec9d203b 100644 --- a/arch/arm/mach-gemini/idle.c +++ b/arch/arm/mach-gemini/idle.c @@ -3,7 +3,7 @@ */ #include -#include +#include #include static void gemini_idle(void) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 25b79a297365..6a6935caac1e 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -17,7 +17,6 @@ #include #include -#include #include "omap_device.h" #include "am35xx.h" #include "control.h" diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index 049ebab0d360..a94bb10eeb03 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 83b3f64d46d1d9bf1e0be1d16f805ccdd52d31c6 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Wed, 5 Mar 2014 06:23:13 +0100 Subject: ARM: 8004/1: [SCSI]: remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag from drivers/scsi/arm It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Russell King --- drivers/scsi/arm/acornscsi.c | 2 +- drivers/scsi/arm/cumana_1.c | 2 +- drivers/scsi/arm/cumana_2.c | 2 +- drivers/scsi/arm/powertec.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index 09ba1869d366..059ff477a398 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -2971,7 +2971,7 @@ static int acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id) ec->irqaddr = ashost->fast + INT_REG; ec->irqmask = 0x0a; - ret = request_irq(host->irq, acornscsi_intr, IRQF_DISABLED, "acornscsi", ashost); + ret = request_irq(host->irq, acornscsi_intr, 0, "acornscsi", ashost); if (ret) { printk(KERN_CRIT "scsi%d: IRQ%d not free: %d\n", host->host_no, ashost->scsi.irq, ret); diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index b679778376c5..f8e060900052 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -262,7 +262,7 @@ static int cumanascsi1_probe(struct expansion_card *ec, goto out_unmap; } - ret = request_irq(host->irq, cumanascsi_intr, IRQF_DISABLED, + ret = request_irq(host->irq, cumanascsi_intr, 0, "CumanaSCSI-1", host); if (ret) { printk("scsi%d: IRQ%d not free: %d\n", diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index 58915f29055b..abc66f5263ec 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -431,7 +431,7 @@ static int cumanascsi2_probe(struct expansion_card *ec, goto out_free; ret = request_irq(ec->irq, cumanascsi_2_intr, - IRQF_DISABLED, "cumanascsi2", info); + 0, "cumanascsi2", info); if (ret) { printk("scsi%d: IRQ%d not free: %d\n", host->host_no, ec->irq, ret); diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index abc9593615e9..5e1b73e1b743 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -358,7 +358,7 @@ static int powertecscsi_probe(struct expansion_card *ec, goto out_free; ret = request_irq(ec->irq, powertecscsi_intr, - IRQF_DISABLED, "powertec", info); + 0, "powertec", info); if (ret) { printk("scsi%d: IRQ%d not free: %d\n", host->host_no, ec->irq, ret); -- cgit v1.2.3 From 104fce73fdbd174eb08a493eeb2920fd59e6d3f4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 12:58:29 +0000 Subject: dmaengine: omap-dma: use devm_kzalloc() to allocate omap_dmadev. Use devm_kzalloc() to allocate omap_dmadev() so that we don't need complex error cleanup paths. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 362e7c49f2e1..98034e8c558f 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -594,7 +594,6 @@ static void omap_dma_free(struct omap_dmadev *od) tasklet_kill(&c->vc.task); kfree(c); } - kfree(od); } static int omap_dma_probe(struct platform_device *pdev) @@ -602,7 +601,7 @@ static int omap_dma_probe(struct platform_device *pdev) struct omap_dmadev *od; int rc, i; - od = kzalloc(sizeof(*od), GFP_KERNEL); + od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); if (!od) return -ENOMEM; -- cgit v1.2.3 From 1b416c4b41351c3eb8fc42dbb4cd8eba463c0813 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 13:00:03 +0000 Subject: dmaengine: omap-dma: provide a hook to get the underlying DMA platform ops Provide and use a hook to obtain the underlying DMA platform operations so that omap-dma.c can access the hardware more directly without involving the legacy DMA driver. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- arch/arm/plat-omap/dma.c | 6 ++++++ drivers/dma/omap-dma.c | 7 +++++++ include/linux/omap-dma.h | 2 ++ 3 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 01619c2910e3..d4d9a5e62152 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -2000,6 +2000,12 @@ void omap_dma_global_context_restore(void) omap_clear_dma(ch); } +struct omap_system_dma_plat_info *omap_get_plat_info(void) +{ + return p; +} +EXPORT_SYMBOL_GPL(omap_get_plat_info); + static int omap_system_dma_probe(struct platform_device *pdev) { int ch, ret = 0; diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 98034e8c558f..4ac26bf0ad30 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -26,11 +26,13 @@ struct omap_dmadev { spinlock_t lock; struct tasklet_struct task; struct list_head pending; + struct omap_system_dma_plat_info *plat; }; struct omap_chan { struct virt_dma_chan vc; struct list_head node; + struct omap_system_dma_plat_info *plat; struct dma_slave_config cfg; unsigned dma_sig; @@ -573,6 +575,7 @@ static int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig) if (!c) return -ENOMEM; + c->plat = od->plat; c->dma_sig = dma_sig; c->vc.desc_free = omap_dma_desc_free; vchan_init(&c->vc, &od->ddev); @@ -605,6 +608,10 @@ static int omap_dma_probe(struct platform_device *pdev) if (!od) return -ENOMEM; + od->plat = omap_get_plat_info(); + if (!od->plat) + return -EPROBE_DEFER; + dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources; diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 7af25a9c9c51..14742fc2aefe 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -292,6 +292,8 @@ struct omap_system_dma_plat_info { #define dma_omap15xx() ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE))) #define dma_omap16xx() ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE))) +extern struct omap_system_dma_plat_info *omap_get_plat_info(void); + 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), -- cgit v1.2.3 From b9e97822da374f52aaf99cb502f531ff2184b8f5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 13:26:57 +0000 Subject: dmaengine: omap-dma: program hardware directly Program the transfer parameters directly into the hardware, rather than using the functions in arch/arm/plat-omap/dma.c. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 142 +++++++++++++++++++++++++++++++++++++++++------ include/linux/omap-dma.h | 6 +- 2 files changed, 130 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 4ac26bf0ad30..47a3fa5bc38e 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -99,16 +99,94 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) { struct omap_sg *sg = d->sg + idx; + uint32_t val; + + if (d->dir == DMA_DEV_TO_MEM) { + if (dma_omap1()) { + val = c->plat->dma_read(CSDP, c->dma_ch); + val &= ~(0x1f << 9); + val |= OMAP_DMA_PORT_EMIFF << 9; + c->plat->dma_write(val, CSDP, c->dma_ch); + } - if (d->dir == DMA_DEV_TO_MEM) - omap_set_dma_dest_params(c->dma_ch, OMAP_DMA_PORT_EMIFF, - OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0); - else - omap_set_dma_src_params(c->dma_ch, OMAP_DMA_PORT_EMIFF, - OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0); + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(0x03 << 14); + val |= OMAP_DMA_AMODE_POST_INC << 14; + c->plat->dma_write(val, CCR, c->dma_ch); + + c->plat->dma_write(sg->addr, CDSA, c->dma_ch); + c->plat->dma_write(0, CDEI, c->dma_ch); + c->plat->dma_write(0, CDFI, c->dma_ch); + } else { + if (dma_omap1()) { + val = c->plat->dma_read(CSDP, c->dma_ch); + val &= ~(0x1f << 2); + val |= OMAP_DMA_PORT_EMIFF << 2; + c->plat->dma_write(val, CSDP, c->dma_ch); + } + + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(0x03 << 12); + val |= OMAP_DMA_AMODE_POST_INC << 12; + c->plat->dma_write(val, CCR, c->dma_ch); + + c->plat->dma_write(sg->addr, CSSA, c->dma_ch); + c->plat->dma_write(0, CSEI, c->dma_ch); + c->plat->dma_write(0, CSFI, c->dma_ch); + } + + val = c->plat->dma_read(CSDP, c->dma_ch); + val &= ~0x03; + val |= d->es; + c->plat->dma_write(val, CSDP, c->dma_ch); + + if (dma_omap1()) { + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(1 << 5); + if (d->sync_mode == OMAP_DMA_SYNC_FRAME) + val |= 1 << 5; + c->plat->dma_write(val, CCR, c->dma_ch); + + val = c->plat->dma_read(CCR2, c->dma_ch); + val &= ~(1 << 2); + if (d->sync_mode == OMAP_DMA_SYNC_BLOCK) + val |= 1 << 2; + c->plat->dma_write(val, CCR2, c->dma_ch); + } else if (c->dma_sig) { + val = c->plat->dma_read(CCR, c->dma_ch); + + /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ + val &= ~((1 << 23) | (3 << 19) | 0x1f); + val |= (c->dma_sig & ~0x1f) << 14; + val |= c->dma_sig & 0x1f; + + if (d->sync_mode & OMAP_DMA_SYNC_FRAME) + val |= 1 << 5; + else + val &= ~(1 << 5); + + if (d->sync_mode & OMAP_DMA_SYNC_BLOCK) + val |= 1 << 18; + else + val &= ~(1 << 18); + + switch (d->sync_type) { + case OMAP_DMA_DST_SYNC_PREFETCH: + val &= ~(1 << 24); /* dest synch */ + val |= 1 << 23; /* Prefetch */ + break; + case 0: + val &= ~(1 << 24); /* dest synch */ + break; + default: + val |= 1 << 24; /* source synch */ + break; + } + c->plat->dma_write(val, CCR, c->dma_ch); + } - omap_set_dma_transfer_params(c->dma_ch, d->es, sg->en, sg->fn, - d->sync_mode, c->dma_sig, d->sync_type); + c->plat->dma_write(sg->en, CEN, c->dma_ch); + c->plat->dma_write(sg->fn, CFN, c->dma_ch); omap_start_dma(c->dma_ch); } @@ -117,6 +195,7 @@ static void omap_dma_start_desc(struct omap_chan *c) { struct virt_dma_desc *vd = vchan_next_desc(&c->vc); struct omap_desc *d; + uint32_t val; if (!vd) { c->desc = NULL; @@ -128,12 +207,39 @@ static void omap_dma_start_desc(struct omap_chan *c) c->desc = d = to_omap_dma_desc(&vd->tx); c->sgidx = 0; - if (d->dir == DMA_DEV_TO_MEM) - omap_set_dma_src_params(c->dma_ch, d->periph_port, - OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi); - else - omap_set_dma_dest_params(c->dma_ch, d->periph_port, - OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi); + if (d->dir == DMA_DEV_TO_MEM) { + if (dma_omap1()) { + val = c->plat->dma_read(CSDP, c->dma_ch); + val &= ~(0x1f << 2); + val |= d->periph_port << 2; + c->plat->dma_write(val, CSDP, c->dma_ch); + } + + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(0x03 << 12); + val |= OMAP_DMA_AMODE_CONSTANT << 12; + c->plat->dma_write(val, CCR, c->dma_ch); + + c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); + c->plat->dma_write(0, CSEI, c->dma_ch); + c->plat->dma_write(d->fi, CSFI, c->dma_ch); + } else { + if (dma_omap1()) { + val = c->plat->dma_read(CSDP, c->dma_ch); + val &= ~(0x1f << 9); + val |= d->periph_port << 9; + c->plat->dma_write(val, CSDP, c->dma_ch); + } + + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(0x03 << 14); + val |= OMAP_DMA_AMODE_CONSTANT << 14; + c->plat->dma_write(val, CCR, c->dma_ch); + + c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); + c->plat->dma_write(0, CDEI, c->dma_ch); + c->plat->dma_write(d->fi, CDFI, c->dma_ch); + } omap_dma_start_sg(c, d, 0); } @@ -452,8 +558,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( } if (dma_omap2plus()) { - omap_set_dma_src_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); - omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); + uint32_t val; + + val = c->plat->dma_read(CSDP, c->dma_ch); + val |= 0x03 << 7; /* src burst mode 16 */ + val |= 0x03 << 14; /* dst burst mode 16 */ + c->plat->dma_write(val, CSDP, c->dma_ch); } return vchan_tx_prep(&c->vc, &d->vd, flags); diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 14742fc2aefe..d631658e2237 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -289,8 +289,10 @@ struct omap_system_dma_plat_info { #define dma_omap2plus() 0 #endif #define dma_omap1() (!dma_omap2plus()) -#define dma_omap15xx() ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE))) -#define dma_omap16xx() ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE))) +#define __dma_omap15xx(d) (dma_omap1() && (d)->dev_caps & ENABLE_1510_MODE) +#define __dma_omap16xx(d) (dma_omap1() && (d)->dev_caps & ENABLE_16XX_MODE) +#define dma_omap15xx() __dma_omap15xx(d) +#define dma_omap16xx() __dma_omap16xx(d) extern struct omap_system_dma_plat_info *omap_get_plat_info(void); -- cgit v1.2.3 From 913a2d0c6952283bc9323cb9152af87f792ff4c4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 14:41:42 +0000 Subject: dmaengine: omap-dma: consolidate writes to DMA registers There's no need to keep writing registers which don't change value in omap_dma_start_sg(). Move this into omap_dma_start_desc() and merge the register updates together. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 123 +++++++++++++++++++------------------------------ 1 file changed, 48 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 47a3fa5bc38e..8c5c862f01ed 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -99,40 +99,75 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) { struct omap_sg *sg = d->sg + idx; + + if (d->dir == DMA_DEV_TO_MEM) { + c->plat->dma_write(sg->addr, CDSA, c->dma_ch); + c->plat->dma_write(0, CDEI, c->dma_ch); + c->plat->dma_write(0, CDFI, c->dma_ch); + } else { + c->plat->dma_write(sg->addr, CSSA, c->dma_ch); + c->plat->dma_write(0, CSEI, c->dma_ch); + c->plat->dma_write(0, CSFI, c->dma_ch); + } + + c->plat->dma_write(sg->en, CEN, c->dma_ch); + c->plat->dma_write(sg->fn, CFN, c->dma_ch); + + omap_start_dma(c->dma_ch); +} + +static void omap_dma_start_desc(struct omap_chan *c) +{ + struct virt_dma_desc *vd = vchan_next_desc(&c->vc); + struct omap_desc *d; uint32_t val; + if (!vd) { + c->desc = NULL; + return; + } + + list_del(&vd->node); + + c->desc = d = to_omap_dma_desc(&vd->tx); + c->sgidx = 0; + if (d->dir == DMA_DEV_TO_MEM) { if (dma_omap1()) { val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 9); + val &= ~(0x1f << 9 | 0x1f << 2); val |= OMAP_DMA_PORT_EMIFF << 9; + val |= d->periph_port << 2; c->plat->dma_write(val, CSDP, c->dma_ch); } val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 14); + val &= ~(0x03 << 14 | 0x03 << 12); val |= OMAP_DMA_AMODE_POST_INC << 14; + val |= OMAP_DMA_AMODE_CONSTANT << 12; c->plat->dma_write(val, CCR, c->dma_ch); - c->plat->dma_write(sg->addr, CDSA, c->dma_ch); - c->plat->dma_write(0, CDEI, c->dma_ch); - c->plat->dma_write(0, CDFI, c->dma_ch); + c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); + c->plat->dma_write(0, CSEI, c->dma_ch); + c->plat->dma_write(d->fi, CSFI, c->dma_ch); } else { if (dma_omap1()) { val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 2); + val &= ~(0x1f << 9 | 0x1f << 2); + val |= d->periph_port << 9; val |= OMAP_DMA_PORT_EMIFF << 2; c->plat->dma_write(val, CSDP, c->dma_ch); } val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 12); + val &= ~(0x03 << 12 | 0x03 << 14); + val |= OMAP_DMA_AMODE_CONSTANT << 14; val |= OMAP_DMA_AMODE_POST_INC << 12; c->plat->dma_write(val, CCR, c->dma_ch); - c->plat->dma_write(sg->addr, CSSA, c->dma_ch); - c->plat->dma_write(0, CSEI, c->dma_ch); - c->plat->dma_write(0, CSFI, c->dma_ch); + c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); + c->plat->dma_write(0, CDEI, c->dma_ch); + c->plat->dma_write(d->fi, CDFI, c->dma_ch); } val = c->plat->dma_read(CSDP, c->dma_ch); @@ -156,91 +191,29 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, val = c->plat->dma_read(CCR, c->dma_ch); /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ - val &= ~((1 << 23) | (3 << 19) | 0x1f); + val &= ~(1 << 24 | 1 << 23 | 3 << 19 | 1 << 18 | 1 << 5 | 0x1f); val |= (c->dma_sig & ~0x1f) << 14; val |= c->dma_sig & 0x1f; if (d->sync_mode & OMAP_DMA_SYNC_FRAME) val |= 1 << 5; - else - val &= ~(1 << 5); if (d->sync_mode & OMAP_DMA_SYNC_BLOCK) val |= 1 << 18; - else - val &= ~(1 << 18); switch (d->sync_type) { - case OMAP_DMA_DST_SYNC_PREFETCH: - val &= ~(1 << 24); /* dest synch */ + case OMAP_DMA_DST_SYNC_PREFETCH:/* dest synch */ val |= 1 << 23; /* Prefetch */ break; case 0: - val &= ~(1 << 24); /* dest synch */ break; default: - val |= 1 << 24; /* source synch */ + val |= 1 << 24; /* source synch */ break; } c->plat->dma_write(val, CCR, c->dma_ch); } - c->plat->dma_write(sg->en, CEN, c->dma_ch); - c->plat->dma_write(sg->fn, CFN, c->dma_ch); - - omap_start_dma(c->dma_ch); -} - -static void omap_dma_start_desc(struct omap_chan *c) -{ - struct virt_dma_desc *vd = vchan_next_desc(&c->vc); - struct omap_desc *d; - uint32_t val; - - if (!vd) { - c->desc = NULL; - return; - } - - list_del(&vd->node); - - c->desc = d = to_omap_dma_desc(&vd->tx); - c->sgidx = 0; - - if (d->dir == DMA_DEV_TO_MEM) { - if (dma_omap1()) { - val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 2); - val |= d->periph_port << 2; - c->plat->dma_write(val, CSDP, c->dma_ch); - } - - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 12); - val |= OMAP_DMA_AMODE_CONSTANT << 12; - c->plat->dma_write(val, CCR, c->dma_ch); - - c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); - c->plat->dma_write(0, CSEI, c->dma_ch); - c->plat->dma_write(d->fi, CSFI, c->dma_ch); - } else { - if (dma_omap1()) { - val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 9); - val |= d->periph_port << 9; - c->plat->dma_write(val, CSDP, c->dma_ch); - } - - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 14); - val |= OMAP_DMA_AMODE_CONSTANT << 14; - c->plat->dma_write(val, CCR, c->dma_ch); - - c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); - c->plat->dma_write(0, CDEI, c->dma_ch); - c->plat->dma_write(d->fi, CDFI, c->dma_ch); - } - omap_dma_start_sg(c, d, 0); } -- cgit v1.2.3 From fa3ad86ae0576b2c721800cc4d46864aa6d31ffd Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 17:07:09 +0000 Subject: dmaengine: omap-dma: control start/stop directly Program the non-cyclic mode DMA start/stop directly, rather than via arch/arm/plat-omap/dma.c. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 151 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 141 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 8c5c862f01ed..7aa5ff7ab935 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -5,6 +5,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -60,6 +61,7 @@ struct omap_desc { uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */ uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */ uint8_t periph_port; /* Peripheral port */ + uint16_t cicr; /* CICR value */ unsigned sglen; struct omap_sg sg[0]; @@ -95,6 +97,111 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd) kfree(container_of(vd, struct omap_desc, vd)); } +static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) +{ + struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); + uint32_t val; + + if (__dma_omap15xx(od->plat->dma_attr)) + c->plat->dma_write(0, CPC, c->dma_ch); + else + c->plat->dma_write(0, CDAC, c->dma_ch); + + if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) { + val = c->plat->dma_read(CLNK_CTRL, c->dma_ch); + + if (dma_omap1()) + val &= ~(1 << 14); + + val |= c->dma_ch | 1 << 15; + + c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); + } else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) + c->plat->dma_write(c->dma_ch, CLNK_CTRL, c->dma_ch); + + /* Clear CSR */ + if (dma_omap1()) + c->plat->dma_read(CSR, c->dma_ch); + else + c->plat->dma_write(~0, CSR, c->dma_ch); + + /* Enable interrupts */ + c->plat->dma_write(d->cicr, CICR, c->dma_ch); + + val = c->plat->dma_read(CCR, c->dma_ch); + if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) + val |= OMAP_DMA_CCR_BUFFERING_DISABLE; + val |= OMAP_DMA_CCR_EN; + mb(); + c->plat->dma_write(val, CCR, c->dma_ch); +} + +static void omap_dma_stop(struct omap_chan *c) +{ + struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); + uint32_t val; + + /* disable irq */ + c->plat->dma_write(0, CICR, c->dma_ch); + + /* Clear CSR */ + if (dma_omap1()) + c->plat->dma_read(CSR, c->dma_ch); + else + c->plat->dma_write(~0, CSR, c->dma_ch); + + val = c->plat->dma_read(CCR, c->dma_ch); + if (od->plat->errata & DMA_ERRATA_i541 && + val & OMAP_DMA_CCR_SEL_SRC_DST_SYNC) { + uint32_t sysconfig; + unsigned i; + + sysconfig = c->plat->dma_read(OCP_SYSCONFIG, c->dma_ch); + val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK; + val |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); + c->plat->dma_write(val, OCP_SYSCONFIG, c->dma_ch); + + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~OMAP_DMA_CCR_EN; + c->plat->dma_write(val, CCR, c->dma_ch); + + /* Wait for sDMA FIFO to drain */ + for (i = 0; ; i++) { + val = c->plat->dma_read(CCR, c->dma_ch); + if (!(val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))) + break; + + if (i > 100) + break; + + udelay(5); + } + + if (val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE)) + dev_err(c->vc.chan.device->dev, + "DMA drain did not complete on lch %d\n", + c->dma_ch); + + c->plat->dma_write(sysconfig, OCP_SYSCONFIG, c->dma_ch); + } else { + val &= ~OMAP_DMA_CCR_EN; + c->plat->dma_write(val, CCR, c->dma_ch); + } + + mb(); + + if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) { + val = c->plat->dma_read(CLNK_CTRL, c->dma_ch); + + if (dma_omap1()) + val |= 1 << 14; /* set the STOP_LNK bit */ + else + val &= ~(1 << 15); /* Clear the ENABLE_LNK bit */ + + c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); + } +} + static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) { @@ -113,7 +220,7 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, c->plat->dma_write(sg->en, CEN, c->dma_ch); c->plat->dma_write(sg->fn, CFN, c->dma_ch); - omap_start_dma(c->dma_ch); + omap_dma_start(c, d); } static void omap_dma_start_desc(struct omap_chan *c) @@ -434,6 +541,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->sync_mode = OMAP_DMA_SYNC_FRAME; d->sync_type = sync_type; d->periph_port = OMAP_DMA_PORT_TIPB; + d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; + + if (dma_omap1()) + d->cicr |= OMAP1_DMA_TOUT_IRQ; + else + d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; /* * Build our scatterlist entries: each contains the address, @@ -463,6 +576,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( size_t period_len, enum dma_transfer_direction dir, unsigned long flags, void *context) { + struct omap_dmadev *od = to_omap_dma_dev(chan->device); struct omap_chan *c = to_omap_dma_chan(chan); enum dma_slave_buswidth dev_width; struct omap_desc *d; @@ -519,15 +633,25 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->sg[0].en = period_len / es_bytes[es]; d->sg[0].fn = buf_len / period_len; d->sglen = 1; + d->cicr = OMAP_DMA_DROP_IRQ; + if (flags & DMA_PREP_INTERRUPT) + d->cicr |= OMAP_DMA_FRAME_IRQ; + + if (dma_omap1()) + d->cicr |= OMAP1_DMA_TOUT_IRQ; + else + d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; if (!c->cyclic) { c->cyclic = true; - omap_dma_link_lch(c->dma_ch, c->dma_ch); - if (flags & DMA_PREP_INTERRUPT) - omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ); + if (__dma_omap15xx(od->plat->dma_attr)) { + uint32_t val; - omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ); + val = c->plat->dma_read(CCR, c->dma_ch); + val |= 3 << 8; + c->plat->dma_write(val, CCR, c->dma_ch); + } } if (dma_omap2plus()) { @@ -568,20 +692,27 @@ static int omap_dma_terminate_all(struct omap_chan *c) /* * Stop DMA activity: we assume the callback will not be called - * after omap_stop_dma() returns (even if it does, it will see + * after omap_dma_stop() returns (even if it does, it will see * c->desc is NULL and exit.) */ if (c->desc) { c->desc = NULL; /* Avoid stopping the dma twice */ if (!c->paused) - omap_stop_dma(c->dma_ch); + omap_dma_stop(c); } if (c->cyclic) { c->cyclic = false; c->paused = false; - omap_dma_unlink_lch(c->dma_ch, c->dma_ch); + + if (__dma_omap15xx(od->plat->dma_attr)) { + uint32_t val; + + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(3 << 8); + c->plat->dma_write(val, CCR, c->dma_ch); + } } vchan_get_all_descriptors(&c->vc, &head); @@ -598,7 +729,7 @@ static int omap_dma_pause(struct omap_chan *c) return -EINVAL; if (!c->paused) { - omap_stop_dma(c->dma_ch); + omap_dma_stop(c); c->paused = true; } @@ -612,7 +743,7 @@ static int omap_dma_resume(struct omap_chan *c) return -EINVAL; if (c->paused) { - omap_start_dma(c->dma_ch); + omap_dma_start(c, c->desc); c->paused = false; } -- cgit v1.2.3 From 3997cab391b38e126f217e36ad7bdc9672c9fb4d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 18:04:17 +0000 Subject: dmaengine: omap-dma: move reading of dma position to omap-dma.c Read the current DMA position from the hardware directly rather than via arch/arm/plat-omap/dma.c. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 7aa5ff7ab935..323eae2c9d08 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -427,6 +427,68 @@ static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr) return size; } +static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) +{ + struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); + dma_addr_t addr; + + if (__dma_omap15xx(od->plat->dma_attr)) + addr = c->plat->dma_read(CPC, c->dma_ch); + else + addr = c->plat->dma_read(CSAC, c->dma_ch); + + if (od->plat->errata & DMA_ERRATA_3_3 && addr == 0) + addr = c->plat->dma_read(CSAC, c->dma_ch); + + if (!__dma_omap15xx(od->plat->dma_attr)) { + /* + * CDAC == 0 indicates that the DMA transfer on the channel has + * not been started (no data has been transferred so far). + * Return the programmed source start address in this case. + */ + if (c->plat->dma_read(CDAC, c->dma_ch)) + addr = c->plat->dma_read(CSAC, c->dma_ch); + else + addr = c->plat->dma_read(CSSA, c->dma_ch); + } + + if (dma_omap1()) + addr |= c->plat->dma_read(CSSA, c->dma_ch) & 0xffff0000; + + return addr; +} + +static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c) +{ + struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); + dma_addr_t addr; + + if (__dma_omap15xx(od->plat->dma_attr)) + addr = c->plat->dma_read(CPC, c->dma_ch); + else + addr = c->plat->dma_read(CDAC, c->dma_ch); + + /* + * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is + * read before the DMA controller finished disabling the channel. + */ + if (!__dma_omap15xx(od->plat->dma_attr) && addr == 0) { + addr = c->plat->dma_read(CDAC, c->dma_ch); + /* + * CDAC == 0 indicates that the DMA transfer on the channel has + * not been started (no data has been transferred so far). + * Return the programmed destination start address in this case. + */ + if (addr == 0) + addr = c->plat->dma_read(CDSA, c->dma_ch); + } + + if (dma_omap1()) + addr |= c->plat->dma_read(CDSA, c->dma_ch) & 0xffff0000; + + return addr; +} + static enum dma_status omap_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, struct dma_tx_state *txstate) { @@ -448,9 +510,9 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan, dma_addr_t pos; if (d->dir == DMA_MEM_TO_DEV) - pos = omap_get_dma_src_pos(c->dma_ch); + pos = omap_dma_get_src_pos(c); else if (d->dir == DMA_DEV_TO_MEM) - pos = omap_get_dma_dst_pos(c->dma_ch); + pos = omap_dma_get_dst_pos(c); else pos = 0; -- cgit v1.2.3 From 2f0d13bdf6440906bb52fe94681ce7927145f4d7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 18:51:53 +0000 Subject: dmaengine: omap-dma: consolidate setup of CSDP Consolidate the setup of the channel source destination parameters register. This way, we calculate the required CSDP value when we setup a transfer descriptor, and only write it to the device registers once when we start the descriptor. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 64 ++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 323eae2c9d08..ec7cc10d4594 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -60,8 +60,8 @@ struct omap_desc { uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */ uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */ uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */ - uint8_t periph_port; /* Peripheral port */ uint16_t cicr; /* CICR value */ + uint32_t csdp; /* CSDP value */ unsigned sglen; struct omap_sg sg[0]; @@ -240,14 +240,6 @@ static void omap_dma_start_desc(struct omap_chan *c) c->sgidx = 0; if (d->dir == DMA_DEV_TO_MEM) { - if (dma_omap1()) { - val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 9 | 0x1f << 2); - val |= OMAP_DMA_PORT_EMIFF << 9; - val |= d->periph_port << 2; - c->plat->dma_write(val, CSDP, c->dma_ch); - } - val = c->plat->dma_read(CCR, c->dma_ch); val &= ~(0x03 << 14 | 0x03 << 12); val |= OMAP_DMA_AMODE_POST_INC << 14; @@ -258,14 +250,6 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(0, CSEI, c->dma_ch); c->plat->dma_write(d->fi, CSFI, c->dma_ch); } else { - if (dma_omap1()) { - val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 9 | 0x1f << 2); - val |= d->periph_port << 9; - val |= OMAP_DMA_PORT_EMIFF << 2; - c->plat->dma_write(val, CSDP, c->dma_ch); - } - val = c->plat->dma_read(CCR, c->dma_ch); val &= ~(0x03 << 12 | 0x03 << 14); val |= OMAP_DMA_AMODE_CONSTANT << 14; @@ -277,10 +261,7 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(d->fi, CDFI, c->dma_ch); } - val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~0x03; - val |= d->es; - c->plat->dma_write(val, CSDP, c->dma_ch); + c->plat->dma_write(d->csdp, CSDP, c->dma_ch); if (dma_omap1()) { val = c->plat->dma_read(CCR, c->dma_ch); @@ -602,13 +583,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->es = es; d->sync_mode = OMAP_DMA_SYNC_FRAME; d->sync_type = sync_type; - d->periph_port = OMAP_DMA_PORT_TIPB; d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; + d->csdp = es; - if (dma_omap1()) + if (dma_omap1()) { d->cicr |= OMAP1_DMA_TOUT_IRQ; - else + + if (dir == DMA_DEV_TO_MEM) + d->csdp |= OMAP_DMA_PORT_EMIFF << 9 | + OMAP_DMA_PORT_TIPB << 2; + else + d->csdp |= OMAP_DMA_PORT_TIPB << 9 | + OMAP_DMA_PORT_EMIFF << 2; + } else { d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; + } /* * Build our scatterlist entries: each contains the address, @@ -690,7 +679,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( else d->sync_mode = OMAP_DMA_SYNC_ELEMENT; d->sync_type = sync_type; - d->periph_port = OMAP_DMA_PORT_MPUI; d->sg[0].addr = buf_addr; d->sg[0].en = period_len / es_bytes[es]; d->sg[0].fn = buf_len / period_len; @@ -699,11 +687,24 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( if (flags & DMA_PREP_INTERRUPT) d->cicr |= OMAP_DMA_FRAME_IRQ; - if (dma_omap1()) + d->csdp = es; + + if (dma_omap1()) { d->cicr |= OMAP1_DMA_TOUT_IRQ; - else + + if (dir == DMA_DEV_TO_MEM) + d->csdp |= OMAP_DMA_PORT_EMIFF << 9 | + OMAP_DMA_PORT_MPUI << 2; + else + d->csdp |= OMAP_DMA_PORT_MPUI << 9 | + OMAP_DMA_PORT_EMIFF << 2; + } else { d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; + /* src and dst burst mode 16 */ + d->csdp |= 3 << 14 | 3 << 7; + } + if (!c->cyclic) { c->cyclic = true; @@ -716,15 +717,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( } } - if (dma_omap2plus()) { - uint32_t val; - - val = c->plat->dma_read(CSDP, c->dma_ch); - val |= 0x03 << 7; /* src burst mode 16 */ - val |= 0x03 << 14; /* dst burst mode 16 */ - c->plat->dma_write(val, CSDP, c->dma_ch); - } - return vchan_tx_prep(&c->vc, &d->vd, flags); } -- cgit v1.2.3 From 3ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 19:16:09 +0000 Subject: dmaengine: omap-dma: consolidate setup of CCR Consolidate the setup of the channel control register. Prepare the basic value in the preparation of the DMA descriptor, and write it into the register upon descriptor execution. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 147 ++++++++++++++++++++----------------------------- 1 file changed, 61 insertions(+), 86 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index ec7cc10d4594..9a9e81907475 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -58,8 +58,7 @@ struct omap_desc { int16_t fi; /* for OMAP_DMA_SYNC_PACKET */ uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */ - uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */ - uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */ + uint32_t ccr; /* CCR value */ uint16_t cicr; /* CICR value */ uint32_t csdp; /* CSDP value */ @@ -227,7 +226,6 @@ static void omap_dma_start_desc(struct omap_chan *c) { struct virt_dma_desc *vd = vchan_next_desc(&c->vc); struct omap_desc *d; - uint32_t val; if (!vd) { c->desc = NULL; @@ -239,23 +237,15 @@ static void omap_dma_start_desc(struct omap_chan *c) c->desc = d = to_omap_dma_desc(&vd->tx); c->sgidx = 0; - if (d->dir == DMA_DEV_TO_MEM) { - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 14 | 0x03 << 12); - val |= OMAP_DMA_AMODE_POST_INC << 14; - val |= OMAP_DMA_AMODE_CONSTANT << 12; - c->plat->dma_write(val, CCR, c->dma_ch); + c->plat->dma_write(d->ccr, CCR, c->dma_ch); + if (dma_omap1()) + c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch); + if (d->dir == DMA_DEV_TO_MEM) { c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); c->plat->dma_write(0, CSEI, c->dma_ch); c->plat->dma_write(d->fi, CSFI, c->dma_ch); } else { - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 12 | 0x03 << 14); - val |= OMAP_DMA_AMODE_CONSTANT << 14; - val |= OMAP_DMA_AMODE_POST_INC << 12; - c->plat->dma_write(val, CCR, c->dma_ch); - c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); c->plat->dma_write(0, CDEI, c->dma_ch); c->plat->dma_write(d->fi, CDFI, c->dma_ch); @@ -263,45 +253,6 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(d->csdp, CSDP, c->dma_ch); - if (dma_omap1()) { - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(1 << 5); - if (d->sync_mode == OMAP_DMA_SYNC_FRAME) - val |= 1 << 5; - c->plat->dma_write(val, CCR, c->dma_ch); - - val = c->plat->dma_read(CCR2, c->dma_ch); - val &= ~(1 << 2); - if (d->sync_mode == OMAP_DMA_SYNC_BLOCK) - val |= 1 << 2; - c->plat->dma_write(val, CCR2, c->dma_ch); - } else if (c->dma_sig) { - val = c->plat->dma_read(CCR, c->dma_ch); - - /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ - val &= ~(1 << 24 | 1 << 23 | 3 << 19 | 1 << 18 | 1 << 5 | 0x1f); - val |= (c->dma_sig & ~0x1f) << 14; - val |= c->dma_sig & 0x1f; - - if (d->sync_mode & OMAP_DMA_SYNC_FRAME) - val |= 1 << 5; - - if (d->sync_mode & OMAP_DMA_SYNC_BLOCK) - val |= 1 << 18; - - switch (d->sync_type) { - case OMAP_DMA_DST_SYNC_PREFETCH:/* dest synch */ - val |= 1 << 23; /* Prefetch */ - break; - case 0: - break; - default: - val |= 1 << 24; /* source synch */ - break; - } - c->plat->dma_write(val, CCR, c->dma_ch); - } - omap_dma_start_sg(c, d, 0); } @@ -540,19 +491,17 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( struct scatterlist *sgent; struct omap_desc *d; dma_addr_t dev_addr; - unsigned i, j = 0, es, en, frame_bytes, sync_type; + unsigned i, j = 0, es, en, frame_bytes; u32 burst; if (dir == DMA_DEV_TO_MEM) { dev_addr = c->cfg.src_addr; dev_width = c->cfg.src_addr_width; burst = c->cfg.src_maxburst; - sync_type = OMAP_DMA_SRC_SYNC; } else if (dir == DMA_MEM_TO_DEV) { dev_addr = c->cfg.dst_addr; dev_width = c->cfg.dst_addr_width; burst = c->cfg.dst_maxburst; - sync_type = OMAP_DMA_DST_SYNC; } else { dev_err(chan->device->dev, "%s: bad direction?\n", __func__); return NULL; @@ -581,12 +530,28 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->dir = dir; d->dev_addr = dev_addr; d->es = es; - d->sync_mode = OMAP_DMA_SYNC_FRAME; - d->sync_type = sync_type; + + d->ccr = 0; + if (dir == DMA_DEV_TO_MEM) + d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 | + OMAP_DMA_AMODE_CONSTANT << 12; + else + d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 | + OMAP_DMA_AMODE_POST_INC << 12; + d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; d->csdp = es; if (dma_omap1()) { + d->ccr |= 1 << 5; /* frame sync */ + if (__dma_omap16xx(od->plat->dma_attr)) { + d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */ + /* Duplicate what plat-omap/dma.c does */ + d->ccr |= c->dma_ch + 1; + } else { + d->ccr |= c->dma_sig & 0x1f; + } + d->cicr |= OMAP1_DMA_TOUT_IRQ; if (dir == DMA_DEV_TO_MEM) @@ -596,6 +561,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->csdp |= OMAP_DMA_PORT_TIPB << 9 | OMAP_DMA_PORT_EMIFF << 2; } else { + d->ccr |= (c->dma_sig & ~0x1f) << 14; + d->ccr |= c->dma_sig & 0x1f; + d->ccr |= 1 << 5; /* frame sync */ + + if (dir == DMA_DEV_TO_MEM) + d->ccr |= 1 << 24; /* source synch */ + d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; } @@ -632,19 +604,17 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( enum dma_slave_buswidth dev_width; struct omap_desc *d; dma_addr_t dev_addr; - unsigned es, sync_type; + unsigned es; u32 burst; if (dir == DMA_DEV_TO_MEM) { dev_addr = c->cfg.src_addr; dev_width = c->cfg.src_addr_width; burst = c->cfg.src_maxburst; - sync_type = OMAP_DMA_SRC_SYNC; } else if (dir == DMA_MEM_TO_DEV) { dev_addr = c->cfg.dst_addr; dev_width = c->cfg.dst_addr_width; burst = c->cfg.dst_maxburst; - sync_type = OMAP_DMA_DST_SYNC; } else { dev_err(chan->device->dev, "%s: bad direction?\n", __func__); return NULL; @@ -674,15 +644,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->dev_addr = dev_addr; d->fi = burst; d->es = es; - if (burst) - d->sync_mode = OMAP_DMA_SYNC_PACKET; - else - d->sync_mode = OMAP_DMA_SYNC_ELEMENT; - d->sync_type = sync_type; d->sg[0].addr = buf_addr; d->sg[0].en = period_len / es_bytes[es]; d->sg[0].fn = buf_len / period_len; d->sglen = 1; + + d->ccr = 0; + if (__dma_omap15xx(od->plat->dma_attr)) + d->ccr = 3 << 8; + if (dir == DMA_DEV_TO_MEM) + d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 | + OMAP_DMA_AMODE_CONSTANT << 12; + else + d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 | + OMAP_DMA_AMODE_POST_INC << 12; + d->cicr = OMAP_DMA_DROP_IRQ; if (flags & DMA_PREP_INTERRUPT) d->cicr |= OMAP_DMA_FRAME_IRQ; @@ -690,6 +666,14 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp = es; if (dma_omap1()) { + if (__dma_omap16xx(od->plat->dma_attr)) { + d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */ + /* Duplicate what plat-omap/dma.c does */ + d->ccr |= c->dma_ch + 1; + } else { + d->ccr |= c->dma_sig & 0x1f; + } + d->cicr |= OMAP1_DMA_TOUT_IRQ; if (dir == DMA_DEV_TO_MEM) @@ -699,23 +683,22 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp |= OMAP_DMA_PORT_MPUI << 9 | OMAP_DMA_PORT_EMIFF << 2; } else { + d->ccr |= (c->dma_sig & ~0x1f) << 14; + d->ccr |= c->dma_sig & 0x1f; + + if (burst) + d->ccr |= 1 << 18 | 1 << 5; /* packet */ + + if (dir == DMA_DEV_TO_MEM) + d->ccr |= 1 << 24; /* source synch */ + d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; /* src and dst burst mode 16 */ d->csdp |= 3 << 14 | 3 << 7; } - if (!c->cyclic) { - c->cyclic = true; - - if (__dma_omap15xx(od->plat->dma_attr)) { - uint32_t val; - - val = c->plat->dma_read(CCR, c->dma_ch); - val |= 3 << 8; - c->plat->dma_write(val, CCR, c->dma_ch); - } - } + c->cyclic = true; return vchan_tx_prep(&c->vc, &d->vd, flags); } @@ -759,14 +742,6 @@ static int omap_dma_terminate_all(struct omap_chan *c) if (c->cyclic) { c->cyclic = false; c->paused = false; - - if (__dma_omap15xx(od->plat->dma_attr)) { - uint32_t val; - - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(3 << 8); - c->plat->dma_write(val, CCR, c->dma_ch); - } } vchan_get_all_descriptors(&c->vc, &head); -- cgit v1.2.3 From 9043826d88467091543c1d3ab06eb4afeed34789 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 19:57:06 +0000 Subject: dmaengine: omap-dma: provide register definitions Provide our own set of more complete register definitions; this allows us to get rid of the meaningless 1 << n constants scattered throughout this code. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 171 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 117 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 9a9e81907475..6cf66e608338 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -57,7 +57,7 @@ struct omap_desc { dma_addr_t dev_addr; int16_t fi; /* for OMAP_DMA_SYNC_PACKET */ - uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */ + uint8_t es; /* CSDP_DATA_TYPE_xxx */ uint32_t ccr; /* CCR value */ uint16_t cicr; /* CICR value */ uint32_t csdp; /* CSDP value */ @@ -66,10 +66,83 @@ struct omap_desc { struct omap_sg sg[0]; }; +enum { + CCR_FS = BIT(5), + CCR_READ_PRIORITY = BIT(6), + CCR_ENABLE = BIT(7), + CCR_AUTO_INIT = BIT(8), /* OMAP1 only */ + CCR_REPEAT = BIT(9), /* OMAP1 only */ + CCR_OMAP31_DISABLE = BIT(10), /* OMAP1 only */ + CCR_SUSPEND_SENSITIVE = BIT(8), /* OMAP2+ only */ + CCR_RD_ACTIVE = BIT(9), /* OMAP2+ only */ + CCR_WR_ACTIVE = BIT(10), /* OMAP2+ only */ + CCR_SRC_AMODE_CONSTANT = 0 << 12, + CCR_SRC_AMODE_POSTINC = 1 << 12, + CCR_SRC_AMODE_SGLIDX = 2 << 12, + CCR_SRC_AMODE_DBLIDX = 3 << 12, + CCR_DST_AMODE_CONSTANT = 0 << 14, + CCR_DST_AMODE_POSTINC = 1 << 14, + CCR_DST_AMODE_SGLIDX = 2 << 14, + CCR_DST_AMODE_DBLIDX = 3 << 14, + CCR_CONSTANT_FILL = BIT(16), + CCR_TRANSPARENT_COPY = BIT(17), + CCR_BS = BIT(18), + CCR_SUPERVISOR = BIT(22), + CCR_PREFETCH = BIT(23), + CCR_TRIGGER_SRC = BIT(24), + CCR_BUFFERING_DISABLE = BIT(25), + CCR_WRITE_PRIORITY = BIT(26), + CCR_SYNC_ELEMENT = 0, + CCR_SYNC_FRAME = CCR_FS, + CCR_SYNC_BLOCK = CCR_BS, + CCR_SYNC_PACKET = CCR_BS | CCR_FS, + + CSDP_DATA_TYPE_8 = 0, + CSDP_DATA_TYPE_16 = 1, + CSDP_DATA_TYPE_32 = 2, + CSDP_SRC_PORT_EMIFF = 0 << 2, /* OMAP1 only */ + CSDP_SRC_PORT_EMIFS = 1 << 2, /* OMAP1 only */ + CSDP_SRC_PORT_OCP_T1 = 2 << 2, /* OMAP1 only */ + CSDP_SRC_PORT_TIPB = 3 << 2, /* OMAP1 only */ + CSDP_SRC_PORT_OCP_T2 = 4 << 2, /* OMAP1 only */ + CSDP_SRC_PORT_MPUI = 5 << 2, /* OMAP1 only */ + CSDP_SRC_PACKED = BIT(6), + CSDP_SRC_BURST_1 = 0 << 7, + CSDP_SRC_BURST_16 = 1 << 7, + CSDP_SRC_BURST_32 = 2 << 7, + CSDP_SRC_BURST_64 = 3 << 7, + CSDP_DST_PORT_EMIFF = 0 << 9, /* OMAP1 only */ + CSDP_DST_PORT_EMIFS = 1 << 9, /* OMAP1 only */ + CSDP_DST_PORT_OCP_T1 = 2 << 9, /* OMAP1 only */ + CSDP_DST_PORT_TIPB = 3 << 9, /* OMAP1 only */ + CSDP_DST_PORT_OCP_T2 = 4 << 9, /* OMAP1 only */ + CSDP_DST_PORT_MPUI = 5 << 9, /* OMAP1 only */ + CSDP_DST_PACKED = BIT(13), + CSDP_DST_BURST_1 = 0 << 14, + CSDP_DST_BURST_16 = 1 << 14, + CSDP_DST_BURST_32 = 2 << 14, + CSDP_DST_BURST_64 = 3 << 14, + + CICR_TOUT_IE = BIT(0), /* OMAP1 only */ + CICR_DROP_IE = BIT(1), + CICR_HALF_IE = BIT(2), + CICR_FRAME_IE = BIT(3), + CICR_LAST_IE = BIT(4), + CICR_BLOCK_IE = BIT(5), + CICR_PKT_IE = BIT(7), /* OMAP2+ only */ + CICR_TRANS_ERR_IE = BIT(8), /* OMAP2+ only */ + CICR_SUPERVISOR_ERR_IE = BIT(10), /* OMAP2+ only */ + CICR_MISALIGNED_ERR_IE = BIT(11), /* OMAP2+ only */ + CICR_DRAIN_IE = BIT(12), /* OMAP2+ only */ + CICR_SUPER_BLOCK_IE = BIT(14), /* OMAP2+ only */ + + CLNK_CTRL_ENABLE_LNK = BIT(15), +}; + static const unsigned es_bytes[] = { - [OMAP_DMA_DATA_TYPE_S8] = 1, - [OMAP_DMA_DATA_TYPE_S16] = 2, - [OMAP_DMA_DATA_TYPE_S32] = 4, + [CSDP_DATA_TYPE_8] = 1, + [CSDP_DATA_TYPE_16] = 2, + [CSDP_DATA_TYPE_32] = 4, }; static struct of_dma_filter_info omap_dma_info = { @@ -112,7 +185,7 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) if (dma_omap1()) val &= ~(1 << 14); - val |= c->dma_ch | 1 << 15; + val |= c->dma_ch | CLNK_CTRL_ENABLE_LNK; c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); } else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) @@ -129,8 +202,8 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) val = c->plat->dma_read(CCR, c->dma_ch); if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) - val |= OMAP_DMA_CCR_BUFFERING_DISABLE; - val |= OMAP_DMA_CCR_EN; + val |= CCR_BUFFERING_DISABLE; + val |= CCR_ENABLE; mb(); c->plat->dma_write(val, CCR, c->dma_ch); } @@ -150,8 +223,7 @@ static void omap_dma_stop(struct omap_chan *c) c->plat->dma_write(~0, CSR, c->dma_ch); val = c->plat->dma_read(CCR, c->dma_ch); - if (od->plat->errata & DMA_ERRATA_i541 && - val & OMAP_DMA_CCR_SEL_SRC_DST_SYNC) { + if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) { uint32_t sysconfig; unsigned i; @@ -161,13 +233,13 @@ static void omap_dma_stop(struct omap_chan *c) c->plat->dma_write(val, OCP_SYSCONFIG, c->dma_ch); val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~OMAP_DMA_CCR_EN; + val &= ~CCR_ENABLE; c->plat->dma_write(val, CCR, c->dma_ch); /* Wait for sDMA FIFO to drain */ for (i = 0; ; i++) { val = c->plat->dma_read(CCR, c->dma_ch); - if (!(val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))) + if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))) break; if (i > 100) @@ -176,14 +248,14 @@ static void omap_dma_stop(struct omap_chan *c) udelay(5); } - if (val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE)) + if (val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE)) dev_err(c->vc.chan.device->dev, "DMA drain did not complete on lch %d\n", c->dma_ch); c->plat->dma_write(sysconfig, OCP_SYSCONFIG, c->dma_ch); } else { - val &= ~OMAP_DMA_CCR_EN; + val &= ~CCR_ENABLE; c->plat->dma_write(val, CCR, c->dma_ch); } @@ -195,7 +267,7 @@ static void omap_dma_stop(struct omap_chan *c) if (dma_omap1()) val |= 1 << 14; /* set the STOP_LNK bit */ else - val &= ~(1 << 15); /* Clear the ENABLE_LNK bit */ + val &= ~CLNK_CTRL_ENABLE_LNK; c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); } @@ -510,13 +582,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( /* Bus width translates to the element size (ES) */ switch (dev_width) { case DMA_SLAVE_BUSWIDTH_1_BYTE: - es = OMAP_DMA_DATA_TYPE_S8; + es = CSDP_DATA_TYPE_8; break; case DMA_SLAVE_BUSWIDTH_2_BYTES: - es = OMAP_DMA_DATA_TYPE_S16; + es = CSDP_DATA_TYPE_16; break; case DMA_SLAVE_BUSWIDTH_4_BYTES: - es = OMAP_DMA_DATA_TYPE_S32; + es = CSDP_DATA_TYPE_32; break; default: /* not reached */ return NULL; @@ -531,44 +603,38 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->dev_addr = dev_addr; d->es = es; - d->ccr = 0; + d->ccr = CCR_SYNC_FRAME; if (dir == DMA_DEV_TO_MEM) - d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 | - OMAP_DMA_AMODE_CONSTANT << 12; + d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; else - d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 | - OMAP_DMA_AMODE_POST_INC << 12; + d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC; - d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; + d->cicr = CICR_DROP_IE | CICR_BLOCK_IE; d->csdp = es; if (dma_omap1()) { - d->ccr |= 1 << 5; /* frame sync */ if (__dma_omap16xx(od->plat->dma_attr)) { - d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */ + d->ccr |= CCR_OMAP31_DISABLE; /* Duplicate what plat-omap/dma.c does */ d->ccr |= c->dma_ch + 1; } else { d->ccr |= c->dma_sig & 0x1f; } - d->cicr |= OMAP1_DMA_TOUT_IRQ; + d->cicr |= CICR_TOUT_IE; if (dir == DMA_DEV_TO_MEM) - d->csdp |= OMAP_DMA_PORT_EMIFF << 9 | - OMAP_DMA_PORT_TIPB << 2; + d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_TIPB; else - d->csdp |= OMAP_DMA_PORT_TIPB << 9 | - OMAP_DMA_PORT_EMIFF << 2; + d->csdp |= CSDP_DST_PORT_TIPB | CSDP_SRC_PORT_EMIFF; } else { d->ccr |= (c->dma_sig & ~0x1f) << 14; d->ccr |= c->dma_sig & 0x1f; - d->ccr |= 1 << 5; /* frame sync */ if (dir == DMA_DEV_TO_MEM) - d->ccr |= 1 << 24; /* source synch */ + d->ccr |= CCR_TRIGGER_SRC; - d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; + d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; } /* @@ -623,13 +689,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( /* Bus width translates to the element size (ES) */ switch (dev_width) { case DMA_SLAVE_BUSWIDTH_1_BYTE: - es = OMAP_DMA_DATA_TYPE_S8; + es = CSDP_DATA_TYPE_8; break; case DMA_SLAVE_BUSWIDTH_2_BYTES: - es = OMAP_DMA_DATA_TYPE_S16; + es = CSDP_DATA_TYPE_16; break; case DMA_SLAVE_BUSWIDTH_4_BYTES: - es = OMAP_DMA_DATA_TYPE_S32; + es = CSDP_DATA_TYPE_32; break; default: /* not reached */ return NULL; @@ -651,51 +717,48 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->ccr = 0; if (__dma_omap15xx(od->plat->dma_attr)) - d->ccr = 3 << 8; + d->ccr = CCR_AUTO_INIT | CCR_REPEAT; if (dir == DMA_DEV_TO_MEM) - d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 | - OMAP_DMA_AMODE_CONSTANT << 12; + d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; else - d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 | - OMAP_DMA_AMODE_POST_INC << 12; + d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC; - d->cicr = OMAP_DMA_DROP_IRQ; + d->cicr = CICR_DROP_IE; if (flags & DMA_PREP_INTERRUPT) - d->cicr |= OMAP_DMA_FRAME_IRQ; + d->cicr |= CICR_FRAME_IE; d->csdp = es; if (dma_omap1()) { if (__dma_omap16xx(od->plat->dma_attr)) { - d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */ + d->ccr |= CCR_OMAP31_DISABLE; /* Duplicate what plat-omap/dma.c does */ d->ccr |= c->dma_ch + 1; } else { d->ccr |= c->dma_sig & 0x1f; } - d->cicr |= OMAP1_DMA_TOUT_IRQ; + d->cicr |= CICR_TOUT_IE; if (dir == DMA_DEV_TO_MEM) - d->csdp |= OMAP_DMA_PORT_EMIFF << 9 | - OMAP_DMA_PORT_MPUI << 2; + d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_MPUI; else - d->csdp |= OMAP_DMA_PORT_MPUI << 9 | - OMAP_DMA_PORT_EMIFF << 2; + d->csdp |= CSDP_DST_PORT_MPUI | CSDP_SRC_PORT_EMIFF; } else { d->ccr |= (c->dma_sig & ~0x1f) << 14; d->ccr |= c->dma_sig & 0x1f; if (burst) - d->ccr |= 1 << 18 | 1 << 5; /* packet */ + d->ccr |= CCR_SYNC_PACKET; + else + d->ccr |= CCR_SYNC_ELEMENT; if (dir == DMA_DEV_TO_MEM) - d->ccr |= 1 << 24; /* source synch */ + d->ccr |= CCR_TRIGGER_SRC; - d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; + d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; - /* src and dst burst mode 16 */ - d->csdp |= 3 << 14 | 3 << 7; + d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64; } c->cyclic = true; -- cgit v1.2.3 From 49ae0b29439446cff81c32bf01fb7b7cce195373 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 21:09:18 +0000 Subject: dmaengine: omap-dma: move CCR buffering disable errata out of the fast path Since we record the CCR register in the dma transaction, we can move the processing of the iframe buffering errata out of the omap_dma_start(). Move it to the preparation functions. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 6cf66e608338..324f4c7c5dd0 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -201,8 +201,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) c->plat->dma_write(d->cicr, CICR, c->dma_ch); val = c->plat->dma_read(CCR, c->dma_ch); - if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) - val |= CCR_BUFFERING_DISABLE; val |= CCR_ENABLE; mb(); c->plat->dma_write(val, CCR, c->dma_ch); @@ -558,6 +556,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, unsigned sglen, enum dma_transfer_direction dir, unsigned long tx_flags, void *context) { + struct omap_dmadev *od = to_omap_dma_dev(chan->device); struct omap_chan *c = to_omap_dma_chan(chan); enum dma_slave_buswidth dev_width; struct scatterlist *sgent; @@ -636,6 +635,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; } + if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) + d->ccr |= CCR_BUFFERING_DISABLE; /* * Build our scatterlist entries: each contains the address, @@ -760,6 +761,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64; } + if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) + d->ccr |= CCR_BUFFERING_DISABLE; c->cyclic = true; -- cgit v1.2.3 From 470b23f7308dd2af25bd075d14a724f8ccd93985 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 21:23:06 +0000 Subject: dmaengine: omap-dma: consolidate clearing channel status register Consolidate clearing of the channel status register, rather than open coding the same functionality in two places. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 324f4c7c5dd0..d1641aa9d113 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -169,6 +169,14 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd) kfree(container_of(vd, struct omap_desc, vd)); } +static void omap_dma_clear_csr(struct omap_chan *c) +{ + if (dma_omap1()) + c->plat->dma_read(CSR, c->dma_ch); + else + c->plat->dma_write(~0, CSR, c->dma_ch); +} + static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) { struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); @@ -191,11 +199,7 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) } else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) c->plat->dma_write(c->dma_ch, CLNK_CTRL, c->dma_ch); - /* Clear CSR */ - if (dma_omap1()) - c->plat->dma_read(CSR, c->dma_ch); - else - c->plat->dma_write(~0, CSR, c->dma_ch); + omap_dma_clear_csr(c); /* Enable interrupts */ c->plat->dma_write(d->cicr, CICR, c->dma_ch); @@ -214,11 +218,7 @@ static void omap_dma_stop(struct omap_chan *c) /* disable irq */ c->plat->dma_write(0, CICR, c->dma_ch); - /* Clear CSR */ - if (dma_omap1()) - c->plat->dma_read(CSR, c->dma_ch); - else - c->plat->dma_write(~0, CSR, c->dma_ch); + omap_dma_clear_csr(c); val = c->plat->dma_read(CCR, c->dma_ch); if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) { -- cgit v1.2.3 From 893e63e301e37cd3be7afb55c95eb8ef6ead304b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 3 Nov 2013 11:17:11 +0000 Subject: dmaengine: omap-dma: improve efficiency loading C.SA/C.EI/C.FI registers The only thing which changes is which registers are written, so put this in local variables instead. This results in smaller code. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index d1641aa9d113..06727a78e883 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -275,17 +275,21 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) { struct omap_sg *sg = d->sg + idx; + unsigned cxsa, cxei, cxfi; if (d->dir == DMA_DEV_TO_MEM) { - c->plat->dma_write(sg->addr, CDSA, c->dma_ch); - c->plat->dma_write(0, CDEI, c->dma_ch); - c->plat->dma_write(0, CDFI, c->dma_ch); + cxsa = CDSA; + cxei = CDEI; + cxfi = CDFI; } else { - c->plat->dma_write(sg->addr, CSSA, c->dma_ch); - c->plat->dma_write(0, CSEI, c->dma_ch); - c->plat->dma_write(0, CSFI, c->dma_ch); + cxsa = CSSA; + cxei = CSEI; + cxfi = CSFI; } + c->plat->dma_write(sg->addr, cxsa, c->dma_ch); + c->plat->dma_write(0, cxei, c->dma_ch); + c->plat->dma_write(0, cxfi, c->dma_ch); c->plat->dma_write(sg->en, CEN, c->dma_ch); c->plat->dma_write(sg->fn, CFN, c->dma_ch); @@ -296,6 +300,7 @@ static void omap_dma_start_desc(struct omap_chan *c) { struct virt_dma_desc *vd = vchan_next_desc(&c->vc); struct omap_desc *d; + unsigned cxsa, cxei, cxfi; if (!vd) { c->desc = NULL; @@ -312,15 +317,18 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch); if (d->dir == DMA_DEV_TO_MEM) { - c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); - c->plat->dma_write(0, CSEI, c->dma_ch); - c->plat->dma_write(d->fi, CSFI, c->dma_ch); + cxsa = CSSA; + cxei = CSEI; + cxfi = CSFI; } else { - c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); - c->plat->dma_write(0, CDEI, c->dma_ch); - c->plat->dma_write(d->fi, CDFI, c->dma_ch); + cxsa = CDSA; + cxei = CDEI; + cxfi = CDFI; } + c->plat->dma_write(d->dev_addr, cxsa, c->dma_ch); + c->plat->dma_write(0, cxei, c->dma_ch); + c->plat->dma_write(d->fi, cxfi, c->dma_ch); c->plat->dma_write(d->csdp, CSDP, c->dma_ch); omap_dma_start_sg(c, d, 0); -- cgit v1.2.3 From 965aeb4df1f2142f5a6407c6d40b7196be719582 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Nov 2013 17:12:30 +0000 Subject: dmaengine: omap-dma: move clnk_ctrl setting to preparation functions Move the clnk_ctrl setup to the preparation functions, saving its value in the omap_desc. This only needs to be set once per descriptor, not for each segment, so set it in omap_dma_start_desc() rather than omap_dma_start(). Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 06727a78e883..49609275b2e7 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -59,6 +59,7 @@ struct omap_desc { int16_t fi; /* for OMAP_DMA_SYNC_PACKET */ uint8_t es; /* CSDP_DATA_TYPE_xxx */ uint32_t ccr; /* CCR value */ + uint16_t clnk_ctrl; /* CLNK_CTRL value */ uint16_t cicr; /* CICR value */ uint32_t csdp; /* CSDP value */ @@ -187,18 +188,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) else c->plat->dma_write(0, CDAC, c->dma_ch); - if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) { - val = c->plat->dma_read(CLNK_CTRL, c->dma_ch); - - if (dma_omap1()) - val &= ~(1 << 14); - - val |= c->dma_ch | CLNK_CTRL_ENABLE_LNK; - - c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); - } else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) - c->plat->dma_write(c->dma_ch, CLNK_CTRL, c->dma_ch); - omap_dma_clear_csr(c); /* Enable interrupts */ @@ -330,6 +319,7 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(0, cxei, c->dma_ch); c->plat->dma_write(d->fi, cxfi, c->dma_ch); c->plat->dma_write(d->csdp, CSDP, c->dma_ch); + c->plat->dma_write(d->clnk_ctrl, CLNK_CTRL, c->dma_ch); omap_dma_start_sg(c, d, 0); } @@ -645,6 +635,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( } if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) d->ccr |= CCR_BUFFERING_DISABLE; + if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) + d->clnk_ctrl = c->dma_ch; /* * Build our scatterlist entries: each contains the address, @@ -725,8 +717,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->sglen = 1; d->ccr = 0; - if (__dma_omap15xx(od->plat->dma_attr)) - d->ccr = CCR_AUTO_INIT | CCR_REPEAT; if (dir == DMA_DEV_TO_MEM) d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; else @@ -772,6 +762,11 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) d->ccr |= CCR_BUFFERING_DISABLE; + if (__dma_omap15xx(od->plat->dma_attr)) + d->ccr |= CCR_AUTO_INIT | CCR_REPEAT; + else + d->clnk_ctrl = c->dma_ch | CLNK_CTRL_ENABLE_LNK; + c->cyclic = true; return vchan_tx_prep(&c->vc, &d->vd, flags); -- cgit v1.2.3 From 59871902703c47acc730555be41bd9cb36d3700c Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Nov 2013 17:15:16 +0000 Subject: dmaengine: omap-dma: move barrier to omap_dma_start_desc() We don't need to issue a barrier for every segment of a DMA transfer; doing this just once per descriptor will do. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 49609275b2e7..49b303296d75 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -195,7 +195,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) val = c->plat->dma_read(CCR, c->dma_ch); val |= CCR_ENABLE; - mb(); c->plat->dma_write(val, CCR, c->dma_ch); } @@ -301,6 +300,13 @@ static void omap_dma_start_desc(struct omap_chan *c) c->desc = d = to_omap_dma_desc(&vd->tx); c->sgidx = 0; + /* + * This provides the necessary barrier to ensure data held in + * DMA coherent memory is visible to the DMA engine prior to + * the transfer starting. + */ + mb(); + c->plat->dma_write(d->ccr, CCR, c->dma_ch); if (dma_omap1()) c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch); -- cgit v1.2.3 From 45da7b0451b1fe15e882b08c79be58458cbe7a2f Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Nov 2013 17:18:42 +0000 Subject: dmaengine: omap-dma: use cached CCR value when enabling DMA We don't need to read-modify-write the CCR register; we already know what value it should contain at this point. Use the cached CCR value when setting the enable bit. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 49b303296d75..b270aedf1d15 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -181,7 +181,6 @@ static void omap_dma_clear_csr(struct omap_chan *c) static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) { struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); - uint32_t val; if (__dma_omap15xx(od->plat->dma_attr)) c->plat->dma_write(0, CPC, c->dma_ch); @@ -193,9 +192,8 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) /* Enable interrupts */ c->plat->dma_write(d->cicr, CICR, c->dma_ch); - val = c->plat->dma_read(CCR, c->dma_ch); - val |= CCR_ENABLE; - c->plat->dma_write(val, CCR, c->dma_ch); + /* Enable channel */ + c->plat->dma_write(d->ccr | CCR_ENABLE, CCR, c->dma_ch); } static void omap_dma_stop(struct omap_chan *c) -- cgit v1.2.3 From c5ed98b6ae79545284b7855a07ded32934865a6d Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Nov 2013 17:33:09 +0000 Subject: dmaengine: omap-dma: provide register read/write functions Provide a pair of channel register accessors, and a pair of global accessors for non-channel specific registers. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 102 +++++++++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index b270aedf1d15..a1baada7dcd4 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -170,12 +170,32 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd) kfree(container_of(vd, struct omap_desc, vd)); } +static void omap_dma_glbl_write(struct omap_dmadev *od, unsigned reg, unsigned val) +{ + od->plat->dma_write(val, reg, 0); +} + +static unsigned omap_dma_glbl_read(struct omap_dmadev *od, unsigned reg) +{ + return od->plat->dma_read(reg, 0); +} + +static void omap_dma_chan_write(struct omap_chan *c, unsigned reg, unsigned val) +{ + c->plat->dma_write(val, reg, c->dma_ch); +} + +static unsigned omap_dma_chan_read(struct omap_chan *c, unsigned reg) +{ + return c->plat->dma_read(reg, c->dma_ch); +} + static void omap_dma_clear_csr(struct omap_chan *c) { if (dma_omap1()) - c->plat->dma_read(CSR, c->dma_ch); + omap_dma_chan_read(c, CSR); else - c->plat->dma_write(~0, CSR, c->dma_ch); + omap_dma_chan_write(c, CSR, ~0); } static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) @@ -183,17 +203,17 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); if (__dma_omap15xx(od->plat->dma_attr)) - c->plat->dma_write(0, CPC, c->dma_ch); + omap_dma_chan_write(c, CPC, 0); else - c->plat->dma_write(0, CDAC, c->dma_ch); + omap_dma_chan_write(c, CDAC, 0); omap_dma_clear_csr(c); /* Enable interrupts */ - c->plat->dma_write(d->cicr, CICR, c->dma_ch); + omap_dma_chan_write(c, CICR, d->cicr); /* Enable channel */ - c->plat->dma_write(d->ccr | CCR_ENABLE, CCR, c->dma_ch); + omap_dma_chan_write(c, CCR, d->ccr | CCR_ENABLE); } static void omap_dma_stop(struct omap_chan *c) @@ -202,27 +222,27 @@ static void omap_dma_stop(struct omap_chan *c) uint32_t val; /* disable irq */ - c->plat->dma_write(0, CICR, c->dma_ch); + omap_dma_chan_write(c, CICR, 0); omap_dma_clear_csr(c); - val = c->plat->dma_read(CCR, c->dma_ch); + val = omap_dma_chan_read(c, CCR); if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) { uint32_t sysconfig; unsigned i; - sysconfig = c->plat->dma_read(OCP_SYSCONFIG, c->dma_ch); + sysconfig = omap_dma_glbl_read(od, OCP_SYSCONFIG); val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK; val |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); - c->plat->dma_write(val, OCP_SYSCONFIG, c->dma_ch); + omap_dma_glbl_write(od, OCP_SYSCONFIG, val); - val = c->plat->dma_read(CCR, c->dma_ch); + val = omap_dma_chan_read(c, CCR); val &= ~CCR_ENABLE; - c->plat->dma_write(val, CCR, c->dma_ch); + omap_dma_chan_write(c, CCR, val); /* Wait for sDMA FIFO to drain */ for (i = 0; ; i++) { - val = c->plat->dma_read(CCR, c->dma_ch); + val = omap_dma_chan_read(c, CCR); if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))) break; @@ -237,23 +257,23 @@ static void omap_dma_stop(struct omap_chan *c) "DMA drain did not complete on lch %d\n", c->dma_ch); - c->plat->dma_write(sysconfig, OCP_SYSCONFIG, c->dma_ch); + omap_dma_glbl_write(od, OCP_SYSCONFIG, sysconfig); } else { val &= ~CCR_ENABLE; - c->plat->dma_write(val, CCR, c->dma_ch); + omap_dma_chan_write(c, CCR, val); } mb(); if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) { - val = c->plat->dma_read(CLNK_CTRL, c->dma_ch); + val = omap_dma_chan_read(c, CLNK_CTRL); if (dma_omap1()) val |= 1 << 14; /* set the STOP_LNK bit */ else val &= ~CLNK_CTRL_ENABLE_LNK; - c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); + omap_dma_chan_write(c, CLNK_CTRL, val); } } @@ -273,11 +293,11 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, cxfi = CSFI; } - c->plat->dma_write(sg->addr, cxsa, c->dma_ch); - c->plat->dma_write(0, cxei, c->dma_ch); - c->plat->dma_write(0, cxfi, c->dma_ch); - c->plat->dma_write(sg->en, CEN, c->dma_ch); - c->plat->dma_write(sg->fn, CFN, c->dma_ch); + omap_dma_chan_write(c, cxsa, sg->addr); + omap_dma_chan_write(c, cxei, 0); + omap_dma_chan_write(c, cxfi, 0); + omap_dma_chan_write(c, CEN, sg->en); + omap_dma_chan_write(c, CFN, sg->fn); omap_dma_start(c, d); } @@ -305,9 +325,9 @@ static void omap_dma_start_desc(struct omap_chan *c) */ mb(); - c->plat->dma_write(d->ccr, CCR, c->dma_ch); + omap_dma_chan_write(c, CCR, d->ccr); if (dma_omap1()) - c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch); + omap_dma_chan_write(c, CCR2, d->ccr >> 16); if (d->dir == DMA_DEV_TO_MEM) { cxsa = CSSA; @@ -319,11 +339,11 @@ static void omap_dma_start_desc(struct omap_chan *c) cxfi = CDFI; } - c->plat->dma_write(d->dev_addr, cxsa, c->dma_ch); - c->plat->dma_write(0, cxei, c->dma_ch); - c->plat->dma_write(d->fi, cxfi, c->dma_ch); - c->plat->dma_write(d->csdp, CSDP, c->dma_ch); - c->plat->dma_write(d->clnk_ctrl, CLNK_CTRL, c->dma_ch); + omap_dma_chan_write(c, cxsa, d->dev_addr); + omap_dma_chan_write(c, cxei, 0); + omap_dma_chan_write(c, cxfi, d->fi); + omap_dma_chan_write(c, CSDP, d->csdp); + omap_dma_chan_write(c, CLNK_CTRL, d->clnk_ctrl); omap_dma_start_sg(c, d, 0); } @@ -437,12 +457,12 @@ static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) dma_addr_t addr; if (__dma_omap15xx(od->plat->dma_attr)) - addr = c->plat->dma_read(CPC, c->dma_ch); + addr = omap_dma_chan_read(c, CPC); else - addr = c->plat->dma_read(CSAC, c->dma_ch); + addr = omap_dma_chan_read(c, CSAC); if (od->plat->errata & DMA_ERRATA_3_3 && addr == 0) - addr = c->plat->dma_read(CSAC, c->dma_ch); + addr = omap_dma_chan_read(c, CSAC); if (!__dma_omap15xx(od->plat->dma_attr)) { /* @@ -450,14 +470,14 @@ static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) * not been started (no data has been transferred so far). * Return the programmed source start address in this case. */ - if (c->plat->dma_read(CDAC, c->dma_ch)) - addr = c->plat->dma_read(CSAC, c->dma_ch); + if (omap_dma_chan_read(c, CDAC)) + addr = omap_dma_chan_read(c, CSAC); else - addr = c->plat->dma_read(CSSA, c->dma_ch); + addr = omap_dma_chan_read(c, CSSA); } if (dma_omap1()) - addr |= c->plat->dma_read(CSSA, c->dma_ch) & 0xffff0000; + addr |= omap_dma_chan_read(c, CSSA) & 0xffff0000; return addr; } @@ -468,27 +488,27 @@ static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c) dma_addr_t addr; if (__dma_omap15xx(od->plat->dma_attr)) - addr = c->plat->dma_read(CPC, c->dma_ch); + addr = omap_dma_chan_read(c, CPC); else - addr = c->plat->dma_read(CDAC, c->dma_ch); + addr = omap_dma_chan_read(c, CDAC); /* * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ if (!__dma_omap15xx(od->plat->dma_attr) && addr == 0) { - addr = c->plat->dma_read(CDAC, c->dma_ch); + addr = omap_dma_chan_read(c, CDAC); /* * CDAC == 0 indicates that the DMA transfer on the channel has * not been started (no data has been transferred so far). * Return the programmed destination start address in this case. */ if (addr == 0) - addr = c->plat->dma_read(CDSA, c->dma_ch); + addr = omap_dma_chan_read(c, CDSA); } if (dma_omap1()) - addr |= c->plat->dma_read(CDSA, c->dma_ch) & 0xffff0000; + addr |= omap_dma_chan_read(c, CDSA) & 0xffff0000; return addr; } -- cgit v1.2.3 From b07fd625ac9df7412bd996edbdc298eb343dd501 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Nov 2013 19:26:45 +0000 Subject: dmaengine: omap-dma: cleanup errata 3.3 handling Provide a function to read the CSAC/CDAC register, working around the OMAP 3.2/3.3 erratum (which requires two reads of the register if the first returned zero. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 52 ++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index a1baada7dcd4..1e0018f36384 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -451,28 +451,39 @@ static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr) return size; } +/* + * OMAP 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is + * read before the DMA controller finished disabling the channel. + */ +static uint32_t omap_dma_chan_read_3_3(struct omap_chan *c, unsigned reg) +{ + struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); + uint32_t val; + + val = omap_dma_chan_read(c, reg); + if (val == 0 && od->plat->errata & DMA_ERRATA_3_3) + val = omap_dma_chan_read(c, reg); + + return val; +} + static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) { struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); - dma_addr_t addr; + dma_addr_t addr, cdac; - if (__dma_omap15xx(od->plat->dma_attr)) + if (__dma_omap15xx(od->plat->dma_attr)) { addr = omap_dma_chan_read(c, CPC); - else - addr = omap_dma_chan_read(c, CSAC); - - if (od->plat->errata & DMA_ERRATA_3_3 && addr == 0) - addr = omap_dma_chan_read(c, CSAC); + } else { + addr = omap_dma_chan_read_3_3(c, CSAC); + cdac = omap_dma_chan_read_3_3(c, CDAC); - if (!__dma_omap15xx(od->plat->dma_attr)) { /* * CDAC == 0 indicates that the DMA transfer on the channel has * not been started (no data has been transferred so far). * Return the programmed source start address in this case. */ - if (omap_dma_chan_read(c, CDAC)) - addr = omap_dma_chan_read(c, CSAC); - else + if (cdac == 0) addr = omap_dma_chan_read(c, CSSA); } @@ -487,21 +498,16 @@ static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c) struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); dma_addr_t addr; - if (__dma_omap15xx(od->plat->dma_attr)) + if (__dma_omap15xx(od->plat->dma_attr)) { addr = omap_dma_chan_read(c, CPC); - else - addr = omap_dma_chan_read(c, CDAC); + } else { + addr = omap_dma_chan_read_3_3(c, CDAC); - /* - * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is - * read before the DMA controller finished disabling the channel. - */ - if (!__dma_omap15xx(od->plat->dma_attr) && addr == 0) { - addr = omap_dma_chan_read(c, CDAC); /* - * CDAC == 0 indicates that the DMA transfer on the channel has - * not been started (no data has been transferred so far). - * Return the programmed destination start address in this case. + * CDAC == 0 indicates that the DMA transfer on the channel + * has not been started (no data has been transferred so + * far). Return the programmed destination start address in + * this case. */ if (addr == 0) addr = omap_dma_chan_read(c, CDSA); -- cgit v1.2.3 From 596c471b69249764d8e241b004736878204daa0f Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 10 Dec 2013 11:08:01 +0000 Subject: dmaengine: omap-dma: move register read/writes into omap-dma.c Export the DMA register information from the SoC specific data, such that we can access the registers directly in omap-dma.c, mapping the register region ourselves as well. Rather than calculating the DMA channel register in its entirety for each access, we pre-calculate an offset base address for the allocated DMA channel and then just use the appropriate register offset. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- arch/arm/mach-omap1/dma.c | 4 ++ arch/arm/mach-omap2/dma.c | 18 ++++++--- drivers/dma/omap-dma.c | 96 ++++++++++++++++++++++++++++++++++++++++++----- include/linux/omap-dma.h | 2 + 4 files changed, 105 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index a8c83ccc36fb..4be601b638d7 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -261,9 +261,13 @@ static const struct platform_device_info omap_dma_dev_info = { .name = "omap-dma-engine", .id = -1, .dma_mask = DMA_BIT_MASK(32), + .res = res, + .num_res = 1, }; static struct omap_system_dma_plat_info dma_plat_info __initdata = { + .reg_map = reg_map, + .channel_stride = 0x40, .show_dma_caps = omap1_show_dma_caps, .clear_lch_regs = omap1_clear_lch_regs, .clear_dma = omap1_clear_dma, diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index 6331fc4b4054..5689c88d986d 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -205,12 +205,20 @@ static unsigned configure_dma_errata(void) } static struct omap_system_dma_plat_info dma_plat_info __initdata = { + .reg_map = reg_map, + .channel_stride = 0x60, .show_dma_caps = omap2_show_dma_caps, .clear_dma = omap2_clear_dma, .dma_write = dma_write, .dma_read = dma_read, }; +static struct platform_device_info omap_dma_dev_info = { + .name = "omap-dma-engine", + .id = -1, + .dma_mask = DMA_BIT_MASK(32), +}; + /* One time initializations */ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) { @@ -231,11 +239,15 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) return PTR_ERR(pdev); } + omap_dma_dev_info.res = pdev->resource; + omap_dma_dev_info.num_res = pdev->num_resources; + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(&pdev->dev, "%s: no mem resource\n", __func__); return -EINVAL; } + dma_base = ioremap(mem->start, resource_size(mem)); if (!dma_base) { dev_err(&pdev->dev, "%s: ioremap fail\n", __func__); @@ -256,12 +268,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) return 0; } -static const struct platform_device_info omap_dma_dev_info = { - .name = "omap-dma-engine", - .id = -1, - .dma_mask = DMA_BIT_MASK(32), -}; - static int __init omap2_system_dma_init(void) { struct platform_device *pdev; diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 1e0018f36384..00f8e566cf12 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -27,13 +27,16 @@ struct omap_dmadev { spinlock_t lock; struct tasklet_struct task; struct list_head pending; + void __iomem *base; + const struct omap_dma_reg *reg_map; struct omap_system_dma_plat_info *plat; }; struct omap_chan { struct virt_dma_chan vc; struct list_head node; - struct omap_system_dma_plat_info *plat; + void __iomem *channel_base; + const struct omap_dma_reg *reg_map; struct dma_slave_config cfg; unsigned dma_sig; @@ -170,24 +173,77 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd) kfree(container_of(vd, struct omap_desc, vd)); } +static void omap_dma_write(uint32_t val, unsigned type, void __iomem *addr) +{ + switch (type) { + case OMAP_DMA_REG_16BIT: + writew_relaxed(val, addr); + break; + case OMAP_DMA_REG_2X16BIT: + writew_relaxed(val, addr); + writew_relaxed(val >> 16, addr + 2); + break; + case OMAP_DMA_REG_32BIT: + writel_relaxed(val, addr); + break; + default: + WARN_ON(1); + } +} + +static unsigned omap_dma_read(unsigned type, void __iomem *addr) +{ + unsigned val; + + switch (type) { + case OMAP_DMA_REG_16BIT: + val = readw_relaxed(addr); + break; + case OMAP_DMA_REG_2X16BIT: + val = readw_relaxed(addr); + val |= readw_relaxed(addr + 2) << 16; + break; + case OMAP_DMA_REG_32BIT: + val = readl_relaxed(addr); + break; + default: + WARN_ON(1); + val = 0; + } + + return val; +} + static void omap_dma_glbl_write(struct omap_dmadev *od, unsigned reg, unsigned val) { - od->plat->dma_write(val, reg, 0); + const struct omap_dma_reg *r = od->reg_map + reg; + + WARN_ON(r->stride); + + omap_dma_write(val, r->type, od->base + r->offset); } static unsigned omap_dma_glbl_read(struct omap_dmadev *od, unsigned reg) { - return od->plat->dma_read(reg, 0); + const struct omap_dma_reg *r = od->reg_map + reg; + + WARN_ON(r->stride); + + return omap_dma_read(r->type, od->base + r->offset); } static void omap_dma_chan_write(struct omap_chan *c, unsigned reg, unsigned val) { - c->plat->dma_write(val, reg, c->dma_ch); + const struct omap_dma_reg *r = c->reg_map + reg; + + omap_dma_write(val, r->type, c->channel_base + r->offset); } static unsigned omap_dma_chan_read(struct omap_chan *c, unsigned reg) { - return c->plat->dma_read(reg, c->dma_ch); + const struct omap_dma_reg *r = c->reg_map + reg; + + return omap_dma_read(r->type, c->channel_base + r->offset); } static void omap_dma_clear_csr(struct omap_chan *c) @@ -198,6 +254,12 @@ static void omap_dma_clear_csr(struct omap_chan *c) omap_dma_chan_write(c, CSR, ~0); } +static void omap_dma_assign(struct omap_dmadev *od, struct omap_chan *c, + unsigned lch) +{ + c->channel_base = od->base + od->plat->channel_stride * lch; +} + static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) { struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); @@ -400,18 +462,26 @@ static void omap_dma_sched(unsigned long data) static int omap_dma_alloc_chan_resources(struct dma_chan *chan) { + struct omap_dmadev *od = to_omap_dma_dev(chan->device); struct omap_chan *c = to_omap_dma_chan(chan); + int ret; + + dev_dbg(od->ddev.dev, "allocating channel for %u\n", c->dma_sig); - dev_dbg(c->vc.chan.device->dev, "allocating channel for %u\n", c->dma_sig); + ret = omap_request_dma(c->dma_sig, "DMA engine", omap_dma_callback, + c, &c->dma_ch); - return omap_request_dma(c->dma_sig, "DMA engine", - omap_dma_callback, c, &c->dma_ch); + if (ret >= 0) + omap_dma_assign(od, c, c->dma_ch); + + return ret; } static void omap_dma_free_chan_resources(struct dma_chan *chan) { struct omap_chan *c = to_omap_dma_chan(chan); + c->channel_base = NULL; vchan_free_chan_resources(&c->vc); omap_free_dma(c->dma_ch); @@ -917,7 +987,7 @@ static int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig) if (!c) return -ENOMEM; - c->plat = od->plat; + c->reg_map = od->reg_map; c->dma_sig = dma_sig; c->vc.desc_free = omap_dma_desc_free; vchan_init(&c->vc, &od->ddev); @@ -944,16 +1014,24 @@ static void omap_dma_free(struct omap_dmadev *od) static int omap_dma_probe(struct platform_device *pdev) { struct omap_dmadev *od; + struct resource *res; int rc, i; od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); if (!od) return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + od->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(od->base)) + return PTR_ERR(od->base); + od->plat = omap_get_plat_info(); if (!od->plat) return -EPROBE_DEFER; + od->reg_map = od->plat->reg_map; + dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources; diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 7813636a193d..41a13e70f41f 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -285,6 +285,8 @@ struct omap_dma_reg { /* System DMA platform data structure */ struct omap_system_dma_plat_info { + const struct omap_dma_reg *reg_map; + unsigned channel_stride; struct omap_dma_dev_attr *dma_attr; u32 errata; void (*show_dma_caps)(void); -- cgit v1.2.3 From 6ddeb6d844596cac13c4a3665c0bd61f074a81a7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 10 Dec 2013 19:05:50 +0000 Subject: dmaengine: omap-dma: move IRQ handling to omap-dma Move the interrupt handling for OMAP2+ into omap-dma, rather than using the legacy support in the platform code. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 00f8e566cf12..ec98e718de70 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -30,6 +30,10 @@ struct omap_dmadev { void __iomem *base; const struct omap_dma_reg *reg_map; struct omap_system_dma_plat_info *plat; + bool legacy; + spinlock_t irq_lock; + uint32_t irq_enable_mask; + struct omap_chan *lch_map[32]; }; struct omap_chan { @@ -254,10 +258,22 @@ static void omap_dma_clear_csr(struct omap_chan *c) omap_dma_chan_write(c, CSR, ~0); } +static unsigned omap_dma_get_csr(struct omap_chan *c) +{ + unsigned val = omap_dma_chan_read(c, CSR); + + if (!dma_omap1()) + omap_dma_chan_write(c, CSR, val); + + return val; +} + static void omap_dma_assign(struct omap_dmadev *od, struct omap_chan *c, unsigned lch) { c->channel_base = od->base + od->plat->channel_stride * lch; + + od->lch_map[lch] = c; } static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) @@ -460,32 +476,103 @@ static void omap_dma_sched(unsigned long data) } } +static irqreturn_t omap_dma_irq(int irq, void *devid) +{ + struct omap_dmadev *od = devid; + unsigned status, channel; + + spin_lock(&od->irq_lock); + + status = omap_dma_glbl_read(od, IRQSTATUS_L1); + status &= od->irq_enable_mask; + if (status == 0) { + spin_unlock(&od->irq_lock); + return IRQ_NONE; + } + + while ((channel = ffs(status)) != 0) { + unsigned mask, csr; + struct omap_chan *c; + + channel -= 1; + mask = BIT(channel); + status &= ~mask; + + c = od->lch_map[channel]; + if (c == NULL) { + /* This should never happen */ + dev_err(od->ddev.dev, "invalid channel %u\n", channel); + continue; + } + + csr = omap_dma_get_csr(c); + omap_dma_glbl_write(od, IRQSTATUS_L1, mask); + + omap_dma_callback(channel, csr, c); + } + + spin_unlock(&od->irq_lock); + + return IRQ_HANDLED; +} + static int omap_dma_alloc_chan_resources(struct dma_chan *chan) { struct omap_dmadev *od = to_omap_dma_dev(chan->device); struct omap_chan *c = to_omap_dma_chan(chan); int ret; - dev_dbg(od->ddev.dev, "allocating channel for %u\n", c->dma_sig); + if (od->legacy) { + ret = omap_request_dma(c->dma_sig, "DMA engine", + omap_dma_callback, c, &c->dma_ch); + } else { + ret = omap_request_dma(c->dma_sig, "DMA engine", NULL, NULL, + &c->dma_ch); + } - ret = omap_request_dma(c->dma_sig, "DMA engine", omap_dma_callback, - c, &c->dma_ch); + dev_dbg(od->ddev.dev, "allocating channel %u for %u\n", + c->dma_ch, c->dma_sig); - if (ret >= 0) + if (ret >= 0) { omap_dma_assign(od, c, c->dma_ch); + if (!od->legacy) { + unsigned val; + + spin_lock_irq(&od->irq_lock); + val = BIT(c->dma_ch); + omap_dma_glbl_write(od, IRQSTATUS_L1, val); + od->irq_enable_mask |= val; + omap_dma_glbl_write(od, IRQENABLE_L1, od->irq_enable_mask); + + val = omap_dma_glbl_read(od, IRQENABLE_L0); + val &= ~BIT(c->dma_ch); + omap_dma_glbl_write(od, IRQENABLE_L0, val); + spin_unlock_irq(&od->irq_lock); + } + } + return ret; } static void omap_dma_free_chan_resources(struct dma_chan *chan) { + struct omap_dmadev *od = to_omap_dma_dev(chan->device); struct omap_chan *c = to_omap_dma_chan(chan); + if (!od->legacy) { + spin_lock_irq(&od->irq_lock); + od->irq_enable_mask &= ~BIT(c->dma_ch); + omap_dma_glbl_write(od, IRQENABLE_L1, od->irq_enable_mask); + spin_unlock_irq(&od->irq_lock); + } + c->channel_base = NULL; + od->lch_map[c->dma_ch] = NULL; vchan_free_chan_resources(&c->vc); omap_free_dma(c->dma_ch); - dev_dbg(c->vc.chan.device->dev, "freeing channel for %u\n", c->dma_sig); + dev_dbg(od->ddev.dev, "freeing channel for %u\n", c->dma_sig); } static size_t omap_dma_sg_size(struct omap_sg *sg) @@ -1015,7 +1102,7 @@ static int omap_dma_probe(struct platform_device *pdev) { struct omap_dmadev *od; struct resource *res; - int rc, i; + int rc, i, irq; od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); if (!od) @@ -1045,6 +1132,7 @@ static int omap_dma_probe(struct platform_device *pdev) INIT_LIST_HEAD(&od->ddev.channels); INIT_LIST_HEAD(&od->pending); spin_lock_init(&od->lock); + spin_lock_init(&od->irq_lock); tasklet_init(&od->task, omap_dma_sched, (unsigned long)od); @@ -1056,6 +1144,21 @@ static int omap_dma_probe(struct platform_device *pdev) } } + irq = platform_get_irq(pdev, 1); + if (irq <= 0) { + dev_info(&pdev->dev, "failed to get L1 IRQ: %d\n", irq); + od->legacy = true; + } else { + /* Disable all interrupts */ + od->irq_enable_mask = 0; + omap_dma_glbl_write(od, IRQENABLE_L1, 0); + + rc = devm_request_irq(&pdev->dev, irq, omap_dma_irq, + IRQF_SHARED, "omap-dma-engine", od); + if (rc) + return rc; + } + rc = dma_async_device_register(&od->ddev); if (rc) { pr_warn("OMAP-DMA: failed to register slave DMA engine device: %d\n", @@ -1092,6 +1195,12 @@ static int omap_dma_remove(struct platform_device *pdev) of_dma_controller_free(pdev->dev.of_node); dma_async_device_unregister(&od->ddev); + + if (!od->legacy) { + /* Disable all interrupts */ + omap_dma_glbl_write(od, IRQENABLE_L0, 0); + } + omap_dma_free(od); return 0; -- cgit v1.2.3 From aa4c5b962a7a03eb6b43b3d2677c3677022c1223 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 14 Jan 2014 23:58:10 +0000 Subject: dmaengine: omap-dma: more consolidation of CCR register setup We can move the handling of the DMA synchronisation control out of the prepare functions; this can be pre-calculated when the DMA channel has been allocated, so we don't need to duplicate this in both prepare functions. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 46 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index ec98e718de70..64ceca2920b8 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -41,6 +41,7 @@ struct omap_chan { struct list_head node; void __iomem *channel_base; const struct omap_dma_reg *reg_map; + uint32_t ccr; struct dma_slave_config cfg; unsigned dma_sig; @@ -552,6 +553,21 @@ static int omap_dma_alloc_chan_resources(struct dma_chan *chan) } } + if (dma_omap1()) { + if (__dma_omap16xx(od->plat->dma_attr)) { + c->ccr = CCR_OMAP31_DISABLE; + /* Duplicate what plat-omap/dma.c does */ + c->ccr |= c->dma_ch + 1; + } else { + c->ccr = c->dma_sig & 0x1f; + } + } else { + c->ccr = c->dma_sig & 0x1f; + c->ccr |= (c->dma_sig & ~0x1f) << 14; + } + if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) + c->ccr |= CCR_BUFFERING_DISABLE; + return ret; } @@ -787,7 +803,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->dev_addr = dev_addr; d->es = es; - d->ccr = CCR_SYNC_FRAME; + d->ccr = c->ccr | CCR_SYNC_FRAME; if (dir == DMA_DEV_TO_MEM) d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; else @@ -797,14 +813,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->csdp = es; if (dma_omap1()) { - if (__dma_omap16xx(od->plat->dma_attr)) { - d->ccr |= CCR_OMAP31_DISABLE; - /* Duplicate what plat-omap/dma.c does */ - d->ccr |= c->dma_ch + 1; - } else { - d->ccr |= c->dma_sig & 0x1f; - } - d->cicr |= CICR_TOUT_IE; if (dir == DMA_DEV_TO_MEM) @@ -812,16 +820,11 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( else d->csdp |= CSDP_DST_PORT_TIPB | CSDP_SRC_PORT_EMIFF; } else { - d->ccr |= (c->dma_sig & ~0x1f) << 14; - d->ccr |= c->dma_sig & 0x1f; - if (dir == DMA_DEV_TO_MEM) d->ccr |= CCR_TRIGGER_SRC; d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; } - if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) - d->ccr |= CCR_BUFFERING_DISABLE; if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) d->clnk_ctrl = c->dma_ch; @@ -903,7 +906,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->sg[0].fn = buf_len / period_len; d->sglen = 1; - d->ccr = 0; + d->ccr = c->ccr; if (dir == DMA_DEV_TO_MEM) d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; else @@ -916,14 +919,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp = es; if (dma_omap1()) { - if (__dma_omap16xx(od->plat->dma_attr)) { - d->ccr |= CCR_OMAP31_DISABLE; - /* Duplicate what plat-omap/dma.c does */ - d->ccr |= c->dma_ch + 1; - } else { - d->ccr |= c->dma_sig & 0x1f; - } - d->cicr |= CICR_TOUT_IE; if (dir == DMA_DEV_TO_MEM) @@ -931,9 +926,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( else d->csdp |= CSDP_DST_PORT_MPUI | CSDP_SRC_PORT_EMIFF; } else { - d->ccr |= (c->dma_sig & ~0x1f) << 14; - d->ccr |= c->dma_sig & 0x1f; - if (burst) d->ccr |= CCR_SYNC_PACKET; else @@ -946,8 +938,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64; } - if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) - d->ccr |= CCR_BUFFERING_DISABLE; if (__dma_omap15xx(od->plat->dma_attr)) d->ccr |= CCR_AUTO_INIT | CCR_REPEAT; -- cgit v1.2.3