[PATCH 3/6] mpc512x_dma: add MPC8308 support
Grant Likely
grant.likely at secretlab.ca
Thu Dec 30 16:35:51 EST 2010
On Wed, Oct 27, 2010 at 01:52:57AM +0200, Ilya Yanok wrote:
> 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 at emcraft.com>
> Cc: Piotr Ziecik <kosmo at semihalf.com>
Merged for -next, thanks.
g.
> ---
> drivers/dma/Kconfig | 2 +-
> drivers/dma/mpc512x_dma.c | 95 +++++++++++++++++++++++++++++++++-----------
> 2 files changed, 72 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index 9520cf0..5c5e95b 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -100,7 +100,7 @@ config FSL_DMA
>
> config MPC512X_DMA
> tristate "Freescale MPC512x built-in DMA engine support"
> - depends on PPC_MPC512x
> + depends on PPC_MPC512x || PPC_MPC831x
> select DMA_ENGINE
> ---help---
> 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 0717527..97b92ec 100644
> --- a/drivers/dma/mpc512x_dma.c
> +++ b/drivers/dma/mpc512x_dma.c
> @@ -1,6 +1,7 @@
> /*
> * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008.
> * Copyright (C) Semihalf 2009
> + * Copyright (C) Ilya Yanok, Emcraft Systems 2010
> *
> * Written by Piotr Ziecik <kosmo at semihalf.com>. Hardware description
> * (defines, structures and comments) was taken from MPC5121 DMA driver
> @@ -70,6 +71,8 @@
> #define MPC_DMA_DMAES_SBE (1 << 1)
> #define MPC_DMA_DMAES_DBE (1 << 0)
>
> +#define MPC_DMA_DMAGPOR_SNOOP_ENABLE (1 << 6)
> +
> #define MPC_DMA_TSIZE_1 0x00
> #define MPC_DMA_TSIZE_2 0x01
> #define MPC_DMA_TSIZE_4 0x02
> @@ -104,7 +107,10 @@ struct __attribute__ ((__packed__)) mpc_dma_regs {
> /* 0x30 */
> u32 dmahrsh; /* DMA hw request status high(ch63~32) */
> u32 dmahrsl; /* DMA hardware request status low(ch31~0) */
> - u32 dmaihsa; /* DMA interrupt high select AXE(ch63~32) */
> + union {
> + u32 dmaihsa; /* DMA interrupt high select AXE(ch63~32) */
> + u32 dmagpor; /* (General purpose register on MPC8308) */
> + };
> u32 dmailsa; /* DMA interrupt low select AXE(ch31~0) */
> /* 0x40 ~ 0xff */
> u32 reserve0[48]; /* Reserved */
> @@ -195,7 +201,9 @@ struct mpc_dma {
> struct mpc_dma_regs __iomem *regs;
> struct mpc_dma_tcd __iomem *tcd;
> int irq;
> + int irq2;
> uint error_status;
> + int is_mpc8308;
>
> /* Lock for error_status field in this structure */
> spinlock_t error_status_lock;
> @@ -307,8 +315,10 @@ static irqreturn_t mpc_dma_irq(int irq, void *data)
> spin_unlock(&mdma->error_status_lock);
>
> /* Handle interrupt on each channel */
> - mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth),
> + if (mdma->dma.chancnt > 32) {
> + mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth),
> in_be32(&mdma->regs->dmaerrh), 32);
> + }
> mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmaintl),
> in_be32(&mdma->regs->dmaerrl), 0);
>
> @@ -562,6 +572,7 @@ static struct dma_async_tx_descriptor *
> mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
> size_t len, unsigned long flags)
> {
> + struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
> struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
> struct mpc_dma_desc *mdesc = NULL;
> 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,
> tcd->dsize = MPC_DMA_TSIZE_32;
> tcd->soff = 32;
> tcd->doff = 32;
> - } else if (IS_ALIGNED(src | dst | len, 16)) {
> + } else if (!mdma->is_mpc8308 && IS_ALIGNED(src | dst | len, 16)) {
> + /* MPC8308 doesn't support 16 byte transfers */
> tcd->ssize = MPC_DMA_TSIZE_16;
> tcd->dsize = MPC_DMA_TSIZE_16;
> tcd->soff = 16;
> @@ -650,6 +662,15 @@ static int __devinit mpc_dma_probe(struct platform_device *op,
> return -EINVAL;
> }
>
> + if (of_device_is_compatible(dn, "fsl,mpc8308-dma")) {
> + mdma->is_mpc8308 = 1;
> + mdma->irq2 = irq_of_parse_and_map(dn, 1);
> + if (mdma->irq2 == NO_IRQ) {
> + dev_err(dev, "Error mapping IRQ!\n");
> + return -EINVAL;
> + }
> + }
> +
> retval = of_address_to_resource(dn, 0, &res);
> if (retval) {
> dev_err(dev, "Error parsing memory region!\n");
> @@ -680,11 +701,23 @@ static int __devinit mpc_dma_probe(struct platform_device *op,
> return -EINVAL;
> }
>
> + if (mdma->is_mpc8308) {
> + retval = devm_request_irq(dev, mdma->irq2, &mpc_dma_irq, 0,
> + DRV_NAME, mdma);
> + if (retval) {
> + dev_err(dev, "Error requesting IRQ2!\n");
> + return -EINVAL;
> + }
> + }
> +
> spin_lock_init(&mdma->error_status_lock);
>
> dma = &mdma->dma;
> dma->dev = dev;
> - dma->chancnt = MPC_DMA_CHANNELS;
> + if (!mdma->is_mpc8308)
> + dma->chancnt = MPC_DMA_CHANNELS;
> + else
> + dma->chancnt = 16; /* MPC8308 DMA has only 16 channels */
> dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources;
> dma->device_free_chan_resources = mpc_dma_free_chan_resources;
> dma->device_issue_pending = mpc_dma_issue_pending;
> @@ -720,26 +753,40 @@ static int __devinit mpc_dma_probe(struct platform_device *op,
> * - Round-robin group arbitration,
> * - Round-robin channel arbitration.
> */
> - out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
> - MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
> -
> - /* Disable hardware DMA requests */
> - out_be32(&mdma->regs->dmaerqh, 0);
> - out_be32(&mdma->regs->dmaerql, 0);
> -
> - /* Disable error interrupts */
> - out_be32(&mdma->regs->dmaeeih, 0);
> - out_be32(&mdma->regs->dmaeeil, 0);
> -
> - /* Clear interrupts status */
> - out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
> - out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
> - out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
> - out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
> -
> - /* Route interrupts to IPIC */
> - out_be32(&mdma->regs->dmaihsa, 0);
> - out_be32(&mdma->regs->dmailsa, 0);
> + if (!mdma->is_mpc8308) {
> + out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
> + MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
> +
> + /* Disable hardware DMA requests */
> + out_be32(&mdma->regs->dmaerqh, 0);
> + out_be32(&mdma->regs->dmaerql, 0);
> +
> + /* Disable error interrupts */
> + out_be32(&mdma->regs->dmaeeih, 0);
> + out_be32(&mdma->regs->dmaeeil, 0);
> +
> + /* Clear interrupts status */
> + out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
> + out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
> + out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
> + out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
> +
> + /* Route interrupts to IPIC */
> + out_be32(&mdma->regs->dmaihsa, 0);
> + out_be32(&mdma->regs->dmailsa, 0);
> + } else {
> + /* MPC8308 has 16 channels and lacks some registers */
> + out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_ERCA);
> +
> + /* enable snooping */
> + out_be32(&mdma->regs->dmagpor, MPC_DMA_DMAGPOR_SNOOP_ENABLE);
> + /* Disable error interrupts */
> + out_be32(&mdma->regs->dmaeeil, 0);
> +
> + /* Clear interrupts status */
> + out_be32(&mdma->regs->dmaintl, 0xFFFF);
> + out_be32(&mdma->regs->dmaerrl, 0xFFFF);
> + }
>
> /* Register DMA engine */
> dev_set_drvdata(dev, mdma);
> --
> 1.7.2.3
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
More information about the Linuxppc-dev
mailing list