Skip to content

Commit

Permalink
powerpc/512x: add MPC8308 dma support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ilya Yanok authored and Grant Likely committed Dec 30, 2010
1 parent 2862559 commit ba2eea2
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 25 deletions.
2 changes: 1 addition & 1 deletion drivers/dma/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,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.
Expand Down
95 changes: 71 additions & 24 deletions drivers/dma/mpc512x_dma.c
Original file line number Diff line number Diff line change
@@ -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@semihalf.com>. Hardware description
* (defines, structures and comments) was taken from MPC5121 DMA driver
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit ba2eea2

Please sign in to comment.