Skip to content

Commit

Permalink
[ARM] dma: rejig DMA initialization
Browse files Browse the repository at this point in the history
Rather than having the central DMA multiplexer call the architecture
specific DMA initialization function, have each architecture DMA
initialization function use core_initcall(), and register each DMA
channel separately with the multiplexer.

This removes the array of dma structures in the central multiplexer,
replacing it with an array of pointers instead; this is more flexible
since it allows the drivers to wrap the DMA structure (eventually
allowing us to transition non-ISA DMA drivers away.)

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Russell King authored and Russell King committed Dec 11, 2008
1 parent 3afb6e9 commit 2f757f2
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 47 deletions.
12 changes: 7 additions & 5 deletions arch/arm/include/asm/mach/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ struct dma_struct {
struct dma_ops *d_ops;
};

/* Prototype: void arch_dma_init(dma)
* Purpose : Initialise architecture specific DMA
* Params : dma - pointer to array of DMA structures
/*
* isa_dma_add - add an ISA-style DMA channel
*/
extern void arch_dma_init(dma_t *dma);
extern int isa_dma_add(unsigned int, dma_t *dma);

extern void isa_init_dma(dma_t *dma);
/*
* Add the ISA DMA controller. Always takes channels 0-7.
*/
extern void isa_init_dma(void);
18 changes: 15 additions & 3 deletions arch/arm/kernel/dma-isa.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,12 @@ static struct resource dma_resources[] = { {
.end = 0x048f
} };

void __init isa_init_dma(dma_t *dma)
static dma_t isa_dma[8];

/*
* ISA DMA always starts at channel 0
*/
void __init isa_init_dma(void)
{
/*
* Try to autodetect presence of an ISA DMA controller.
Expand All @@ -178,10 +183,10 @@ void __init isa_init_dma(dma_t *dma)
outb(0xaa, 0x00);

if (inb(0) == 0x55 && inb(0) == 0xaa) {
int chan, i;
unsigned int chan, i;

for (chan = 0; chan < 8; chan++) {
dma[chan].d_ops = &isa_dma_ops;
isa_dma[chan].d_ops = &isa_dma_ops;
isa_disable_dma(chan, NULL);
}

Expand Down Expand Up @@ -217,5 +222,12 @@ void __init isa_init_dma(dma_t *dma)

for (i = 0; i < ARRAY_SIZE(dma_resources); i++)
request_resource(&ioport_resource, dma_resources + i);

for (chan = 0; chan < 8; chan++) {
int ret = isa_dma_add(chan, &isa_dma[chan]);
if (ret)
printk(KERN_ERR "ISADMA%u: unable to register: %d\n",
chan, ret);
}
}
}
25 changes: 13 additions & 12 deletions arch/arm/kernel/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,24 @@
DEFINE_SPINLOCK(dma_spin_lock);
EXPORT_SYMBOL(dma_spin_lock);

static dma_t dma_chan[MAX_DMA_CHANNELS];
static dma_t *dma_chan[MAX_DMA_CHANNELS];

static inline dma_t *dma_channel(unsigned int chan)
{
dma_t *dma = dma_chan + chan;

if (chan >= MAX_DMA_CHANNELS || !dma->d_ops)
if (chan >= MAX_DMA_CHANNELS)
return NULL;

return dma;
return dma_chan[chan];
}

int __init isa_dma_add(unsigned int chan, dma_t *dma)
{
if (!dma->d_ops)
return -EINVAL;
if (dma_chan[chan])
return -EBUSY;
dma_chan[chan] = dma;
return 0;
}

/*
Expand Down Expand Up @@ -252,10 +260,3 @@ int get_dma_residue(unsigned int chan)
return ret;
}
EXPORT_SYMBOL(get_dma_residue);

static int __init init_dma(void)
{
arch_dma_init(dma_chan);
return 0;
}
core_initcall(init_dma);
6 changes: 4 additions & 2 deletions arch/arm/mach-footbridge/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,16 @@ static struct dma_ops fb_dma_ops = {
};
#endif

void __init arch_dma_init(dma_t *dma)
static int __init fb_dma_init(void)
{
#if 0
dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops;
dma[_DC21285_DMA(1)].d_ops = &fb_dma_ops;
#endif
#ifdef CONFIG_ISA_DMA
if (footbridge_cfn_mode())
isa_init_dma(dma + _ISA_DMA(0));
isa_init_dma();
#endif
return 0;
}
core_initcall(fb_dma_init);
68 changes: 45 additions & 23 deletions arch/arm/mach-rpc/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,40 +302,62 @@ static struct dma_ops sound_dma_ops = {
.disable = sound_enable_disable_dma,
};

void __init arch_dma_init(dma_t *dma)
static dma_t iomd_dma[6];

static dma_t floppy_dma = {
.dma_irq = FIQ_FLOPPYDATA,
.d_ops = &floppy_dma_ops,
};

static dma_t sound_dma = {
.d_ops = &sound_dma_ops,
};

static int __init rpc_dma_init(void)
{
unsigned int i;
int ret;

iomd_writeb(0, IOMD_IO0CR);
iomd_writeb(0, IOMD_IO1CR);
iomd_writeb(0, IOMD_IO2CR);
iomd_writeb(0, IOMD_IO3CR);

iomd_writeb(0xa0, IOMD_DMATCR);

dma[DMA_0].dma_base = IOMD_IO0CURA;
dma[DMA_0].dma_irq = IRQ_DMA0;
dma[DMA_0].d_ops = &iomd_dma_ops;
dma[DMA_1].dma_base = IOMD_IO1CURA;
dma[DMA_1].dma_irq = IRQ_DMA1;
dma[DMA_1].d_ops = &iomd_dma_ops;
dma[DMA_2].dma_base = IOMD_IO2CURA;
dma[DMA_2].dma_irq = IRQ_DMA2;
dma[DMA_2].d_ops = &iomd_dma_ops;
dma[DMA_3].dma_base = IOMD_IO3CURA;
dma[DMA_3].dma_irq = IRQ_DMA3;
dma[DMA_3].d_ops = &iomd_dma_ops;
dma[DMA_S0].dma_base = IOMD_SD0CURA;
dma[DMA_S0].dma_irq = IRQ_DMAS0;
dma[DMA_S0].d_ops = &iomd_dma_ops;
dma[DMA_S1].dma_base = IOMD_SD1CURA;
dma[DMA_S1].dma_irq = IRQ_DMAS1;
dma[DMA_S1].d_ops = &iomd_dma_ops;
dma[DMA_VIRTUAL_FLOPPY].dma_irq = FIQ_FLOPPYDATA;
dma[DMA_VIRTUAL_FLOPPY].d_ops = &floppy_dma_ops;
dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops;

/*
* Setup DMA channels 2,3 to be for podules
* and channels 0,1 for internal devices
*/
iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);

iomd_dma[DMA_0].dma_base = IOMD_IO0CURA;
iomd_dma[DMA_0].dma_irq = IRQ_DMA0;
iomd_dma[DMA_1].dma_base = IOMD_IO1CURA;
iomd_dma[DMA_1].dma_irq = IRQ_DMA1;
iomd_dma[DMA_2].dma_base = IOMD_IO2CURA;
iomd_dma[DMA_2].dma_irq = IRQ_DMA2;
iomd_dma[DMA_3].dma_base = IOMD_IO3CURA;
iomd_dma[DMA_3].dma_irq = IRQ_DMA3;
iomd_dma[DMA_S0].dma_base = IOMD_SD0CURA;
iomd_dma[DMA_S0].dma_irq = IRQ_DMAS0;
iomd_dma[DMA_S1].dma_base = IOMD_SD1CURA;
iomd_dma[DMA_S1].dma_irq = IRQ_DMAS1;

for (i = DMA_0; i <= DMA_S1; i++) {
iomd_dma[i].d_ops = &iomd_dma_ops;

ret = isa_dma_add(i, &iomd_dma[i]);
if (ret)
printk("IOMDDMA%u: unable to register: %d\n", i, ret);
}

ret = isa_dma_add(DMA_VIRTUAL_FLOPPY, &floppy_dma);
if (ret)
printk("IOMDFLOPPY: unable to register: %d\n", ret);
ret = isa_dma_add(DMA_VIRTUAL_SOUND, &sound_dma);
if (ret)
printk("IOMDSOUND: unable to register: %d\n", ret);
return 0;
}
core_initcall(rpc_dma_init);
6 changes: 4 additions & 2 deletions arch/arm/mach-shark/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
#include <asm/dma.h>
#include <asm/mach/dma.h>

void __init arch_dma_init(dma_t *dma)
static int __init shark_dma_init(void)
{
#ifdef CONFIG_ISA_DMA
isa_init_dma(dma);
isa_init_dma();
#endif
return 0;
}
core_initcall(shark_dma_init);

0 comments on commit 2f757f2

Please sign in to comment.