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 <ya...@emcraft.com> > Cc: Piotr Ziecik <ko...@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 <ko...@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@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/linuxppc-dev _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev