From 5a9eb8da8b95fce21eb2dd39fe71b2b7882ce89a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 19 Mar 2009 15:02:33 +0000 Subject: [ARM] S3C24XX: Move plat/dma.h Move the platform dma.h to dma-plat.h to ensure it doen't get confused with plat/dma.h Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index 440c014..6248f41 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c index 9e34785..f888d4e 100644 --- a/arch/arm/mach-s3c2412/dma.c +++ b/arch/arm/mach-s3c2412/dma.c @@ -20,7 +20,7 @@ #include -#include +#include #include #include diff --git a/arch/arm/mach-s3c2440/dma.c b/arch/arm/mach-s3c2440/dma.c index 69b6cf3..895783f 100644 --- a/arch/arm/mach-s3c2440/dma.c +++ b/arch/arm/mach-s3c2440/dma.c @@ -19,7 +19,7 @@ #include -#include +#include #include #include diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c index 8430e58..825b718 100644 --- a/arch/arm/mach-s3c2443/dma.c +++ b/arch/arm/mach-s3c2443/dma.c @@ -20,7 +20,7 @@ #include -#include +#include #include #include diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index aee2aeb..d3d1375 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -34,7 +34,7 @@ #include -#include +#include /* io map for dma */ static void __iomem *dma_base; diff --git a/arch/arm/plat-s3c24xx/include/plat/dma-plat.h b/arch/arm/plat-s3c24xx/include/plat/dma-plat.h new file mode 100644 index 0000000..fbe84af --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/plat/dma-plat.h @@ -0,0 +1,82 @@ +/* linux/arch/arm/plat-s3c24xx/include/plat/dma-plat.h + * + * Copyright (C) 2006 Simtec Electronics + * Ben Dooks + * + * Samsung S3C24XX DMA support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +extern struct sysdev_class dma_sysclass; +extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; + +#define DMA_CH_VALID (1<<31) +#define DMA_CH_NEVER (1<<30) + +struct s3c24xx_dma_addr { + unsigned long from; + unsigned long to; +}; + +/* struct s3c24xx_dma_map + * + * this holds the mapping information for the channel selected + * to be connected to the specified device +*/ + +struct s3c24xx_dma_map { + const char *name; + struct s3c24xx_dma_addr hw_addr; + + unsigned long channels[S3C2410_DMA_CHANNELS]; + unsigned long channels_rx[S3C2410_DMA_CHANNELS]; +}; + +struct s3c24xx_dma_selection { + struct s3c24xx_dma_map *map; + unsigned long map_size; + unsigned long dcon_mask; + + void (*select)(struct s3c2410_dma_chan *chan, + struct s3c24xx_dma_map *map); + + void (*direction)(struct s3c2410_dma_chan *chan, + struct s3c24xx_dma_map *map, + enum s3c2410_dmasrc dir); +}; + +extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel); + +/* struct s3c24xx_dma_order_ch + * + * channel map for one of the `enum dma_ch` dma channels. the list + * entry contains a set of low-level channel numbers, orred with + * DMA_CH_VALID, which are checked in the order in the array. +*/ + +struct s3c24xx_dma_order_ch { + unsigned int list[S3C2410_DMA_CHANNELS]; /* list of channels */ + unsigned int flags; /* flags */ +}; + +/* struct s3c24xx_dma_order + * + * information provided by either the core or the board to give the + * dma system a hint on how to allocate channels +*/ + +struct s3c24xx_dma_order { + struct s3c24xx_dma_order_ch channels[DMACH_MAX]; +}; + +extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map); + +/* DMA init code, called from the cpu support code */ + +extern int s3c2410_dma_init(void); + +extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq, + unsigned int stride); diff --git a/arch/arm/plat-s3c24xx/include/plat/dma.h b/arch/arm/plat-s3c24xx/include/plat/dma.h deleted file mode 100644 index c78efe3..0000000 --- a/arch/arm/plat-s3c24xx/include/plat/dma.h +++ /dev/null @@ -1,82 +0,0 @@ -/* linux/include/asm-arm/plat-s3c24xx/dma.h - * - * Copyright (C) 2006 Simtec Electronics - * Ben Dooks - * - * Samsung S3C24XX DMA support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -extern struct sysdev_class dma_sysclass; -extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; - -#define DMA_CH_VALID (1<<31) -#define DMA_CH_NEVER (1<<30) - -struct s3c24xx_dma_addr { - unsigned long from; - unsigned long to; -}; - -/* struct s3c24xx_dma_map - * - * this holds the mapping information for the channel selected - * to be connected to the specified device -*/ - -struct s3c24xx_dma_map { - const char *name; - struct s3c24xx_dma_addr hw_addr; - - unsigned long channels[S3C2410_DMA_CHANNELS]; - unsigned long channels_rx[S3C2410_DMA_CHANNELS]; -}; - -struct s3c24xx_dma_selection { - struct s3c24xx_dma_map *map; - unsigned long map_size; - unsigned long dcon_mask; - - void (*select)(struct s3c2410_dma_chan *chan, - struct s3c24xx_dma_map *map); - - void (*direction)(struct s3c2410_dma_chan *chan, - struct s3c24xx_dma_map *map, - enum s3c2410_dmasrc dir); -}; - -extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel); - -/* struct s3c24xx_dma_order_ch - * - * channel map for one of the `enum dma_ch` dma channels. the list - * entry contains a set of low-level channel numbers, orred with - * DMA_CH_VALID, which are checked in the order in the array. -*/ - -struct s3c24xx_dma_order_ch { - unsigned int list[S3C2410_DMA_CHANNELS]; /* list of channels */ - unsigned int flags; /* flags */ -}; - -/* struct s3c24xx_dma_order - * - * information provided by either the core or the board to give the - * dma system a hint on how to allocate channels -*/ - -struct s3c24xx_dma_order { - struct s3c24xx_dma_order_ch channels[DMACH_MAX]; -}; - -extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map); - -/* DMA init code, called from the cpu support code */ - -extern int s3c2410_dma_init(void); - -extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq, - unsigned int stride); -- cgit v0.10.2 From 8970ef47d56fd3db28ee798b9d400caf08abd924 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 19 Mar 2009 15:02:34 +0000 Subject: [ARM] S3C24XX: Remove hardware specific registers from DMA calls The S3C24XX DMA API channel configuration registers are being passed values comprised of register values which makes it hard to move the API to cover both the S3C24XX and S3C64XX. These values can be calculated from knowing which device the channel is connected to, so remove them from the two calls s3c2410_dma_config and s3c2410_dma_devconfig. Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h index 13358ce..acaef67 100644 --- a/arch/arm/mach-s3c2410/include/mach/dma.h +++ b/arch/arm/mach-s3c2410/include/mach/dma.h @@ -206,10 +206,10 @@ struct s3c2410_dma_chan { /* channel configuration */ enum s3c2410_dmasrc source; + enum dma_ch req_ch; unsigned long dev_addr; unsigned long load_timeout; unsigned int flags; /* channel flags */ - unsigned int hw_cfg; /* last hw config */ struct s3c24xx_dma_map *map; /* channel hw maps */ @@ -290,7 +290,7 @@ extern int s3c2410_dma_enqueue(unsigned int channel, void *id, * configure the dma channel */ -extern int s3c2410_dma_config(unsigned int channel, int xferunit, int dcon); +extern int s3c2410_dma_config(unsigned int channel, int xferunit); /* s3c2410_dma_devconfig * @@ -298,7 +298,7 @@ extern int s3c2410_dma_config(unsigned int channel, int xferunit, int dcon); */ extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, - int hwcfg, unsigned long devaddr); + unsigned long devaddr); /* s3c2410_dma_getposition * diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index d3d1375..dc58a0d 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -1038,14 +1038,13 @@ EXPORT_SYMBOL(s3c2410_dma_ctrl); /* s3c2410_dma_config * * xfersize: size of unit in bytes (1,2,4) - * dcon: base value of the DCONx register */ int s3c2410_dma_config(unsigned int channel, - int xferunit, - int dcon) + int xferunit) { struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); + unsigned int dcon; pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n", __func__, channel, xferunit, dcon); @@ -1055,10 +1054,33 @@ int s3c2410_dma_config(unsigned int channel, pr_debug("%s: Initial dcon is %08x\n", __func__, dcon); - dcon |= chan->dcon & dma_sel.dcon_mask; + dcon = chan->dcon & dma_sel.dcon_mask; pr_debug("%s: New dcon is %08x\n", __func__, dcon); + switch (chan->req_ch) { + case DMACH_I2S_IN: + case DMACH_I2S_OUT: + case DMACH_PCM_IN: + case DMACH_PCM_OUT: + case DMACH_MIC_IN: + default: + dcon |= S3C2410_DCON_HANDSHAKE; + dcon |= S3C2410_DCON_SYNC_PCLK; + break; + + case DMACH_SDI: + /* note, ensure if need HANDSHAKE or not */ + dcon |= S3C2410_DCON_SYNC_PCLK; + break; + + case DMACH_XD0: + case DMACH_XD1: + dcon |= S3C2410_DCON_HANDSHAKE; + dcon |= S3C2410_DCON_SYNC_HCLK; + break; + } + switch (xferunit) { case 1: dcon |= S3C2410_DCON_BYTE; @@ -1150,29 +1172,38 @@ EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); * source: S3C2410_DMASRC_HW: source is hardware * S3C2410_DMASRC_MEM: source is memory * - * hwcfg: the value for xxxSTCn register, - * bit 0: 0=increment pointer, 1=leave pointer - * bit 1: 0=source is AHB, 1=source is APB - * * devaddr: physical address of the source */ int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, - int hwcfg, unsigned long devaddr) { struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); + unsigned int hwcfg; if (chan == NULL) return -EINVAL; - pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n", - __func__, (int)source, hwcfg, devaddr); + pr_debug("%s: source=%d, devaddr=%08lx\n", + __func__, (int)source, devaddr); chan->source = source; chan->dev_addr = devaddr; - chan->hw_cfg = hwcfg; + + switch (chan->req_ch) { + case DMACH_XD0: + case DMACH_XD1: + hwcfg = 0; /* AHB */ + break; + + default: + hwcfg = S3C2410_DISRCC_APB; + } + + /* always assume our peripheral desintation is a fixed + * address in memory. */ + hwcfg |= S3C2410_DISRCC_INC; switch (source) { case S3C2410_DMASRC_HW: @@ -1278,8 +1309,8 @@ static int s3c2410_dma_resume(struct sys_device *dev) printk(KERN_INFO "dma%d: restoring configuration\n", cp->number); - s3c2410_dma_config(no, cp->xfer_unit, cp->dcon); - s3c2410_dma_devconfig(no, cp->source, cp->hw_cfg, cp->dev_addr); + s3c2410_dma_config(no, cp->xfer_unit); + s3c2410_dma_devconfig(no, cp->source, cp->dev_addr); /* re-select the dma source for this channel */ @@ -1476,6 +1507,7 @@ static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel) found: dmach = &s3c2410_chans[ch]; dmach->map = ch_map; + dmach->req_ch = channel; dma_chan_map[channel] = dmach; /* select the channel */ diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 2db166b..889f350 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -789,7 +789,7 @@ static void s3cmci_dma_setup(struct s3cmci_host *host, last_source = source; - s3c2410_dma_devconfig(host->dma, source, 3, + s3c2410_dma_devconfig(host->dma, source, host->mem->start + host->sdidata); if (!setup_ok) { diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c index 169ddad..eecfa5e 100644 --- a/sound/soc/s3c24xx/s3c24xx-pcm.c +++ b/sound/soc/s3c24xx/s3c24xx-pcm.c @@ -218,24 +218,17 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream) * sync to pclk, half-word transfers to the IIS-FIFO. */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { s3c2410_dma_devconfig(prtd->params->channel, - S3C2410_DMASRC_MEM, S3C2410_DISRCC_INC | - S3C2410_DISRCC_APB, prtd->params->dma_addr); - - s3c2410_dma_config(prtd->params->channel, - prtd->params->dma_size, - S3C2410_DCON_SYNC_PCLK | - S3C2410_DCON_HANDSHAKE); + S3C2410_DMASRC_MEM, + prtd->params->dma_addr); } else { - s3c2410_dma_config(prtd->params->channel, - prtd->params->dma_size, - S3C2410_DCON_HANDSHAKE | - S3C2410_DCON_SYNC_PCLK); - s3c2410_dma_devconfig(prtd->params->channel, - S3C2410_DMASRC_HW, 0x3, - prtd->params->dma_addr); + S3C2410_DMASRC_HW, + prtd->params->dma_addr); } + s3c2410_dma_config(prtd->params->channel, + prtd->params->dma_size); + /* flush the DMA channel */ s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH); prtd->dma_loaded = 0; -- cgit v0.10.2 From 44dc94045f6ddbc07db3e0eb3448c2efc13ac2cf Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 19 Mar 2009 15:02:35 +0000 Subject: [ARM] S3C24XX: DMA: Split hardware regs out of The is for the driver API for the DMA system and should not have anything relying on the CPU specific registers. Remove the registers to for the code that really needs to know about them. Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index 6248f41..aba159f 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h index acaef67..6cefa56 100644 --- a/arch/arm/mach-s3c2410/include/mach/dma.h +++ b/arch/arm/mach-s3c2410/include/mach/dma.h @@ -3,7 +3,7 @@ * Copyright (C) 2003,2004,2006 Simtec Electronics * Ben Dooks * - * Samsung S3C241XX DMA support + * Samsung S3C24XX DMA support * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -68,7 +68,6 @@ enum s3c2410_dma_state { S3C2410_DMA_PAUSED }; - /* enum s3c2410_dma_loadst * * This represents the state of the DMA engine, wrt to the loaded / running @@ -311,138 +310,4 @@ extern int s3c2410_dma_getposition(unsigned int channel, extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn); extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn); -/* DMA Register definitions */ - -#define S3C2410_DMA_DISRC (0x00) -#define S3C2410_DMA_DISRCC (0x04) -#define S3C2410_DMA_DIDST (0x08) -#define S3C2410_DMA_DIDSTC (0x0C) -#define S3C2410_DMA_DCON (0x10) -#define S3C2410_DMA_DSTAT (0x14) -#define S3C2410_DMA_DCSRC (0x18) -#define S3C2410_DMA_DCDST (0x1C) -#define S3C2410_DMA_DMASKTRIG (0x20) -#define S3C2412_DMA_DMAREQSEL (0x24) -#define S3C2443_DMA_DMAREQSEL (0x24) - -#define S3C2410_DISRCC_INC (1<<0) -#define S3C2410_DISRCC_APB (1<<1) - -#define S3C2410_DMASKTRIG_STOP (1<<2) -#define S3C2410_DMASKTRIG_ON (1<<1) -#define S3C2410_DMASKTRIG_SWTRIG (1<<0) - -#define S3C2410_DCON_DEMAND (0<<31) -#define S3C2410_DCON_HANDSHAKE (1<<31) -#define S3C2410_DCON_SYNC_PCLK (0<<30) -#define S3C2410_DCON_SYNC_HCLK (1<<30) - -#define S3C2410_DCON_INTREQ (1<<29) - -#define S3C2410_DCON_CH0_XDREQ0 (0<<24) -#define S3C2410_DCON_CH0_UART0 (1<<24) -#define S3C2410_DCON_CH0_SDI (2<<24) -#define S3C2410_DCON_CH0_TIMER (3<<24) -#define S3C2410_DCON_CH0_USBEP1 (4<<24) - -#define S3C2410_DCON_CH1_XDREQ1 (0<<24) -#define S3C2410_DCON_CH1_UART1 (1<<24) -#define S3C2410_DCON_CH1_I2SSDI (2<<24) -#define S3C2410_DCON_CH1_SPI (3<<24) -#define S3C2410_DCON_CH1_USBEP2 (4<<24) - -#define S3C2410_DCON_CH2_I2SSDO (0<<24) -#define S3C2410_DCON_CH2_I2SSDI (1<<24) -#define S3C2410_DCON_CH2_SDI (2<<24) -#define S3C2410_DCON_CH2_TIMER (3<<24) -#define S3C2410_DCON_CH2_USBEP3 (4<<24) - -#define S3C2410_DCON_CH3_UART2 (0<<24) -#define S3C2410_DCON_CH3_SDI (1<<24) -#define S3C2410_DCON_CH3_SPI (2<<24) -#define S3C2410_DCON_CH3_TIMER (3<<24) -#define S3C2410_DCON_CH3_USBEP4 (4<<24) - -#define S3C2410_DCON_SRCSHIFT (24) -#define S3C2410_DCON_SRCMASK (7<<24) - -#define S3C2410_DCON_BYTE (0<<20) -#define S3C2410_DCON_HALFWORD (1<<20) -#define S3C2410_DCON_WORD (2<<20) - -#define S3C2410_DCON_AUTORELOAD (0<<22) -#define S3C2410_DCON_NORELOAD (1<<22) -#define S3C2410_DCON_HWTRIG (1<<23) - -#ifdef CONFIG_CPU_S3C2440 -#define S3C2440_DIDSTC_CHKINT (1<<2) - -#define S3C2440_DCON_CH0_I2SSDO (5<<24) -#define S3C2440_DCON_CH0_PCMIN (6<<24) - -#define S3C2440_DCON_CH1_PCMOUT (5<<24) -#define S3C2440_DCON_CH1_SDI (6<<24) - -#define S3C2440_DCON_CH2_PCMIN (5<<24) -#define S3C2440_DCON_CH2_MICIN (6<<24) - -#define S3C2440_DCON_CH3_MICIN (5<<24) -#define S3C2440_DCON_CH3_PCMOUT (6<<24) -#endif - -#ifdef CONFIG_CPU_S3C2412 - -#define S3C2412_DMAREQSEL_SRC(x) ((x)<<1) - -#define S3C2412_DMAREQSEL_HW (1) - -#define S3C2412_DMAREQSEL_SPI0TX S3C2412_DMAREQSEL_SRC(0) -#define S3C2412_DMAREQSEL_SPI0RX S3C2412_DMAREQSEL_SRC(1) -#define S3C2412_DMAREQSEL_SPI1TX S3C2412_DMAREQSEL_SRC(2) -#define S3C2412_DMAREQSEL_SPI1RX S3C2412_DMAREQSEL_SRC(3) -#define S3C2412_DMAREQSEL_I2STX S3C2412_DMAREQSEL_SRC(4) -#define S3C2412_DMAREQSEL_I2SRX S3C2412_DMAREQSEL_SRC(5) -#define S3C2412_DMAREQSEL_TIMER S3C2412_DMAREQSEL_SRC(9) -#define S3C2412_DMAREQSEL_SDI S3C2412_DMAREQSEL_SRC(10) -#define S3C2412_DMAREQSEL_USBEP1 S3C2412_DMAREQSEL_SRC(13) -#define S3C2412_DMAREQSEL_USBEP2 S3C2412_DMAREQSEL_SRC(14) -#define S3C2412_DMAREQSEL_USBEP3 S3C2412_DMAREQSEL_SRC(15) -#define S3C2412_DMAREQSEL_USBEP4 S3C2412_DMAREQSEL_SRC(16) -#define S3C2412_DMAREQSEL_XDREQ0 S3C2412_DMAREQSEL_SRC(17) -#define S3C2412_DMAREQSEL_XDREQ1 S3C2412_DMAREQSEL_SRC(18) -#define S3C2412_DMAREQSEL_UART0_0 S3C2412_DMAREQSEL_SRC(19) -#define S3C2412_DMAREQSEL_UART0_1 S3C2412_DMAREQSEL_SRC(20) -#define S3C2412_DMAREQSEL_UART1_0 S3C2412_DMAREQSEL_SRC(21) -#define S3C2412_DMAREQSEL_UART1_1 S3C2412_DMAREQSEL_SRC(22) -#define S3C2412_DMAREQSEL_UART2_0 S3C2412_DMAREQSEL_SRC(23) -#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24) - -#endif - -#define S3C2443_DMAREQSEL_SRC(x) ((x)<<1) - -#define S3C2443_DMAREQSEL_HW (1) - -#define S3C2443_DMAREQSEL_SPI0TX S3C2443_DMAREQSEL_SRC(0) -#define S3C2443_DMAREQSEL_SPI0RX S3C2443_DMAREQSEL_SRC(1) -#define S3C2443_DMAREQSEL_SPI1TX S3C2443_DMAREQSEL_SRC(2) -#define S3C2443_DMAREQSEL_SPI1RX S3C2443_DMAREQSEL_SRC(3) -#define S3C2443_DMAREQSEL_I2STX S3C2443_DMAREQSEL_SRC(4) -#define S3C2443_DMAREQSEL_I2SRX S3C2443_DMAREQSEL_SRC(5) -#define S3C2443_DMAREQSEL_TIMER S3C2443_DMAREQSEL_SRC(9) -#define S3C2443_DMAREQSEL_SDI S3C2443_DMAREQSEL_SRC(10) -#define S3C2443_DMAREQSEL_XDREQ0 S3C2443_DMAREQSEL_SRC(17) -#define S3C2443_DMAREQSEL_XDREQ1 S3C2443_DMAREQSEL_SRC(18) -#define S3C2443_DMAREQSEL_UART0_0 S3C2443_DMAREQSEL_SRC(19) -#define S3C2443_DMAREQSEL_UART0_1 S3C2443_DMAREQSEL_SRC(20) -#define S3C2443_DMAREQSEL_UART1_0 S3C2443_DMAREQSEL_SRC(21) -#define S3C2443_DMAREQSEL_UART1_1 S3C2443_DMAREQSEL_SRC(22) -#define S3C2443_DMAREQSEL_UART2_0 S3C2443_DMAREQSEL_SRC(23) -#define S3C2443_DMAREQSEL_UART2_1 S3C2443_DMAREQSEL_SRC(24) -#define S3C2443_DMAREQSEL_UART3_0 S3C2443_DMAREQSEL_SRC(25) -#define S3C2443_DMAREQSEL_UART3_1 S3C2443_DMAREQSEL_SRC(26) -#define S3C2443_DMAREQSEL_PCMOUT S3C2443_DMAREQSEL_SRC(27) -#define S3C2443_DMAREQSEL_PCMIN S3C2443_DMAREQSEL_SRC(28) -#define S3C2443_DMAREQSEL_MICIN S3C2443_DMAREQSEL_SRC(29) - #endif /* __ASM_ARCH_DMA_H */ diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c index f888d4e..f8d16fc 100644 --- a/arch/arm/mach-s3c2412/dma.c +++ b/arch/arm/mach-s3c2412/dma.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-s3c2440/dma.c b/arch/arm/mach-s3c2440/dma.c index 895783f..e08e081 100644 --- a/arch/arm/mach-s3c2440/dma.c +++ b/arch/arm/mach-s3c2440/dma.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c index 825b718..397f3b5 100644 --- a/arch/arm/mach-s3c2443/dma.c +++ b/arch/arm/mach-s3c2443/dma.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index dc58a0d..7c37c9a 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -31,10 +31,10 @@ #include #include #include - #include #include +#include /* io map for dma */ static void __iomem *dma_base; diff --git a/arch/arm/plat-s3c24xx/include/plat/regs-dma.h b/arch/arm/plat-s3c24xx/include/plat/regs-dma.h new file mode 100644 index 0000000..d38e7b7 --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/plat/regs-dma.h @@ -0,0 +1,145 @@ +/* arch/arm/mach-s3c2410/include/mach/dma.h + * + * Copyright (C) 2003,2004,2006 Simtec Electronics + * Ben Dooks + * + * Samsung S3C24XX DMA support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* DMA Register definitions */ + +#define S3C2410_DMA_DISRC (0x00) +#define S3C2410_DMA_DISRCC (0x04) +#define S3C2410_DMA_DIDST (0x08) +#define S3C2410_DMA_DIDSTC (0x0C) +#define S3C2410_DMA_DCON (0x10) +#define S3C2410_DMA_DSTAT (0x14) +#define S3C2410_DMA_DCSRC (0x18) +#define S3C2410_DMA_DCDST (0x1C) +#define S3C2410_DMA_DMASKTRIG (0x20) +#define S3C2412_DMA_DMAREQSEL (0x24) +#define S3C2443_DMA_DMAREQSEL (0x24) + +#define S3C2410_DISRCC_INC (1<<0) +#define S3C2410_DISRCC_APB (1<<1) + +#define S3C2410_DMASKTRIG_STOP (1<<2) +#define S3C2410_DMASKTRIG_ON (1<<1) +#define S3C2410_DMASKTRIG_SWTRIG (1<<0) + +#define S3C2410_DCON_DEMAND (0<<31) +#define S3C2410_DCON_HANDSHAKE (1<<31) +#define S3C2410_DCON_SYNC_PCLK (0<<30) +#define S3C2410_DCON_SYNC_HCLK (1<<30) + +#define S3C2410_DCON_INTREQ (1<<29) + +#define S3C2410_DCON_CH0_XDREQ0 (0<<24) +#define S3C2410_DCON_CH0_UART0 (1<<24) +#define S3C2410_DCON_CH0_SDI (2<<24) +#define S3C2410_DCON_CH0_TIMER (3<<24) +#define S3C2410_DCON_CH0_USBEP1 (4<<24) + +#define S3C2410_DCON_CH1_XDREQ1 (0<<24) +#define S3C2410_DCON_CH1_UART1 (1<<24) +#define S3C2410_DCON_CH1_I2SSDI (2<<24) +#define S3C2410_DCON_CH1_SPI (3<<24) +#define S3C2410_DCON_CH1_USBEP2 (4<<24) + +#define S3C2410_DCON_CH2_I2SSDO (0<<24) +#define S3C2410_DCON_CH2_I2SSDI (1<<24) +#define S3C2410_DCON_CH2_SDI (2<<24) +#define S3C2410_DCON_CH2_TIMER (3<<24) +#define S3C2410_DCON_CH2_USBEP3 (4<<24) + +#define S3C2410_DCON_CH3_UART2 (0<<24) +#define S3C2410_DCON_CH3_SDI (1<<24) +#define S3C2410_DCON_CH3_SPI (2<<24) +#define S3C2410_DCON_CH3_TIMER (3<<24) +#define S3C2410_DCON_CH3_USBEP4 (4<<24) + +#define S3C2410_DCON_SRCSHIFT (24) +#define S3C2410_DCON_SRCMASK (7<<24) + +#define S3C2410_DCON_BYTE (0<<20) +#define S3C2410_DCON_HALFWORD (1<<20) +#define S3C2410_DCON_WORD (2<<20) + +#define S3C2410_DCON_AUTORELOAD (0<<22) +#define S3C2410_DCON_NORELOAD (1<<22) +#define S3C2410_DCON_HWTRIG (1<<23) + +#ifdef CONFIG_CPU_S3C2440 +#define S3C2440_DIDSTC_CHKINT (1<<2) + +#define S3C2440_DCON_CH0_I2SSDO (5<<24) +#define S3C2440_DCON_CH0_PCMIN (6<<24) + +#define S3C2440_DCON_CH1_PCMOUT (5<<24) +#define S3C2440_DCON_CH1_SDI (6<<24) + +#define S3C2440_DCON_CH2_PCMIN (5<<24) +#define S3C2440_DCON_CH2_MICIN (6<<24) + +#define S3C2440_DCON_CH3_MICIN (5<<24) +#define S3C2440_DCON_CH3_PCMOUT (6<<24) +#endif + +#ifdef CONFIG_CPU_S3C2412 + +#define S3C2412_DMAREQSEL_SRC(x) ((x)<<1) + +#define S3C2412_DMAREQSEL_HW (1) + +#define S3C2412_DMAREQSEL_SPI0TX S3C2412_DMAREQSEL_SRC(0) +#define S3C2412_DMAREQSEL_SPI0RX S3C2412_DMAREQSEL_SRC(1) +#define S3C2412_DMAREQSEL_SPI1TX S3C2412_DMAREQSEL_SRC(2) +#define S3C2412_DMAREQSEL_SPI1RX S3C2412_DMAREQSEL_SRC(3) +#define S3C2412_DMAREQSEL_I2STX S3C2412_DMAREQSEL_SRC(4) +#define S3C2412_DMAREQSEL_I2SRX S3C2412_DMAREQSEL_SRC(5) +#define S3C2412_DMAREQSEL_TIMER S3C2412_DMAREQSEL_SRC(9) +#define S3C2412_DMAREQSEL_SDI S3C2412_DMAREQSEL_SRC(10) +#define S3C2412_DMAREQSEL_USBEP1 S3C2412_DMAREQSEL_SRC(13) +#define S3C2412_DMAREQSEL_USBEP2 S3C2412_DMAREQSEL_SRC(14) +#define S3C2412_DMAREQSEL_USBEP3 S3C2412_DMAREQSEL_SRC(15) +#define S3C2412_DMAREQSEL_USBEP4 S3C2412_DMAREQSEL_SRC(16) +#define S3C2412_DMAREQSEL_XDREQ0 S3C2412_DMAREQSEL_SRC(17) +#define S3C2412_DMAREQSEL_XDREQ1 S3C2412_DMAREQSEL_SRC(18) +#define S3C2412_DMAREQSEL_UART0_0 S3C2412_DMAREQSEL_SRC(19) +#define S3C2412_DMAREQSEL_UART0_1 S3C2412_DMAREQSEL_SRC(20) +#define S3C2412_DMAREQSEL_UART1_0 S3C2412_DMAREQSEL_SRC(21) +#define S3C2412_DMAREQSEL_UART1_1 S3C2412_DMAREQSEL_SRC(22) +#define S3C2412_DMAREQSEL_UART2_0 S3C2412_DMAREQSEL_SRC(23) +#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24) + +#endif + +#define S3C2443_DMAREQSEL_SRC(x) ((x)<<1) + +#define S3C2443_DMAREQSEL_HW (1) + +#define S3C2443_DMAREQSEL_SPI0TX S3C2443_DMAREQSEL_SRC(0) +#define S3C2443_DMAREQSEL_SPI0RX S3C2443_DMAREQSEL_SRC(1) +#define S3C2443_DMAREQSEL_SPI1TX S3C2443_DMAREQSEL_SRC(2) +#define S3C2443_DMAREQSEL_SPI1RX S3C2443_DMAREQSEL_SRC(3) +#define S3C2443_DMAREQSEL_I2STX S3C2443_DMAREQSEL_SRC(4) +#define S3C2443_DMAREQSEL_I2SRX S3C2443_DMAREQSEL_SRC(5) +#define S3C2443_DMAREQSEL_TIMER S3C2443_DMAREQSEL_SRC(9) +#define S3C2443_DMAREQSEL_SDI S3C2443_DMAREQSEL_SRC(10) +#define S3C2443_DMAREQSEL_XDREQ0 S3C2443_DMAREQSEL_SRC(17) +#define S3C2443_DMAREQSEL_XDREQ1 S3C2443_DMAREQSEL_SRC(18) +#define S3C2443_DMAREQSEL_UART0_0 S3C2443_DMAREQSEL_SRC(19) +#define S3C2443_DMAREQSEL_UART0_1 S3C2443_DMAREQSEL_SRC(20) +#define S3C2443_DMAREQSEL_UART1_0 S3C2443_DMAREQSEL_SRC(21) +#define S3C2443_DMAREQSEL_UART1_1 S3C2443_DMAREQSEL_SRC(22) +#define S3C2443_DMAREQSEL_UART2_0 S3C2443_DMAREQSEL_SRC(23) +#define S3C2443_DMAREQSEL_UART2_1 S3C2443_DMAREQSEL_SRC(24) +#define S3C2443_DMAREQSEL_UART3_0 S3C2443_DMAREQSEL_SRC(25) +#define S3C2443_DMAREQSEL_UART3_1 S3C2443_DMAREQSEL_SRC(26) +#define S3C2443_DMAREQSEL_PCMOUT S3C2443_DMAREQSEL_SRC(27) +#define S3C2443_DMAREQSEL_PCMIN S3C2443_DMAREQSEL_SRC(28) +#define S3C2443_DMAREQSEL_MICIN S3C2443_DMAREQSEL_SRC(29) -- cgit v0.10.2 From 023b40cd1018915beb5a519b55ea174683215f16 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 19 Mar 2009 15:02:36 +0000 Subject: [ARM] S3C24XX: Fix indentation in The pre-date the invention of the TAB character, so fix the indentation of the register defines. Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s3c24xx/include/plat/regs-dma.h b/arch/arm/plat-s3c24xx/include/plat/regs-dma.h index d38e7b7..3bc0a21 100644 --- a/arch/arm/plat-s3c24xx/include/plat/regs-dma.h +++ b/arch/arm/plat-s3c24xx/include/plat/regs-dma.h @@ -12,81 +12,81 @@ /* DMA Register definitions */ -#define S3C2410_DMA_DISRC (0x00) -#define S3C2410_DMA_DISRCC (0x04) -#define S3C2410_DMA_DIDST (0x08) -#define S3C2410_DMA_DIDSTC (0x0C) -#define S3C2410_DMA_DCON (0x10) -#define S3C2410_DMA_DSTAT (0x14) -#define S3C2410_DMA_DCSRC (0x18) -#define S3C2410_DMA_DCDST (0x1C) -#define S3C2410_DMA_DMASKTRIG (0x20) -#define S3C2412_DMA_DMAREQSEL (0x24) -#define S3C2443_DMA_DMAREQSEL (0x24) - -#define S3C2410_DISRCC_INC (1<<0) -#define S3C2410_DISRCC_APB (1<<1) - -#define S3C2410_DMASKTRIG_STOP (1<<2) -#define S3C2410_DMASKTRIG_ON (1<<1) -#define S3C2410_DMASKTRIG_SWTRIG (1<<0) - -#define S3C2410_DCON_DEMAND (0<<31) -#define S3C2410_DCON_HANDSHAKE (1<<31) -#define S3C2410_DCON_SYNC_PCLK (0<<30) -#define S3C2410_DCON_SYNC_HCLK (1<<30) - -#define S3C2410_DCON_INTREQ (1<<29) - -#define S3C2410_DCON_CH0_XDREQ0 (0<<24) -#define S3C2410_DCON_CH0_UART0 (1<<24) -#define S3C2410_DCON_CH0_SDI (2<<24) -#define S3C2410_DCON_CH0_TIMER (3<<24) -#define S3C2410_DCON_CH0_USBEP1 (4<<24) - -#define S3C2410_DCON_CH1_XDREQ1 (0<<24) -#define S3C2410_DCON_CH1_UART1 (1<<24) -#define S3C2410_DCON_CH1_I2SSDI (2<<24) -#define S3C2410_DCON_CH1_SPI (3<<24) -#define S3C2410_DCON_CH1_USBEP2 (4<<24) - -#define S3C2410_DCON_CH2_I2SSDO (0<<24) -#define S3C2410_DCON_CH2_I2SSDI (1<<24) -#define S3C2410_DCON_CH2_SDI (2<<24) -#define S3C2410_DCON_CH2_TIMER (3<<24) -#define S3C2410_DCON_CH2_USBEP3 (4<<24) - -#define S3C2410_DCON_CH3_UART2 (0<<24) -#define S3C2410_DCON_CH3_SDI (1<<24) -#define S3C2410_DCON_CH3_SPI (2<<24) -#define S3C2410_DCON_CH3_TIMER (3<<24) -#define S3C2410_DCON_CH3_USBEP4 (4<<24) - -#define S3C2410_DCON_SRCSHIFT (24) -#define S3C2410_DCON_SRCMASK (7<<24) - -#define S3C2410_DCON_BYTE (0<<20) -#define S3C2410_DCON_HALFWORD (1<<20) -#define S3C2410_DCON_WORD (2<<20) - -#define S3C2410_DCON_AUTORELOAD (0<<22) -#define S3C2410_DCON_NORELOAD (1<<22) -#define S3C2410_DCON_HWTRIG (1<<23) +#define S3C2410_DMA_DISRC (0x00) +#define S3C2410_DMA_DISRCC (0x04) +#define S3C2410_DMA_DIDST (0x08) +#define S3C2410_DMA_DIDSTC (0x0C) +#define S3C2410_DMA_DCON (0x10) +#define S3C2410_DMA_DSTAT (0x14) +#define S3C2410_DMA_DCSRC (0x18) +#define S3C2410_DMA_DCDST (0x1C) +#define S3C2410_DMA_DMASKTRIG (0x20) +#define S3C2412_DMA_DMAREQSEL (0x24) +#define S3C2443_DMA_DMAREQSEL (0x24) + +#define S3C2410_DISRCC_INC (1<<0) +#define S3C2410_DISRCC_APB (1<<1) + +#define S3C2410_DMASKTRIG_STOP (1<<2) +#define S3C2410_DMASKTRIG_ON (1<<1) +#define S3C2410_DMASKTRIG_SWTRIG (1<<0) + +#define S3C2410_DCON_DEMAND (0<<31) +#define S3C2410_DCON_HANDSHAKE (1<<31) +#define S3C2410_DCON_SYNC_PCLK (0<<30) +#define S3C2410_DCON_SYNC_HCLK (1<<30) + +#define S3C2410_DCON_INTREQ (1<<29) + +#define S3C2410_DCON_CH0_XDREQ0 (0<<24) +#define S3C2410_DCON_CH0_UART0 (1<<24) +#define S3C2410_DCON_CH0_SDI (2<<24) +#define S3C2410_DCON_CH0_TIMER (3<<24) +#define S3C2410_DCON_CH0_USBEP1 (4<<24) + +#define S3C2410_DCON_CH1_XDREQ1 (0<<24) +#define S3C2410_DCON_CH1_UART1 (1<<24) +#define S3C2410_DCON_CH1_I2SSDI (2<<24) +#define S3C2410_DCON_CH1_SPI (3<<24) +#define S3C2410_DCON_CH1_USBEP2 (4<<24) + +#define S3C2410_DCON_CH2_I2SSDO (0<<24) +#define S3C2410_DCON_CH2_I2SSDI (1<<24) +#define S3C2410_DCON_CH2_SDI (2<<24) +#define S3C2410_DCON_CH2_TIMER (3<<24) +#define S3C2410_DCON_CH2_USBEP3 (4<<24) + +#define S3C2410_DCON_CH3_UART2 (0<<24) +#define S3C2410_DCON_CH3_SDI (1<<24) +#define S3C2410_DCON_CH3_SPI (2<<24) +#define S3C2410_DCON_CH3_TIMER (3<<24) +#define S3C2410_DCON_CH3_USBEP4 (4<<24) + +#define S3C2410_DCON_SRCSHIFT (24) +#define S3C2410_DCON_SRCMASK (7<<24) + +#define S3C2410_DCON_BYTE (0<<20) +#define S3C2410_DCON_HALFWORD (1<<20) +#define S3C2410_DCON_WORD (2<<20) + +#define S3C2410_DCON_AUTORELOAD (0<<22) +#define S3C2410_DCON_NORELOAD (1<<22) +#define S3C2410_DCON_HWTRIG (1<<23) #ifdef CONFIG_CPU_S3C2440 -#define S3C2440_DIDSTC_CHKINT (1<<2) +#define S3C2440_DIDSTC_CHKINT (1<<2) -#define S3C2440_DCON_CH0_I2SSDO (5<<24) -#define S3C2440_DCON_CH0_PCMIN (6<<24) +#define S3C2440_DCON_CH0_I2SSDO (5<<24) +#define S3C2440_DCON_CH0_PCMIN (6<<24) -#define S3C2440_DCON_CH1_PCMOUT (5<<24) -#define S3C2440_DCON_CH1_SDI (6<<24) +#define S3C2440_DCON_CH1_PCMOUT (5<<24) +#define S3C2440_DCON_CH1_SDI (6<<24) -#define S3C2440_DCON_CH2_PCMIN (5<<24) -#define S3C2440_DCON_CH2_MICIN (6<<24) +#define S3C2440_DCON_CH2_PCMIN (5<<24) +#define S3C2440_DCON_CH2_MICIN (6<<24) -#define S3C2440_DCON_CH3_MICIN (5<<24) -#define S3C2440_DCON_CH3_PCMOUT (6<<24) +#define S3C2440_DCON_CH3_MICIN (5<<24) +#define S3C2440_DCON_CH3_PCMOUT (6<<24) #endif #ifdef CONFIG_CPU_S3C2412 -- cgit v0.10.2 From c133c290118bfc99cd7a23b5a00b5252d2be90c8 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 19 Mar 2009 15:02:37 +0000 Subject: [ARM] S3C: Make common header Move the common information from the header into a new shareable header for re-use on the s3c64xx. Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h index 6cefa56..2fbabec 100644 --- a/arch/arm/mach-s3c2410/include/mach/dma.h +++ b/arch/arm/mach-s3c2410/include/mach/dma.h @@ -13,6 +13,7 @@ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H __FILE__ +#include #include #include @@ -103,32 +104,6 @@ enum s3c2410_dma_loadst { S3C2410_DMALOAD_1LOADED_1RUNNING, }; -enum s3c2410_dma_buffresult { - S3C2410_RES_OK, - S3C2410_RES_ERR, - S3C2410_RES_ABORT -}; - -enum s3c2410_dmasrc { - S3C2410_DMASRC_HW, /* source is memory */ - S3C2410_DMASRC_MEM /* source is hardware */ -}; - -/* enum s3c2410_chan_op - * - * operation codes passed to the DMA code by the user, and also used - * to inform the current channel owner of any changes to the system state -*/ - -enum s3c2410_chan_op { - S3C2410_DMAOP_START, - S3C2410_DMAOP_STOP, - S3C2410_DMAOP_PAUSE, - S3C2410_DMAOP_RESUME, - S3C2410_DMAOP_FLUSH, - S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */ - S3C2410_DMAOP_STARTED, /* indicate channel started */ -}; /* flags */ @@ -138,17 +113,14 @@ enum s3c2410_chan_op { /* dma buffer */ -struct s3c2410_dma_client { - char *name; -}; +struct s3c2410_dma_buf; -/* s3c2410_dma_buf_s +/* s3c2410_dma_buf * * internally used buffer structure to describe a queued or running * buffer. */ -struct s3c2410_dma_buf; struct s3c2410_dma_buf { struct s3c2410_dma_buf *next; int magic; /* magic */ @@ -160,20 +132,6 @@ struct s3c2410_dma_buf { /* [1] is this updated for both recv/send modes? */ -struct s3c2410_dma_chan; - -/* s3c2410_dma_cbfn_t - * - * buffer callback routine type -*/ - -typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *, - void *buf, int size, - enum s3c2410_dma_buffresult result); - -typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *, - enum s3c2410_chan_op ); - struct s3c2410_dma_stats { unsigned long loads; unsigned long timeout_longest; @@ -241,73 +199,4 @@ extern struct s3c2410_dma_chan s3c2410_chans[]; /* note, we don't really use dma_device_t at the moment */ typedef unsigned long dma_device_t; -/* functions --------------------------------------------------------------- */ - -/* s3c2410_dma_request - * - * request a dma channel exclusivley -*/ - -extern int s3c2410_dma_request(unsigned int channel, - struct s3c2410_dma_client *, void *dev); - - -/* s3c2410_dma_ctrl - * - * change the state of the dma channel -*/ - -extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op); - -/* s3c2410_dma_setflags - * - * set the channel's flags to a given state -*/ - -extern int s3c2410_dma_setflags(unsigned int channel, - unsigned int flags); - -/* s3c2410_dma_free - * - * free the dma channel (will also abort any outstanding operations) -*/ - -extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *); - -/* s3c2410_dma_enqueue - * - * place the given buffer onto the queue of operations for the channel. - * The buffer must be allocated from dma coherent memory, or the Dcache/WB - * drained before the buffer is given to the DMA system. -*/ - -extern int s3c2410_dma_enqueue(unsigned int channel, void *id, - dma_addr_t data, int size); - -/* s3c2410_dma_config - * - * configure the dma channel -*/ - -extern int s3c2410_dma_config(unsigned int channel, int xferunit); - -/* s3c2410_dma_devconfig - * - * configure the device we're talking to -*/ - -extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, - unsigned long devaddr); - -/* s3c2410_dma_getposition - * - * get the position that the dma transfer is currently at -*/ - -extern int s3c2410_dma_getposition(unsigned int channel, - dma_addr_t *src, dma_addr_t *dest); - -extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn); -extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn); - #endif /* __ASM_ARCH_DMA_H */ diff --git a/arch/arm/plat-s3c/include/plat/dma.h b/arch/arm/plat-s3c/include/plat/dma.h new file mode 100644 index 0000000..34dba98 --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/dma.h @@ -0,0 +1,127 @@ +/* arch/arm/plat-s3c/include/plat/dma.h + * + * Copyright (C) 2003,2004,2006 Simtec Electronics + * Ben Dooks + * + * Samsung S3C DMA support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +enum s3c2410_dma_buffresult { + S3C2410_RES_OK, + S3C2410_RES_ERR, + S3C2410_RES_ABORT +}; + +enum s3c2410_dmasrc { + S3C2410_DMASRC_HW, /* source is memory */ + S3C2410_DMASRC_MEM /* source is hardware */ +}; + +/* enum s3c2410_chan_op + * + * operation codes passed to the DMA code by the user, and also used + * to inform the current channel owner of any changes to the system state +*/ + +enum s3c2410_chan_op { + S3C2410_DMAOP_START, + S3C2410_DMAOP_STOP, + S3C2410_DMAOP_PAUSE, + S3C2410_DMAOP_RESUME, + S3C2410_DMAOP_FLUSH, + S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */ + S3C2410_DMAOP_STARTED, /* indicate channel started */ +}; + +struct s3c2410_dma_client { + char *name; +}; + +struct s3c2410_dma_chan; + +/* s3c2410_dma_cbfn_t + * + * buffer callback routine type +*/ + +typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *, + void *buf, int size, + enum s3c2410_dma_buffresult result); + +typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *, + enum s3c2410_chan_op ); + + + +/* s3c2410_dma_request + * + * request a dma channel exclusivley +*/ + +extern int s3c2410_dma_request(unsigned int channel, + struct s3c2410_dma_client *, void *dev); + + +/* s3c2410_dma_ctrl + * + * change the state of the dma channel +*/ + +extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op); + +/* s3c2410_dma_setflags + * + * set the channel's flags to a given state +*/ + +extern int s3c2410_dma_setflags(unsigned int channel, + unsigned int flags); + +/* s3c2410_dma_free + * + * free the dma channel (will also abort any outstanding operations) +*/ + +extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *); + +/* s3c2410_dma_enqueue + * + * place the given buffer onto the queue of operations for the channel. + * The buffer must be allocated from dma coherent memory, or the Dcache/WB + * drained before the buffer is given to the DMA system. +*/ + +extern int s3c2410_dma_enqueue(unsigned int channel, void *id, + dma_addr_t data, int size); + +/* s3c2410_dma_config + * + * configure the dma channel +*/ + +extern int s3c2410_dma_config(unsigned int channel, int xferunit); + +/* s3c2410_dma_devconfig + * + * configure the device we're talking to +*/ + +extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, + unsigned long devaddr); + +/* s3c2410_dma_getposition + * + * get the position that the dma transfer is currently at +*/ + +extern int s3c2410_dma_getposition(unsigned int channel, + dma_addr_t *src, dma_addr_t *dest); + +extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn); +extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn); + + -- cgit v0.10.2 From 20934cdbaae9c26a31d7f593c6a747c687ae79a1 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 19 Mar 2009 15:02:38 +0000 Subject: [ARM] S3C24XX: dma.h should not include The dma.h header does not need to include as there is nothing it depends on. Remove the include and fixup the couple of places where was not explicitly included (dragged in via ) Note, we have to fix arch/arm/plat-s3c24xx/pm.c which seems to rely on having included by this method. Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index aba159f..dbf96e6 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -17,6 +17,7 @@ #include #include +#include #include #include diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h index 2fbabec..1648311 100644 --- a/arch/arm/mach-s3c2410/include/mach/dma.h +++ b/arch/arm/mach-s3c2410/include/mach/dma.h @@ -15,7 +15,6 @@ #include #include -#include #define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */ -- cgit v0.10.2 From 97c1b145231730e62dd71921ec653315a1da3aad Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 19 Mar 2009 15:02:39 +0000 Subject: [ARM] S3C: Move DMA channel management code to plat-s3c Change the name of S3C2410_DMA_CHANNELS to S3C_DMA_CHANNELS in the process. Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h index 1648311..c3a2629 100644 --- a/arch/arm/mach-s3c2410/include/mach/dma.h +++ b/arch/arm/mach-s3c2410/include/mach/dma.h @@ -55,9 +55,9 @@ enum dma_ch { /* we have 4 dma channels */ #ifndef CONFIG_CPU_S3C2443 -#define S3C2410_DMA_CHANNELS (4) +#define S3C_DMA_CHANNELS (4) #else -#define S3C2410_DMA_CHANNELS (6) +#define S3C_DMA_CHANNELS (6) #endif /* types */ @@ -192,10 +192,6 @@ struct s3c2410_dma_chan { struct sys_device dev; }; -/* the currently allocated channel information */ -extern struct s3c2410_dma_chan s3c2410_chans[]; - -/* note, we don't really use dma_device_t at the moment */ typedef unsigned long dma_device_t; #endif /* __ASM_ARCH_DMA_H */ diff --git a/arch/arm/plat-s3c/Kconfig b/arch/arm/plat-s3c/Kconfig index de93838..d4fc89f 100644 --- a/arch/arm/plat-s3c/Kconfig +++ b/arch/arm/plat-s3c/Kconfig @@ -150,6 +150,13 @@ config S3C_GPIO_CFG_S3C64XX Internal configuration to enable S3C64XX style GPIO configuration functions. +# DMA + +config S3C_DMA + bool + help + Internal configuration for S3C DMA core + # device definitions to compile in config S3C_DEV_HSMMC diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile index 8d7815d..e8b23fc 100644 --- a/arch/arm/plat-s3c/Makefile +++ b/arch/arm/plat-s3c/Makefile @@ -18,6 +18,10 @@ obj-y += pwm-clock.o obj-y += gpio.o obj-y += gpio-config.o +# DMA support + +obj-$(CONFIG_S3C_DMA) += dma.o + # PM support obj-$(CONFIG_PM) += pm.o diff --git a/arch/arm/plat-s3c/dma.c b/arch/arm/plat-s3c/dma.c new file mode 100644 index 0000000..c9db75c --- /dev/null +++ b/arch/arm/plat-s3c/dma.c @@ -0,0 +1,86 @@ +/* linux/arch/arm/plat-s3c/dma.c + * + * Copyright (c) 2003-2005,2006,2009 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C DMA core + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +struct s3c2410_dma_buf; + +#include +#include +#include + +#include +#include + +#include + +/* dma channel state information */ +struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS]; +struct s3c2410_dma_chan *s3c_dma_chan_map[DMACH_MAX]; + +/* s3c_dma_lookup_channel + * + * change the dma channel number given into a real dma channel id +*/ + +struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel) +{ + if (channel & DMACH_LOW_LEVEL) + return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL]; + else + return s3c_dma_chan_map[channel]; +} + +/* do we need to protect the settings of the fields from + * irq? +*/ + +int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn) +{ + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); + + if (chan == NULL) + return -EINVAL; + + pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn); + + chan->op_fn = rtn; + + return 0; +} +EXPORT_SYMBOL(s3c2410_dma_set_opfn); + +int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn) +{ + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); + + if (chan == NULL) + return -EINVAL; + + pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn); + + chan->callback_fn = rtn; + + return 0; +} +EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); + +int s3c2410_dma_setflags(unsigned int channel, unsigned int flags) +{ + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); + + if (chan == NULL) + return -EINVAL; + + chan->flags = flags; + return 0; +} +EXPORT_SYMBOL(s3c2410_dma_setflags); diff --git a/arch/arm/plat-s3c/include/plat/dma-core.h b/arch/arm/plat-s3c/include/plat/dma-core.h new file mode 100644 index 0000000..32ff2a9 --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/dma-core.h @@ -0,0 +1,22 @@ +/* arch/arm/plat-s3c/include/plat/dma.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * Samsung S3C DMA core support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +extern struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel); + +extern struct s3c2410_dma_chan *s3c_dma_chan_map[]; + +/* the currently allocated channel information */ +extern struct s3c2410_dma_chan s3c2410_chans[]; + + diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index 2c8a2f5..5b0bc91 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -71,6 +71,7 @@ config PM_SIMTEC config S3C2410_DMA bool "S3C2410 DMA support" depends on ARCH_S3C2410 + select S3C_DMA help S3C2410 DMA support. This is needed for drivers like sound which use the S3C2410's DMA system to move data to and from the diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index 7c37c9a..b07fec0 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -44,8 +44,6 @@ static int dma_channels; static struct s3c24xx_dma_selection dma_sel; -/* dma channel state information */ -struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; /* debugging functions */ @@ -135,21 +133,6 @@ dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan) #define dbg_showchan(chan) do { } while(0) #endif /* CONFIG_S3C2410_DMA_DEBUG */ -static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX]; - -/* lookup_dma_channel - * - * change the dma channel number given into a real dma channel id -*/ - -static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel) -{ - if (channel & DMACH_LOW_LEVEL) - return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL]; - else - return dma_chan_map[channel]; -} - /* s3c2410_dma_stats_timeout * * Update DMA stats from timeout info @@ -214,8 +197,6 @@ s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line) return 0; } - - /* s3c2410_dma_loadbuffer * * load a buffer, and update the channel state @@ -453,7 +434,7 @@ s3c2410_dma_canload(struct s3c2410_dma_chan *chan) int s3c2410_dma_enqueue(unsigned int channel, void *id, dma_addr_t data, int size) { - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); struct s3c2410_dma_buf *buf; unsigned long flags; @@ -804,7 +785,7 @@ EXPORT_SYMBOL(s3c2410_dma_request); int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client) { - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); unsigned long flags; if (chan == NULL) @@ -836,7 +817,7 @@ int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client) chan->irq_claimed = 0; if (!(channel & DMACH_LOW_LEVEL)) - dma_chan_map[channel] = NULL; + s3c_dma_chan_map[channel] = NULL; local_irq_restore(flags); @@ -995,7 +976,7 @@ static int s3c2410_dma_started(struct s3c2410_dma_chan *chan) int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op) { - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); if (chan == NULL) return -EINVAL; @@ -1043,7 +1024,7 @@ EXPORT_SYMBOL(s3c2410_dma_ctrl); int s3c2410_dma_config(unsigned int channel, int xferunit) { - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); unsigned int dcon; pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n", @@ -1112,58 +1093,6 @@ int s3c2410_dma_config(unsigned int channel, EXPORT_SYMBOL(s3c2410_dma_config); -int s3c2410_dma_setflags(unsigned int channel, unsigned int flags) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - - if (chan == NULL) - return -EINVAL; - - pr_debug("%s: chan=%p, flags=%08x\n", __func__, chan, flags); - - chan->flags = flags; - - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_setflags); - - -/* do we need to protect the settings of the fields from - * irq? -*/ - -int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - - if (chan == NULL) - return -EINVAL; - - pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn); - - chan->op_fn = rtn; - - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_set_opfn); - -int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - - if (chan == NULL) - return -EINVAL; - - pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn); - - chan->callback_fn = rtn; - - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); /* s3c2410_dma_devconfig * @@ -1179,7 +1108,7 @@ int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, unsigned long devaddr) { - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); unsigned int hwcfg; if (chan == NULL) @@ -1250,7 +1179,7 @@ EXPORT_SYMBOL(s3c2410_dma_devconfig); int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *dst) { - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); if (chan == NULL) return -EINVAL; @@ -1508,7 +1437,7 @@ static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel) dmach = &s3c2410_chans[ch]; dmach->map = ch_map; dmach->req_ch = channel; - dma_chan_map[channel] = dmach; + s3c_dma_chan_map[channel] = dmach; /* select the channel */ diff --git a/arch/arm/plat-s3c24xx/include/plat/dma-plat.h b/arch/arm/plat-s3c24xx/include/plat/dma-plat.h index fbe84af..9565ead 100644 --- a/arch/arm/plat-s3c24xx/include/plat/dma-plat.h +++ b/arch/arm/plat-s3c24xx/include/plat/dma-plat.h @@ -10,8 +10,10 @@ * published by the Free Software Foundation. */ +#include + extern struct sysdev_class dma_sysclass; -extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; +extern struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS]; #define DMA_CH_VALID (1<<31) #define DMA_CH_NEVER (1<<30) @@ -31,8 +33,8 @@ struct s3c24xx_dma_map { const char *name; struct s3c24xx_dma_addr hw_addr; - unsigned long channels[S3C2410_DMA_CHANNELS]; - unsigned long channels_rx[S3C2410_DMA_CHANNELS]; + unsigned long channels[S3C_DMA_CHANNELS]; + unsigned long channels_rx[S3C_DMA_CHANNELS]; }; struct s3c24xx_dma_selection { @@ -58,7 +60,7 @@ extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel); */ struct s3c24xx_dma_order_ch { - unsigned int list[S3C2410_DMA_CHANNELS]; /* list of channels */ + unsigned int list[S3C_DMA_CHANNELS]; /* list of channels */ unsigned int flags; /* flags */ }; -- cgit v0.10.2 From fa7a7883fe5c647decee57a9c1b86a96408c5b26 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 10 Mar 2009 23:57:26 +0000 Subject: [ARM] S3C64XX: DMA support Add support for the DMA blocks in the S3C64XX series of CPUS, which are based on the ARM PL080 PrimeCell system. Unfortunately, these DMA controllers diverge from the PL080 design by adding another DMA controller register and configuration for OneNAND. Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks diff --git a/arch/arm/include/asm/hardware/pl080.h b/arch/arm/include/asm/hardware/pl080.h new file mode 100644 index 0000000..6a6c66b --- /dev/null +++ b/arch/arm/include/asm/hardware/pl080.h @@ -0,0 +1,138 @@ +/* arch/arm/include/asm/hardware/pl080.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks + * + * ARM PrimeCell PL080 DMA controller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* Note, there are some Samsung updates to this controller block which + * make it not entierly compatible with the PL080 specification from + * ARM. When in doubt, check the Samsung documentation first. + * + * The Samsung defines are PL080S, and add an extra controll register, + * the ability to move more than 2^11 counts of data and some extra + * OneNAND features. +*/ + +#define PL080_INT_STATUS (0x00) +#define PL080_TC_STATUS (0x04) +#define PL080_TC_CLEAR (0x08) +#define PL080_ERR_STATUS (0x0C) +#define PL080_ERR_CLEAR (0x10) +#define PL080_RAW_TC_STATUS (0x14) +#define PL080_RAW_ERR_STATUS (0x18) +#define PL080_EN_CHAN (0x1c) +#define PL080_SOFT_BREQ (0x20) +#define PL080_SOFT_SREQ (0x24) +#define PL080_SOFT_LBREQ (0x28) +#define PL080_SOFT_LSREQ (0x2C) + +#define PL080_CONFIG (0x30) +#define PL080_CONFIG_M2_BE (1 << 2) +#define PL080_CONFIG_M1_BE (1 << 1) +#define PL080_CONFIG_ENABLE (1 << 0) + +#define PL080_SYNC (0x34) + +/* Per channel configuration registers */ + +#define PL008_Cx_STRIDE (0x20) +#define PL080_Cx_BASE(x) ((0x100 + (x * 0x20))) +#define PL080_Cx_SRC_ADDR(x) ((0x100 + (x * 0x20))) +#define PL080_Cx_DST_ADDR(x) ((0x104 + (x * 0x20))) +#define PL080_Cx_LLI(x) ((0x108 + (x * 0x20))) +#define PL080_Cx_CONTROL(x) ((0x10C + (x * 0x20))) +#define PL080_Cx_CONFIG(x) ((0x110 + (x * 0x20))) +#define PL080S_Cx_CONTROL2(x) ((0x110 + (x * 0x20))) +#define PL080S_Cx_CONFIG(x) ((0x114 + (x * 0x20))) + +#define PL080_CH_SRC_ADDR (0x00) +#define PL080_CH_DST_ADDR (0x04) +#define PL080_CH_LLI (0x08) +#define PL080_CH_CONTROL (0x0C) +#define PL080_CH_CONFIG (0x10) +#define PL080S_CH_CONTROL2 (0x10) +#define PL080S_CH_CONFIG (0x14) + +#define PL080_LLI_ADDR_MASK (0x3fffffff << 2) +#define PL080_LLI_ADDR_SHIFT (2) +#define PL080_LLI_LM_AHB2 (1 << 0) + +#define PL080_CONTROL_TC_IRQ_EN (1 << 31) +#define PL080_CONTROL_PROT_MASK (0x7 << 28) +#define PL080_CONTROL_PROT_SHIFT (28) +#define PL080_CONTROL_PROT_SYS (1 << 28) +#define PL080_CONTROL_DST_INCR (1 << 27) +#define PL080_CONTROL_SRC_INCR (1 << 26) +#define PL080_CONTROL_DST_AHB2 (1 << 25) +#define PL080_CONTROL_SRC_AHB2 (1 << 24) +#define PL080_CONTROL_DWIDTH_MASK (0x7 << 21) +#define PL080_CONTROL_DWIDTH_SHIFT (21) +#define PL080_CONTROL_SWIDTH_MASK (0x7 << 18) +#define PL080_CONTROL_SWIDTH_SHIFT (18) +#define PL080_CONTROL_DB_SIZE_MASK (0x7 << 15) +#define PL080_CONTROL_DB_SIZE_SHIFT (15) +#define PL080_CONTROL_SB_SIZE_MASK (0x7 << 12) +#define PL080_CONTROL_SB_SIZE_SHIFT (12) +#define PL080_CONTROL_TRANSFER_SIZE_MASK (0xfff << 0) +#define PL080_CONTROL_TRANSFER_SIZE_SHIFT (0) + +#define PL080_BSIZE_1 (0x0) +#define PL080_BSIZE_4 (0x1) +#define PL080_BSIZE_8 (0x2) +#define PL080_BSIZE_16 (0x3) +#define PL080_BSIZE_32 (0x4) +#define PL080_BSIZE_64 (0x5) +#define PL080_BSIZE_128 (0x6) +#define PL080_BSIZE_256 (0x7) + +#define PL080_WIDTH_8BIT (0x0) +#define PL080_WIDTH_16BIT (0x1) +#define PL080_WIDTH_32BIT (0x2) + +#define PL080_CONFIG_HALT (1 << 18) +#define PL080_CONFIG_ACTIVE (1 << 17) /* RO */ +#define PL080_CONFIG_LOCK (1 << 16) +#define PL080_CONFIG_TC_IRQ_MASK (1 << 15) +#define PL080_CONFIG_ERR_IRQ_MASK (1 << 14) +#define PL080_CONFIG_FLOW_CONTROL_MASK (0x7 << 11) +#define PL080_CONFIG_FLOW_CONTROL_SHIFT (11) +#define PL080_CONFIG_DST_SEL_MASK (0xf << 6) +#define PL080_CONFIG_DST_SEL_SHIFT (6) +#define PL080_CONFIG_SRC_SEL_MASK (0xf << 1) +#define PL080_CONFIG_SRC_SEL_SHIFT (1) +#define PL080_CONFIG_ENABLE (1 << 0) + +#define PL080_FLOW_MEM2MEM (0x0) +#define PL080_FLOW_MEM2PER (0x1) +#define PL080_FLOW_PER2MEM (0x2) +#define PL080_FLOW_SRC2DST (0x3) +#define PL080_FLOW_SRC2DST_DST (0x4) +#define PL080_FLOW_MEM2PER_PER (0x5) +#define PL080_FLOW_PER2MEM_PER (0x6) +#define PL080_FLOW_SRC2DST_SRC (0x7) + +/* DMA linked list chain structure */ + +struct pl080_lli { + u32 src_addr; + u32 dst_addr; + u32 next_lli; + u32 control0; +}; + +struct pl080s_lli { + u32 src_addr; + u32 dst_addr; + u32 next_lli; + u32 control0; + u32 control1; +}; + diff --git a/arch/arm/mach-s3c6400/include/mach/dma.h b/arch/arm/mach-s3c6400/include/mach/dma.h index 9771ac2..1067619 100644 --- a/arch/arm/mach-s3c6400/include/mach/dma.h +++ b/arch/arm/mach-s3c6400/include/mach/dma.h @@ -11,6 +11,63 @@ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H __FILE__ -/* currently nothing here, placeholder */ +#define S3C_DMA_CHANNELS (16) + +/* see mach-s3c2410/dma.h for notes on dma channel numbers */ + +/* Note, for the S3C64XX architecture we keep the DMACH_ + * defines in the order they are allocated to [S]DMA0/[S]DMA1 + * so that is easy to do DHACH_ -> DMA controller conversion + */ +enum dma_ch { + /* DMA0/SDMA0 */ + DMACH_UART0 = 0, + DMACH_UART0_SRC2, + DMACH_UART1, + DMACH_UART1_SRC2, + DMACH_UART2, + DMACH_UART2_SRC2, + DMACH_UART3, + DMACH_UART3_SRC2, + DMACH_PCM0_TX, + DMACH_PCM0_RX, + DMACH_I2S0_OUT, + DMACH_I2S0_IN, + DMACH_SPI0_TX, + DMACH_SPI0_RX, + DMACH_HSI_I2SV40_TX, + DMACH_HSI_I2SV40_RX, + + /* DMA1/SDMA1 */ + DMACH_PCM1_TX = 16, + DMACH_PCM1_RX, + DMACH_I2S1_OUT, + DMACH_I2S1_IN, + DMACH_SPI1_TX, + DMACH_SPI1_RX, + DMACH_AC97_PCMOUT, + DMACH_AC97_PCMIN, + DMACH_AC97_MICIN, + DMACH_PWM, + DMACH_IRDA, + DMACH_EXTERNAL, + DMACH_RES1, + DMACH_RES2, + DMACH_SECURITY_RX, /* SDMA1 only */ + DMACH_SECURITY_TX, /* SDMA1 only */ + DMACH_MAX /* the end */ +}; + +static __inline__ int s3c_dma_has_circular(void) +{ + /* we will be supporting ciruclar buffers as soon as we have DMA + * engine support. + */ + return 1; +} + +#define S3C2410_DMAF_CIRCULAR (1 << 0) + +#include #endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig index 54375a0..9ce6615 100644 --- a/arch/arm/plat-s3c64xx/Kconfig +++ b/arch/arm/plat-s3c64xx/Kconfig @@ -38,6 +38,10 @@ config CPU_S3C6400_CLOCK Common clock support code for the S3C6400 that is shared by other CPUs in the series, such as the S3C6410. +config S3C64XX_DMA + bool "S3C64XX DMA" + select S3C_DMA + # platform specific device setup config S3C64XX_SETUP_I2C0 diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 2e6d79b..61bdb67 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -24,6 +24,10 @@ obj-y += gpiolib.o obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o +# DMA support + +obj-$(CONFIG_S3C64XX_DMA) += dma.o + # Device setup obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o diff --git a/arch/arm/plat-s3c64xx/dma.c b/arch/arm/plat-s3c64xx/dma.c new file mode 100644 index 0000000..1c0f51c --- /dev/null +++ b/arch/arm/plat-s3c64xx/dma.c @@ -0,0 +1,722 @@ +/* linux/arch/arm/plat-s3c64xx/dma.c + * + * Copyright 2009 Openmoko, Inc. + * Copyright 2009 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C64XX DMA core + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +/* dma channel state information */ + +struct s3c64xx_dmac { + struct sys_device sysdev; + struct clk *clk; + void __iomem *regs; + struct s3c2410_dma_chan *channels; + enum dma_ch chanbase; +}; + +/* pool to provide LLI buffers */ +static struct dma_pool *dma_pool; + +/* Debug configuration and code */ + +static unsigned char debug_show_buffs = 0; + +static void dbg_showchan(struct s3c2410_dma_chan *chan) +{ + pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n", + chan->number, + readl(chan->regs + PL080_CH_SRC_ADDR), + readl(chan->regs + PL080_CH_DST_ADDR), + readl(chan->regs + PL080_CH_LLI), + readl(chan->regs + PL080_CH_CONTROL), + readl(chan->regs + PL080S_CH_CONTROL2), + readl(chan->regs + PL080S_CH_CONFIG)); +} + +static void show_lli(struct pl080s_lli *lli) +{ + pr_debug("LLI[%p] %08x->%08x, NL %08x C %08x,%08x\n", + lli, lli->src_addr, lli->dst_addr, lli->next_lli, + lli->control0, lli->control1); +} + +static void dbg_showbuffs(struct s3c2410_dma_chan *chan) +{ + struct s3c64xx_dma_buff *ptr; + struct s3c64xx_dma_buff *end; + + pr_debug("DMA%d: buffs next %p, curr %p, end %p\n", + chan->number, chan->next, chan->curr, chan->end); + + ptr = chan->next; + end = chan->end; + + if (debug_show_buffs) { + for (; ptr != NULL; ptr = ptr->next) { + pr_debug("DMA%d: %08x ", + chan->number, ptr->lli_dma); + show_lli(ptr->lli); + } + } +} + +/* End of Debug */ + +static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel) +{ + struct s3c2410_dma_chan *chan; + unsigned int start, offs; + + start = 0; + + if (channel >= DMACH_PCM1_TX) + start = 8; + + for (offs = 0; offs < 8; offs++) { + chan = &s3c2410_chans[start + offs]; + if (!chan->in_use) + goto found; + } + + return NULL; + +found: + s3c_dma_chan_map[channel] = chan; + return chan; +} + +int s3c2410_dma_config(unsigned int channel, int xferunit) +{ + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); + + if (chan == NULL) + return -EINVAL; + + switch (xferunit) { + case 1: + chan->hw_width = 0; + break; + case 2: + chan->hw_width = 1; + break; + case 4: + chan->hw_width = 2; + break; + default: + printk(KERN_ERR "%s: illegal width %d\n", __func__, xferunit); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(s3c2410_dma_config); + +static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan, + struct pl080s_lli *lli, + dma_addr_t data, int size) +{ + dma_addr_t src, dst; + u32 control0, control1; + + switch (chan->source) { + case S3C2410_DMASRC_HW: + src = chan->dev_addr; + dst = data; + control0 = PL080_CONTROL_SRC_AHB2; + control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT; + control0 |= 2 << PL080_CONTROL_DWIDTH_SHIFT; + control0 |= PL080_CONTROL_DST_INCR; + break; + + case S3C2410_DMASRC_MEM: + src = data; + dst = chan->dev_addr; + control0 = PL080_CONTROL_DST_AHB2; + control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT; + control0 |= 2 << PL080_CONTROL_SWIDTH_SHIFT; + control0 |= PL080_CONTROL_SRC_INCR; + break; + default: + BUG(); + } + + /* note, we do not currently setup any of the burst controls */ + + control1 = size >> chan->hw_width; /* size in no of xfers */ + control0 |= PL080_CONTROL_PROT_SYS; /* always in priv. mode */ + control0 |= PL080_CONTROL_TC_IRQ_EN; /* always fire IRQ */ + + lli->src_addr = src; + lli->dst_addr = dst; + lli->next_lli = 0; + lli->control0 = control0; + lli->control1 = control1; +} + +static void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan, + struct pl080s_lli *lli) +{ + void __iomem *regs = chan->regs; + + pr_debug("%s: LLI %p => regs\n", __func__, lli); + show_lli(lli); + + writel(lli->src_addr, regs + PL080_CH_SRC_ADDR); + writel(lli->dst_addr, regs + PL080_CH_DST_ADDR); + writel(lli->next_lli, regs + PL080_CH_LLI); + writel(lli->control0, regs + PL080_CH_CONTROL); + writel(lli->control1, regs + PL080S_CH_CONTROL2); +} + +static int s3c64xx_dma_start(struct s3c2410_dma_chan *chan) +{ + struct s3c64xx_dmac *dmac = chan->dmac; + u32 config; + u32 bit = chan->bit; + + dbg_showchan(chan); + + pr_debug("%s: clearing interrupts\n", __func__); + + /* clear interrupts */ + writel(bit, dmac->regs + PL080_TC_CLEAR); + writel(bit, dmac->regs + PL080_ERR_CLEAR); + + pr_debug("%s: starting channel\n", __func__); + + config = readl(chan->regs + PL080S_CH_CONFIG); + config |= PL080_CONFIG_ENABLE; + + pr_debug("%s: writing config %08x\n", __func__, config); + writel(config, chan->regs + PL080S_CH_CONFIG); + + return 0; +} + +static int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan) +{ + u32 config; + int timeout; + + pr_debug("%s: stopping channel\n", __func__); + + dbg_showchan(chan); + + config = readl(chan->regs + PL080S_CH_CONFIG); + config |= PL080_CONFIG_HALT; + writel(config, chan->regs + PL080S_CH_CONFIG); + + timeout = 1000; + do { + config = readl(chan->regs + PL080S_CH_CONFIG); + pr_debug("%s: %d - config %08x\n", __func__, timeout, config); + if (config & PL080_CONFIG_ACTIVE) + udelay(10); + else + break; + } while (--timeout > 0); + + if (config & PL080_CONFIG_ACTIVE) { + printk(KERN_ERR "%s: channel still active\n", __func__); + return -EFAULT; + } + + config = readl(chan->regs + PL080S_CH_CONFIG); + config &= ~PL080_CONFIG_ENABLE; + writel(config, chan->regs + PL080S_CH_CONFIG); + + return 0; +} + +static inline void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan, + struct s3c64xx_dma_buff *buf, + enum s3c2410_dma_buffresult result) +{ + if (chan->callback_fn != NULL) + (chan->callback_fn)(chan, buf->pw, 0, result); +} + +static void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff) +{ + dma_pool_free(dma_pool, buff->lli, buff->lli_dma); + kfree(buff); +} + +static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan) +{ + struct s3c64xx_dma_buff *buff, *next; + u32 config; + + dbg_showchan(chan); + + pr_debug("%s: flushing channel\n", __func__); + + config = readl(chan->regs + PL080S_CH_CONFIG); + config &= ~PL080_CONFIG_ENABLE; + writel(config, chan->regs + PL080S_CH_CONFIG); + + /* dump all the buffers associated with this channel */ + + for (buff = chan->curr; buff != NULL; buff = next) { + next = buff->next; + pr_debug("%s: buff %p (next %p)\n", __func__, buff, buff->next); + + s3c64xx_dma_bufffdone(chan, buff, S3C2410_RES_ABORT); + s3c64xx_dma_freebuff(buff); + } + + chan->curr = chan->next = chan->end = NULL; + + return 0; +} + +int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op) +{ + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); + + WARN_ON(!chan); + if (!chan) + return -EINVAL; + + switch (op) { + case S3C2410_DMAOP_START: + return s3c64xx_dma_start(chan); + + case S3C2410_DMAOP_STOP: + return s3c64xx_dma_stop(chan); + + case S3C2410_DMAOP_FLUSH: + return s3c64xx_dma_flush(chan); + + /* belive PAUSE/RESUME are no-ops */ + case S3C2410_DMAOP_PAUSE: + case S3C2410_DMAOP_RESUME: + case S3C2410_DMAOP_STARTED: + case S3C2410_DMAOP_TIMEOUT: + return 0; + } + + return -ENOENT; +} +EXPORT_SYMBOL(s3c2410_dma_ctrl); + +/* s3c2410_dma_enque + * + */ + +int s3c2410_dma_enqueue(unsigned int channel, void *id, + dma_addr_t data, int size) +{ + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); + struct s3c64xx_dma_buff *next; + struct s3c64xx_dma_buff *buff; + struct pl080s_lli *lli; + int ret; + + WARN_ON(!chan); + if (!chan) + return -EINVAL; + + buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_KERNEL); + if (!buff) { + printk(KERN_ERR "%s: no memory for buffer\n", __func__); + return -ENOMEM; + } + + lli = dma_pool_alloc(dma_pool, GFP_KERNEL, &buff->lli_dma); + if (!lli) { + printk(KERN_ERR "%s: no memory for lli\n", __func__); + ret = -ENOMEM; + goto err_buff; + } + + pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n", + __func__, buff, data, lli, (u32)buff->lli_dma, size); + + buff->lli = lli; + buff->pw = id; + + s3c64xx_dma_fill_lli(chan, lli, data, size); + + if ((next = chan->next) != NULL) { + struct s3c64xx_dma_buff *end = chan->end; + struct pl080s_lli *endlli = end->lli; + + pr_debug("enquing onto channel\n"); + + end->next = buff; + endlli->next_lli = buff->lli_dma; + + if (chan->flags & S3C2410_DMAF_CIRCULAR) { + struct s3c64xx_dma_buff *curr = chan->curr; + lli->next_lli = curr->lli_dma; + } + + if (next == chan->curr) { + writel(buff->lli_dma, chan->regs + PL080_CH_LLI); + chan->next = buff; + } + + show_lli(endlli); + chan->end = buff; + } else { + pr_debug("enquing onto empty channel\n"); + + chan->curr = buff; + chan->next = buff; + chan->end = buff; + + s3c64xx_lli_to_regs(chan, lli); + } + + show_lli(lli); + + dbg_showchan(chan); + dbg_showbuffs(chan); + return 0; + +err_buff: + kfree(buff); + return ret; +} + +EXPORT_SYMBOL(s3c2410_dma_enqueue); + + +int s3c2410_dma_devconfig(int channel, + enum s3c2410_dmasrc source, + unsigned long devaddr) +{ + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); + u32 peripheral; + u32 config = 0; + + printk("%s: channel %d, source %d, dev %08lx, chan %p\n", + __func__, channel, source, devaddr, chan); + + WARN_ON(!chan); + if (!chan) + return -EINVAL; + + peripheral = (chan->peripheral & 0xf); + chan->source = source; + chan->dev_addr = devaddr; + + pr_debug("%s: peripheral %d\n", __func__, peripheral); + + switch (source) { + case S3C2410_DMASRC_HW: + config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT; + config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT; + break; + case S3C2410_DMASRC_MEM: + config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT; + config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT; + break; + default: + printk(KERN_ERR "%s: bad source\n", __func__); + return -EINVAL; + } + + /* allow TC and ERR interrupts */ + config |= PL080_CONFIG_TC_IRQ_MASK; + config |= PL080_CONFIG_ERR_IRQ_MASK; + + pr_debug("%s: config %08x\n", __func__, config); + + writel(config, chan->regs + PL080S_CH_CONFIG); + + return 0; +} +EXPORT_SYMBOL(s3c2410_dma_devconfig); + + +int s3c2410_dma_getposition(unsigned int channel, + dma_addr_t *src, dma_addr_t *dst) +{ + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); + + WARN_ON(!chan); + if (!chan) + return -EINVAL; + + if (src != NULL) + *src = readl(chan->regs + PL080_CH_SRC_ADDR); + + if (dst != NULL) + *dst = readl(chan->regs + PL080_CH_DST_ADDR); + + return 0; +} +EXPORT_SYMBOL(s3c2410_dma_getposition); + +/* s3c2410_request_dma + * + * get control of an dma channel +*/ + +int s3c2410_dma_request(unsigned int channel, + struct s3c2410_dma_client *client, + void *dev) +{ + struct s3c2410_dma_chan *chan; + unsigned long flags; + + pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n", + channel, client->name, dev); + + local_irq_save(flags); + + chan = s3c64xx_dma_map_channel(channel); + if (chan == NULL) { + local_irq_restore(flags); + return -EBUSY; + } + + dbg_showchan(chan); + + chan->client = client; + chan->in_use = 1; + chan->peripheral = channel; + + local_irq_restore(flags); + + /* need to setup */ + + pr_debug("%s: channel initialised, %p\n", __func__, chan); + + return chan->number | DMACH_LOW_LEVEL; +} + +EXPORT_SYMBOL(s3c2410_dma_request); + +/* s3c2410_dma_free + * + * release the given channel back to the system, will stop and flush + * any outstanding transfers, and ensure the channel is ready for the + * next claimant. + * + * Note, although a warning is currently printed if the freeing client + * info is not the same as the registrant's client info, the free is still + * allowed to go through. +*/ + +int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client) +{ + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); + unsigned long flags; + + if (chan == NULL) + return -EINVAL; + + local_irq_save(flags); + + if (chan->client != client) { + printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n", + channel, chan->client, client); + } + + /* sort out stopping and freeing the channel */ + + + chan->client = NULL; + chan->in_use = 0; + + if (!(channel & DMACH_LOW_LEVEL)) + s3c_dma_chan_map[channel] = NULL; + + local_irq_restore(flags); + + return 0; +} + +EXPORT_SYMBOL(s3c2410_dma_free); + + +static void s3c64xx_dma_tcirq(struct s3c64xx_dmac *dmac, int offs) +{ + struct s3c2410_dma_chan *chan = dmac->channels + offs; + + /* note, we currently do not bother to work out which buffer + * or buffers have been completed since the last tc-irq. */ + + if (chan->callback_fn) + (chan->callback_fn)(chan, chan->curr->pw, 0, S3C2410_RES_OK); +} + +static void s3c64xx_dma_errirq(struct s3c64xx_dmac *dmac, int offs) +{ + printk(KERN_DEBUG "%s: offs %d\n", __func__, offs); +} + +static irqreturn_t s3c64xx_dma_irq(int irq, void *pw) +{ + struct s3c64xx_dmac *dmac = pw; + u32 tcstat, errstat; + u32 bit; + int offs; + + tcstat = readl(dmac->regs + PL080_TC_STATUS); + errstat = readl(dmac->regs + PL080_ERR_STATUS); + + for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) { + if (tcstat & bit) { + writel(bit, dmac->regs + PL080_TC_CLEAR); + s3c64xx_dma_tcirq(dmac, offs); + } + + if (errstat & bit) { + s3c64xx_dma_errirq(dmac, offs); + writel(bit, dmac->regs + PL080_ERR_CLEAR); + } + } + + return IRQ_HANDLED; +} + +static struct sysdev_class dma_sysclass = { + .name = "s3c64xx-dma", +}; + +static int s3c64xx_dma_init1(int chno, enum dma_ch chbase, + int irq, unsigned int base) +{ + struct s3c2410_dma_chan *chptr = &s3c2410_chans[chno]; + struct s3c64xx_dmac *dmac; + char clkname[16]; + void __iomem *regs; + void __iomem *regptr; + int err, ch; + + dmac = kzalloc(sizeof(struct s3c64xx_dmac), GFP_KERNEL); + if (!dmac) { + printk(KERN_ERR "%s: failed to alloc mem\n", __func__); + return -ENOMEM; + } + + dmac->sysdev.id = chno / 8; + dmac->sysdev.cls = &dma_sysclass; + + err = sysdev_register(&dmac->sysdev); + if (err) { + printk(KERN_ERR "%s: failed to register sysdevice\n", __func__); + goto err_alloc; + } + + regs = ioremap(base, 0x200); + if (!regs) { + printk(KERN_ERR "%s: failed to ioremap()\n", __func__); + err = -ENXIO; + goto err_dev; + } + + snprintf(clkname, sizeof(clkname), "dma%d", dmac->sysdev.id); + + dmac->clk = clk_get(NULL, clkname); + if (IS_ERR(dmac->clk)) { + printk(KERN_ERR "%s: failed to get clock %s\n", __func__, clkname); + err = PTR_ERR(dmac->clk); + goto err_map; + } + + clk_enable(dmac->clk); + + dmac->regs = regs; + dmac->chanbase = chbase; + dmac->channels = chptr; + + err = request_irq(irq, s3c64xx_dma_irq, 0, "DMA", dmac); + if (err < 0) { + printk(KERN_ERR "%s: failed to get irq\n", __func__); + goto err_clk; + } + + regptr = regs + PL080_Cx_BASE(0); + + for (ch = 0; ch < 8; ch++, chno++, chptr++) { + printk(KERN_INFO "%s: registering DMA %d (%p)\n", + __func__, chno, regptr); + + chptr->bit = 1 << ch; + chptr->number = chno; + chptr->dmac = dmac; + chptr->regs = regptr; + regptr += PL008_Cx_STRIDE; + } + + /* for the moment, permanently enable the controller */ + writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG); + + printk(KERN_INFO "PL080: IRQ %d, at %p\n", irq, regs); + + return 0; + +err_clk: + clk_disable(dmac->clk); + clk_put(dmac->clk); +err_map: + iounmap(regs); +err_dev: + sysdev_unregister(&dmac->sysdev); +err_alloc: + kfree(dmac); + return err; +} + +static int __init s3c64xx_dma_init(void) +{ + int ret; + + printk(KERN_INFO "%s: Registering DMA channels\n", __func__); + + dma_pool = dma_pool_create("DMA-LLI", NULL, 32, 16, 0); + if (!dma_pool) { + printk(KERN_ERR "%s: failed to create pool\n", __func__); + return -ENOMEM; + } + + ret = sysdev_class_register(&dma_sysclass); + if (ret) { + printk(KERN_ERR "%s: failed to create sysclass\n", __func__); + return -ENOMEM; + } + + /* Set all DMA configuration to be DMA, not SDMA */ + writel(0xffffff, S3C_SYSREG(0x110)); + + /* Register standard DMA controlers */ + s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000); + s3c64xx_dma_init1(8, DMACH_PCM1_TX, IRQ_DMA1, 0x75100000); + + return 0; +} + +arch_initcall(s3c64xx_dma_init); diff --git a/arch/arm/plat-s3c64xx/include/plat/dma-plat.h b/arch/arm/plat-s3c64xx/include/plat/dma-plat.h new file mode 100644 index 0000000..0c30dd9 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/dma-plat.h @@ -0,0 +1,70 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/dma-plat.h + * + * Copyright 2009 Openmoko, Inc. + * Copyright 2009 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C64XX DMA core + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */ + +struct s3c64xx_dma_buff; + +/** s3c64xx_dma_buff - S3C64XX DMA buffer descriptor + * @next: Pointer to next buffer in queue or ring. + * @pw: Client provided identifier + * @lli: Pointer to hardware descriptor this buffer is associated with. + * @lli_dma: Hardare address of the descriptor. + */ +struct s3c64xx_dma_buff { + struct s3c64xx_dma_buff *next; + + void *pw; + struct pl080_lli *lli; + dma_addr_t lli_dma; +}; + +struct s3c64xx_dmac; + +struct s3c2410_dma_chan { + unsigned char number; /* number of this dma channel */ + unsigned char in_use; /* channel allocated */ + unsigned char bit; /* bit for enable/disable/etc */ + unsigned char hw_width; + unsigned char peripheral; + + unsigned int flags; + enum s3c2410_dmasrc source; + + + dma_addr_t dev_addr; + + struct s3c2410_dma_client *client; + struct s3c64xx_dmac *dmac; /* pointer to controller */ + + void __iomem *regs; + + /* cdriver callbacks */ + s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */ + s3c2410_dma_opfn_t op_fn; /* channel op callback */ + + /* buffer list and information */ + struct s3c64xx_dma_buff *curr; /* current dma buffer */ + struct s3c64xx_dma_buff *next; /* next buffer to load */ + struct s3c64xx_dma_buff *end; /* end of queue */ + + /* note, when channel is running in circular mode, curr is the + * first buffer enqueued, end is the last and curr is where the + * last buffer-done event is set-at. The buffers are not freed + * and the last buffer hardware descriptor points back to the + * first. + */ +}; + +#include -- cgit v0.10.2 From 0b13406a1f1928ec71e81dde52cb62d72ffd28ef Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Apr 2009 14:58:40 +0100 Subject: [ARM] S3C64XX: Lower severity of DMA logging The message was missing a severity macro so pick pr_debug(). Signed-off-by: Mark Brown Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s3c64xx/dma.c b/arch/arm/plat-s3c64xx/dma.c index 1c0f51c..67aa93d 100644 --- a/arch/arm/plat-s3c64xx/dma.c +++ b/arch/arm/plat-s3c64xx/dma.c @@ -419,7 +419,7 @@ int s3c2410_dma_devconfig(int channel, u32 peripheral; u32 config = 0; - printk("%s: channel %d, source %d, dev %08lx, chan %p\n", + pr_debug("%s: channel %d, source %d, dev %08lx, chan %p\n", __func__, channel, source, devaddr, chan); WARN_ON(!chan); -- cgit v0.10.2