aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlya Yanok <yanok@emcraft.com>2010-10-26 19:52:57 -0400
committerGrant Likely <grant.likely@secretlab.ca>2010-12-30 00:29:02 -0500
commitba2eea251f815b3674cde13ecdba4772332bf56e (patch)
tree858c0d3657b5aabed3bcd5f5fbf677dd3f95d9f9
parent2862559e8a1e7c47bb3003f0edbc9db9009dc32b (diff)
powerpc/512x: add MPC8308 dma support
MPC8308 has pretty much the same DMA controller as MPC5121 and this patch adds support for MPC8308 to the mpc512x_dma driver. Signed-off-by: Ilya Yanok <yanok@emcraft.com> Acked-by: Wolfgang Denk <wd@denx.de> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r--drivers/dma/Kconfig2
-rw-r--r--drivers/dma/mpc512x_dma.c95
2 files changed, 72 insertions, 25 deletions
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 6ee23592700a..ef138731c0ea 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -109,7 +109,7 @@ config FSL_DMA
109 109
110config MPC512X_DMA 110config MPC512X_DMA
111 tristate "Freescale MPC512x built-in DMA engine support" 111 tristate "Freescale MPC512x built-in DMA engine support"
112 depends on PPC_MPC512x 112 depends on PPC_MPC512x || PPC_MPC831x
113 select DMA_ENGINE 113 select DMA_ENGINE
114 ---help--- 114 ---help---
115 Enable support for the Freescale MPC512x built-in DMA engine. 115 Enable support for the Freescale MPC512x built-in DMA engine.
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 071752727718..97b92ecb1427 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008. 2 * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008.
3 * Copyright (C) Semihalf 2009 3 * Copyright (C) Semihalf 2009
4 * Copyright (C) Ilya Yanok, Emcraft Systems 2010
4 * 5 *
5 * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description 6 * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description
6 * (defines, structures and comments) was taken from MPC5121 DMA driver 7 * (defines, structures and comments) was taken from MPC5121 DMA driver
@@ -70,6 +71,8 @@
70#define MPC_DMA_DMAES_SBE (1 << 1) 71#define MPC_DMA_DMAES_SBE (1 << 1)
71#define MPC_DMA_DMAES_DBE (1 << 0) 72#define MPC_DMA_DMAES_DBE (1 << 0)
72 73
74#define MPC_DMA_DMAGPOR_SNOOP_ENABLE (1 << 6)
75
73#define MPC_DMA_TSIZE_1 0x00 76#define MPC_DMA_TSIZE_1 0x00
74#define MPC_DMA_TSIZE_2 0x01 77#define MPC_DMA_TSIZE_2 0x01
75#define MPC_DMA_TSIZE_4 0x02 78#define MPC_DMA_TSIZE_4 0x02
@@ -104,7 +107,10 @@ struct __attribute__ ((__packed__)) mpc_dma_regs {
104 /* 0x30 */ 107 /* 0x30 */
105 u32 dmahrsh; /* DMA hw request status high(ch63~32) */ 108 u32 dmahrsh; /* DMA hw request status high(ch63~32) */
106 u32 dmahrsl; /* DMA hardware request status low(ch31~0) */ 109 u32 dmahrsl; /* DMA hardware request status low(ch31~0) */
107 u32 dmaihsa; /* DMA interrupt high select AXE(ch63~32) */ 110 union {
111 u32 dmaihsa; /* DMA interrupt high select AXE(ch63~32) */
112 u32 dmagpor; /* (General purpose register on MPC8308) */
113 };
108 u32 dmailsa; /* DMA interrupt low select AXE(ch31~0) */ 114 u32 dmailsa; /* DMA interrupt low select AXE(ch31~0) */
109 /* 0x40 ~ 0xff */ 115 /* 0x40 ~ 0xff */
110 u32 reserve0[48]; /* Reserved */ 116 u32 reserve0[48]; /* Reserved */
@@ -195,7 +201,9 @@ struct mpc_dma {
195 struct mpc_dma_regs __iomem *regs; 201 struct mpc_dma_regs __iomem *regs;
196 struct mpc_dma_tcd __iomem *tcd; 202 struct mpc_dma_tcd __iomem *tcd;
197 int irq; 203 int irq;
204 int irq2;
198 uint error_status; 205 uint error_status;
206 int is_mpc8308;
199 207
200 /* Lock for error_status field in this structure */ 208 /* Lock for error_status field in this structure */
201 spinlock_t error_status_lock; 209 spinlock_t error_status_lock;
@@ -307,8 +315,10 @@ static irqreturn_t mpc_dma_irq(int irq, void *data)
307 spin_unlock(&mdma->error_status_lock); 315 spin_unlock(&mdma->error_status_lock);
308 316
309 /* Handle interrupt on each channel */ 317 /* Handle interrupt on each channel */
310 mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth), 318 if (mdma->dma.chancnt > 32) {
319 mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth),
311 in_be32(&mdma->regs->dmaerrh), 32); 320 in_be32(&mdma->regs->dmaerrh), 32);
321 }
312 mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmaintl), 322 mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmaintl),
313 in_be32(&mdma->regs->dmaerrl), 0); 323 in_be32(&mdma->regs->dmaerrl), 0);
314 324
@@ -562,6 +572,7 @@ static struct dma_async_tx_descriptor *
562mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, 572mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
563 size_t len, unsigned long flags) 573 size_t len, unsigned long flags)
564{ 574{
575 struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
565 struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan); 576 struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
566 struct mpc_dma_desc *mdesc = NULL; 577 struct mpc_dma_desc *mdesc = NULL;
567 struct mpc_dma_tcd *tcd; 578 struct mpc_dma_tcd *tcd;
@@ -590,7 +601,8 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
590 tcd->dsize = MPC_DMA_TSIZE_32; 601 tcd->dsize = MPC_DMA_TSIZE_32;
591 tcd->soff = 32; 602 tcd->soff = 32;
592 tcd->doff = 32; 603 tcd->doff = 32;
593 } else if (IS_ALIGNED(src | dst | len, 16)) { 604 } else if (!mdma->is_mpc8308 && IS_ALIGNED(src | dst | len, 16)) {
605 /* MPC8308 doesn't support 16 byte transfers */
594 tcd->ssize = MPC_DMA_TSIZE_16; 606 tcd->ssize = MPC_DMA_TSIZE_16;
595 tcd->dsize = MPC_DMA_TSIZE_16; 607 tcd->dsize = MPC_DMA_TSIZE_16;
596 tcd->soff = 16; 608 tcd->soff = 16;
@@ -650,6 +662,15 @@ static int __devinit mpc_dma_probe(struct platform_device *op,
650 return -EINVAL; 662 return -EINVAL;
651 } 663 }
652 664
665 if (of_device_is_compatible(dn, "fsl,mpc8308-dma")) {
666 mdma->is_mpc8308 = 1;
667 mdma->irq2 = irq_of_parse_and_map(dn, 1);
668 if (mdma->irq2 == NO_IRQ) {
669 dev_err(dev, "Error mapping IRQ!\n");
670 return -EINVAL;
671 }
672 }
673
653 retval = of_address_to_resource(dn, 0, &res); 674 retval = of_address_to_resource(dn, 0, &res);
654 if (retval) { 675 if (retval) {
655 dev_err(dev, "Error parsing memory region!\n"); 676 dev_err(dev, "Error parsing memory region!\n");
@@ -680,11 +701,23 @@ static int __devinit mpc_dma_probe(struct platform_device *op,
680 return -EINVAL; 701 return -EINVAL;
681 } 702 }
682 703
704 if (mdma->is_mpc8308) {
705 retval = devm_request_irq(dev, mdma->irq2, &mpc_dma_irq, 0,
706 DRV_NAME, mdma);
707 if (retval) {
708 dev_err(dev, "Error requesting IRQ2!\n");
709 return -EINVAL;
710 }
711 }
712
683 spin_lock_init(&mdma->error_status_lock); 713 spin_lock_init(&mdma->error_status_lock);
684 714
685 dma = &mdma->dma; 715 dma = &mdma->dma;
686 dma->dev = dev; 716 dma->dev = dev;
687 dma->chancnt = MPC_DMA_CHANNELS; 717 if (!mdma->is_mpc8308)
718 dma->chancnt = MPC_DMA_CHANNELS;
719 else
720 dma->chancnt = 16; /* MPC8308 DMA has only 16 channels */
688 dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources; 721 dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources;
689 dma->device_free_chan_resources = mpc_dma_free_chan_resources; 722 dma->device_free_chan_resources = mpc_dma_free_chan_resources;
690 dma->device_issue_pending = mpc_dma_issue_pending; 723 dma->device_issue_pending = mpc_dma_issue_pending;
@@ -720,26 +753,40 @@ static int __devinit mpc_dma_probe(struct platform_device *op,
720 * - Round-robin group arbitration, 753 * - Round-robin group arbitration,
721 * - Round-robin channel arbitration. 754 * - Round-robin channel arbitration.
722 */ 755 */
723 out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG | 756 if (!mdma->is_mpc8308) {
724 MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA); 757 out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
725 758 MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
726 /* Disable hardware DMA requests */ 759
727 out_be32(&mdma->regs->dmaerqh, 0); 760 /* Disable hardware DMA requests */
728 out_be32(&mdma->regs->dmaerql, 0); 761 out_be32(&mdma->regs->dmaerqh, 0);
729 762 out_be32(&mdma->regs->dmaerql, 0);
730 /* Disable error interrupts */ 763
731 out_be32(&mdma->regs->dmaeeih, 0); 764 /* Disable error interrupts */
732 out_be32(&mdma->regs->dmaeeil, 0); 765 out_be32(&mdma->regs->dmaeeih, 0);
733 766 out_be32(&mdma->regs->dmaeeil, 0);
734 /* Clear interrupts status */ 767
735 out_be32(&mdma->regs->dmainth, 0xFFFFFFFF); 768 /* Clear interrupts status */
736 out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF); 769 out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
737 out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF); 770 out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
738 out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF); 771 out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
739 772 out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
740 /* Route interrupts to IPIC */ 773
741 out_be32(&mdma->regs->dmaihsa, 0); 774 /* Route interrupts to IPIC */
742 out_be32(&mdma->regs->dmailsa, 0); 775 out_be32(&mdma->regs->dmaihsa, 0);
776 out_be32(&mdma->regs->dmailsa, 0);
777 } else {
778 /* MPC8308 has 16 channels and lacks some registers */
779 out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_ERCA);
780
781 /* enable snooping */
782 out_be32(&mdma->regs->dmagpor, MPC_DMA_DMAGPOR_SNOOP_ENABLE);
783 /* Disable error interrupts */
784 out_be32(&mdma->regs->dmaeeil, 0);
785
786 /* Clear interrupts status */
787 out_be32(&mdma->regs->dmaintl, 0xFFFF);
788 out_be32(&mdma->regs->dmaerrl, 0xFFFF);
789 }
743 790
744 /* Register DMA engine */ 791 /* Register DMA engine */
745 dev_set_drvdata(dev, mdma); 792 dev_set_drvdata(dev, mdma);