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); |
