--- 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 @@ -13,8 +13,8 @@ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H __FILE__ +#include #include -#include #define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */ @@ -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 */ @@ -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 @@ -104,32 +103,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 */ @@ -137,19 +110,18 @@ enum s3c2410_chan_op { * waiting for reloads */ #define S3C2410_DMAF_AUTOSTART (1<<1) /* auto-start if buffer queued */ +#define S3C2410_DMAF_CIRCULAR (0x00) /* circular enqueue not supp. */ + /* 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 */ @@ -161,20 +133,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; @@ -206,10 +164,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 */ @@ -236,213 +194,12 @@ 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; -/* 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, int dcon); - -/* s3c2410_dma_devconfig - * - * configure the device we're talking to -*/ - -extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, - int hwcfg, 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); - -/* 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) +static int s3c_dma_has_circular(void) +{ + return 0; +} #endif /* __ASM_ARCH_DMA_H */ --- a/arch/arm/mach-s3c2442/Kconfig +++ b/arch/arm/mach-s3c2442/Kconfig @@ -11,6 +11,7 @@ config CPU_S3C2442 select S3C2410_CLOCK select S3C2410_GPIO select S3C2410_PM if PM + select S3C2440_DMA if S3C2410_DMA select CPU_S3C244X select CPU_LLSERIAL_S3C2440 help --- /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); --- /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[]; + + --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/dma.h @@ -0,0 +1,128 @@ +/* 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); + + --- 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 --- 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 @@ -31,3 +35,5 @@ obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmm obj-y += dev-i2c0.o obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o +obj-$(CONFIG_S3C_DMA) += dma.o + --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -31,10 +31,11 @@ #include #include #include - #include -#include +#include +#include +#include /* io map for dma */ static void __iomem *dma_base; @@ -44,8 +45,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 +134,6 @@ dmadbg_showregs(const char *fname, int l #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 +198,6 @@ s3c2410_dma_waitforload(struct s3c2410_d return 0; } - - /* s3c2410_dma_loadbuffer * * load a buffer, and update the channel state @@ -453,7 +435,7 @@ s3c2410_dma_canload(struct s3c2410_dma_c 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 +786,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 +818,7 @@ int s3c2410_dma_free(unsigned int channe 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 +977,7 @@ static int s3c2410_dma_started(struct s3 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; @@ -1038,14 +1020,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); + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); + unsigned int dcon; pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n", __func__, channel, xferunit, dcon); @@ -1055,10 +1036,33 @@ int s3c2410_dma_config(unsigned int chan 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; @@ -1089,10 +1093,10 @@ int s3c2410_dma_config(unsigned int chan } EXPORT_SYMBOL(s3c2410_dma_config); - +#if 0 /* moved to plat-s3c? */ int s3c2410_dma_setflags(unsigned int channel, unsigned int flags) { - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); if (chan == NULL) return -EINVAL; @@ -1105,43 +1109,7 @@ int s3c2410_dma_setflags(unsigned int ch } 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); +#endif /* s3c2410_dma_devconfig * @@ -1150,29 +1118,38 @@ EXPORT_SYMBOL(s3c2410_dma_set_buffdone_f * 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); + struct s3c2410_dma_chan *chan = s3c_dma_lookup_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: @@ -1219,7 +1196,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; @@ -1278,8 +1255,8 @@ static int s3c2410_dma_resume(struct sys 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,7 +1453,8 @@ static struct s3c2410_dma_chan *s3c2410_ found: dmach = &s3c2410_chans[ch]; dmach->map = ch_map; - dma_chan_map[channel] = dmach; + dmach->req_ch = channel; + s3c_dma_chan_map[channel] = dmach; /* select the channel */ --- 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); --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/plat/dma-plat.h @@ -0,0 +1,84 @@ +/* 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. +*/ + +#include + +extern struct sysdev_class dma_sysclass; +extern struct s3c2410_dma_chan s3c2410_chans[S3C_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[S3C_DMA_CHANNELS]; + unsigned long channels_rx[S3C_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[S3C_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); --- /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) + +#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) +#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) --- 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 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -17,14 +17,16 @@ #include #include +#include #include #include -#include +#include #include #include #include +#include #include #include #include --- a/arch/arm/mach-s3c2440/dma.c +++ b/arch/arm/mach-s3c2440/dma.c @@ -17,14 +17,16 @@ #include #include +#include #include -#include +#include #include #include #include #include +#include #include #include #include --- a/sound/soc/s3c24xx/s3c24xx-pcm.c +++ b/sound/soc/s3c24xx/s3c24xx-pcm.c @@ -218,24 +218,17 @@ static int s3c24xx_pcm_prepare(struct sn * 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;