diff options
author | Ilya Yanok <yanok@emcraft.com> | 2010-10-26 19:52:57 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-12-30 00:29:02 -0500 |
commit | ba2eea251f815b3674cde13ecdba4772332bf56e (patch) | |
tree | 858c0d3657b5aabed3bcd5f5fbf677dd3f95d9f9 | |
parent | 2862559e8a1e7c47bb3003f0edbc9db9009dc32b (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/Kconfig | 2 | ||||
-rw-r--r-- | drivers/dma/mpc512x_dma.c | 95 |
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 | ||
110 | config MPC512X_DMA | 110 | config 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 * | |||
562 | mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, | 572 | mpc_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); |