352 lines
7.6 KiB
C
352 lines
7.6 KiB
C
/* linux/arch/arm/mach-s3c6410/dma.c
|
|
*
|
|
* Copyright (c) 2003-2005,2006 Samsung Electronics
|
|
*
|
|
* S3C6400 DMA selection
|
|
*
|
|
* http://www.samsung.com/
|
|
*
|
|
* 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 <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/sysdev.h>
|
|
#include <linux/serial_core.h>
|
|
|
|
#include <asm/dma.h>
|
|
#include <asm/arch/dma.h>
|
|
#include <asm/io.h>
|
|
|
|
#include <asm/plat-s3c24xx/dma.h>
|
|
#include <asm/plat-s3c24xx/cpu.h>
|
|
|
|
|
|
/* DMAC-0 */
|
|
#define MAP0(x) { \
|
|
[0] = (x) | DMA_CH_VALID, \
|
|
[1] = (x) | DMA_CH_VALID, \
|
|
[2] = (x) | DMA_CH_VALID, \
|
|
[3] = (x) | DMA_CH_VALID, \
|
|
[4] = (x) | DMA_CH_VALID, \
|
|
[5] = (x) | DMA_CH_VALID, \
|
|
[6] = (x) | DMA_CH_VALID, \
|
|
[7] = (x) | DMA_CH_VALID, \
|
|
[8] = (x), \
|
|
[9] = (x), \
|
|
[10] = (x), \
|
|
[11] = (x), \
|
|
[12] = (x), \
|
|
[13] = (x), \
|
|
[14] = (x), \
|
|
[15] = (x), \
|
|
[16] = (x), \
|
|
[17] = (x), \
|
|
[18] = (x), \
|
|
[19] = (x), \
|
|
[20] = (x), \
|
|
[21] = (x), \
|
|
[22] = (x), \
|
|
[23] = (x), \
|
|
[24] = (x), \
|
|
[25] = (x), \
|
|
[26] = (x), \
|
|
[27] = (x), \
|
|
[28] = (x), \
|
|
[29] = (x), \
|
|
[30] = (x), \
|
|
[31] = (x), \
|
|
}
|
|
|
|
/* DMAC-1 */
|
|
#define MAP1(x) { \
|
|
[0] = (x), \
|
|
[1] = (x), \
|
|
[2] = (x), \
|
|
[3] = (x), \
|
|
[4] = (x), \
|
|
[5] = (x), \
|
|
[6] = (x), \
|
|
[7] = (x), \
|
|
[8] = (x) | DMA_CH_VALID, \
|
|
[9] = (x) | DMA_CH_VALID, \
|
|
[10] = (x) | DMA_CH_VALID, \
|
|
[11] = (x) | DMA_CH_VALID, \
|
|
[12] = (x) | DMA_CH_VALID, \
|
|
[13] = (x) | DMA_CH_VALID, \
|
|
[14] = (x) | DMA_CH_VALID, \
|
|
[15] = (x) | DMA_CH_VALID, \
|
|
[16] = (x), \
|
|
[17] = (x), \
|
|
[18] = (x), \
|
|
[19] = (x), \
|
|
[20] = (x), \
|
|
[21] = (x), \
|
|
[22] = (x), \
|
|
[23] = (x), \
|
|
[24] = (x), \
|
|
[25] = (x), \
|
|
[26] = (x), \
|
|
[27] = (x), \
|
|
[28] = (x), \
|
|
[29] = (x), \
|
|
[30] = (x), \
|
|
[31] = (x), \
|
|
}
|
|
|
|
/* SDMAC-0 */
|
|
#define MAP2(x) { \
|
|
[0] = (x), \
|
|
[1] = (x), \
|
|
[2] = (x), \
|
|
[3] = (x), \
|
|
[4] = (x), \
|
|
[5] = (x), \
|
|
[6] = (x), \
|
|
[7] = (x), \
|
|
[8] = (x), \
|
|
[9] = (x), \
|
|
[10] = (x), \
|
|
[11] = (x), \
|
|
[12] = (x), \
|
|
[13] = (x), \
|
|
[14] = (x), \
|
|
[15] = (x), \
|
|
[16] = (x) | DMA_CH_VALID, \
|
|
[17] = (x) | DMA_CH_VALID, \
|
|
[18] = (x) | DMA_CH_VALID, \
|
|
[19] = (x) | DMA_CH_VALID, \
|
|
[20] = (x) | DMA_CH_VALID, \
|
|
[21] = (x) | DMA_CH_VALID, \
|
|
[22] = (x) | DMA_CH_VALID, \
|
|
[23] = (x) | DMA_CH_VALID, \
|
|
[24] = (x), \
|
|
[25] = (x), \
|
|
[26] = (x), \
|
|
[27] = (x), \
|
|
[28] = (x), \
|
|
[29] = (x), \
|
|
[30] = (x), \
|
|
[31] = (x), \
|
|
}
|
|
|
|
/* SDMAC-1 */
|
|
#define MAP3(x) { \
|
|
[0] = (x), \
|
|
[1] = (x), \
|
|
[2] = (x), \
|
|
[3] = (x), \
|
|
[4] = (x), \
|
|
[5] = (x), \
|
|
[6] = (x), \
|
|
[7] = (x), \
|
|
[8] = (x), \
|
|
[9] = (x), \
|
|
[10] = (x), \
|
|
[11] = (x), \
|
|
[12] = (x), \
|
|
[13] = (x), \
|
|
[14] = (x), \
|
|
[15] = (x), \
|
|
[16] = (x), \
|
|
[17] = (x), \
|
|
[18] = (x), \
|
|
[19] = (x), \
|
|
[20] = (x), \
|
|
[21] = (x), \
|
|
[22] = (x), \
|
|
[23] = (x), \
|
|
[24] = (x) | DMA_CH_VALID, \
|
|
[25] = (x) | DMA_CH_VALID, \
|
|
[26] = (x) | DMA_CH_VALID, \
|
|
[27] = (x) | DMA_CH_VALID, \
|
|
[28] = (x) | DMA_CH_VALID, \
|
|
[29] = (x) | DMA_CH_VALID, \
|
|
[30] = (x) | DMA_CH_VALID, \
|
|
[31] = (x) | DMA_CH_VALID, \
|
|
}
|
|
|
|
/* SDMAC-0 */
|
|
#define MAP2_ONENAND(x) { \
|
|
[0] = (x), \
|
|
[1] = (x), \
|
|
[2] = (x), \
|
|
[3] = (x) , \
|
|
[4] = (x), \
|
|
[5] = (x), \
|
|
[6] = (x), \
|
|
[7] = (x), \
|
|
[8] = (x), \
|
|
[9] = (x), \
|
|
[10] = (x), \
|
|
[11] = (x), \
|
|
[12] = (x), \
|
|
[13] = (x), \
|
|
[14] = (x), \
|
|
[15] = (x), \
|
|
[16] = (x), \
|
|
[17] = (x), \
|
|
[18] = (x) , \
|
|
[19] = (x) | DMA_CH_VALID, \
|
|
[20] = (x), \
|
|
[21] = (x), \
|
|
[22] = (x), \
|
|
[23] = (x), \
|
|
[24] = (x), \
|
|
[25] = (x), \
|
|
[26] = (x), \
|
|
[27] = (x), \
|
|
[28] = (x), \
|
|
[29] = (x), \
|
|
[30] = (x), \
|
|
[31] = (x), \
|
|
}
|
|
|
|
static struct s3c24xx_dma_map __initdata s3c6400_dma_mappings[] = {
|
|
|
|
[DMACH_I2S_IN] = {
|
|
.name = "i2s0-in",
|
|
.channels = MAP0(S3C_DMA0_I2S0_RX),
|
|
.hw_addr.from = S3C_DMA0_I2S0_RX,
|
|
.sdma_sel = 1 << S3C_DMA0_I2S0_RX,
|
|
},
|
|
[DMACH_I2S_OUT] = {
|
|
.name = "i2s0-out",
|
|
.channels = MAP0(S3C_DMA0_I2S0_TX),
|
|
.hw_addr.to = S3C_DMA0_I2S0_TX,
|
|
.sdma_sel = 1 << S3C_DMA0_I2S0_TX,
|
|
},
|
|
[DMACH_I2S1_IN] = {
|
|
.name = "i2s1-in",
|
|
.channels = MAP1(S3C_DMA1_I2S1_RX),
|
|
.hw_addr.from = S3C_DMA1_I2S1_RX,
|
|
.sdma_sel = 1 << (S3C_DMA1_I2S1_RX+S3C_DMA1),
|
|
},
|
|
[DMACH_I2S1_OUT] = {
|
|
.name = "i2s1-out",
|
|
.channels = MAP1(S3C_DMA1_I2S1_TX),
|
|
.hw_addr.to = S3C_DMA1_I2S1_TX,
|
|
.sdma_sel = 1 << (S3C_DMA1_I2S1_TX+S3C_DMA1),
|
|
},
|
|
[DMACH_SPI0_IN] = {
|
|
.name = "spi0-in",
|
|
.channels = MAP0(S3C_DMA0_SPI0_RX),
|
|
.hw_addr.from = S3C_DMA0_SPI0_RX,
|
|
.sdma_sel = 1 << S3C_DMA0_SPI0_RX,
|
|
},
|
|
[DMACH_SPI0_OUT] = {
|
|
.name = "spi0-out",
|
|
.channels = MAP0(S3C_DMA0_SPI0_TX),
|
|
.hw_addr.to = S3C_DMA0_SPI0_TX,
|
|
.sdma_sel = 1 << S3C_DMA0_SPI0_TX,
|
|
},
|
|
[DMACH_SPI1_IN] = {
|
|
.name = "spi1-in",
|
|
.channels = MAP1(S3C_DMA1_SPI1_RX),
|
|
.hw_addr.from = S3C_DMA1_SPI1_RX,
|
|
.sdma_sel = 1 << (S3C_DMA1_SPI1_RX+S3C_DMA1),
|
|
},
|
|
[DMACH_SPI1_OUT] = {
|
|
.name = "spi1-out",
|
|
.channels = MAP1(S3C_DMA1_SPI1_TX),
|
|
.hw_addr.to = S3C_DMA1_SPI1_TX,
|
|
.sdma_sel = 1 << (S3C_DMA1_SPI1_TX+S3C_DMA1),
|
|
},
|
|
[DMACH_AC97_PCM_OUT] = {
|
|
.name = "ac97-pcm-out",
|
|
.channels = MAP1(S3C_DMA1_AC97_PCMOUT),
|
|
.hw_addr.to = S3C_DMA1_AC97_PCMOUT,
|
|
.sdma_sel = 1 << (S3C_DMA1_AC97_PCMOUT+S3C_DMA1),
|
|
},
|
|
[DMACH_AC97_PCM_IN] = {
|
|
.name = "ac97-pcm-in",
|
|
.channels = MAP1(S3C_DMA1_AC97_PCMIN),
|
|
.hw_addr.from = S3C_DMA1_AC97_PCMIN,
|
|
.sdma_sel = 1 << (S3C_DMA1_AC97_PCMIN+S3C_DMA1),
|
|
},
|
|
[DMACH_AC97_MIC_IN] = {
|
|
.name = "ac97-mic-in",
|
|
.channels = MAP1(S3C_DMA1_AC97_MICIN),
|
|
.hw_addr.from = S3C_DMA1_AC97_MICIN,
|
|
.sdma_sel = 1 << (S3C_DMA1_AC97_MICIN+S3C_DMA1),
|
|
},
|
|
[DMACH_ONENAND_IN] = {
|
|
.name = "onenand-in",
|
|
.channels = MAP2_ONENAND(S3C_DMA0_ONENAND_RX),
|
|
.hw_addr.from = S3C_DMA0_ONENAND_RX,
|
|
},
|
|
[DMACH_I2S_V40_IN] = {
|
|
.name = "i2s-v40-in",
|
|
.channels = MAP0(S3C_DMA0_HSI_RX),
|
|
.hw_addr.from = S3C_DMA0_HSI_RX,
|
|
.sdma_sel = 1 << S3C_DMA0_HSI_RX,
|
|
},
|
|
[DMACH_I2S_V40_OUT] = {
|
|
.name = "i2s-v40-out",
|
|
.channels = MAP0(S3C_DMA0_HSI_TX),
|
|
.hw_addr.to = S3C_DMA0_HSI_TX,
|
|
.sdma_sel = 1 << S3C_DMA0_HSI_TX,
|
|
},
|
|
[DMACH_PCMIF_CH0_TX] = {
|
|
.name = "pcmif_ch0_tx",
|
|
.channels = MAP0(S3C_DMA0_PCM0_TX),
|
|
.hw_addr.from = S3C_DMA0_PCM0_TX,
|
|
.sdma_sel = 1 << S3C_DMA0_PCM0_TX,
|
|
},
|
|
[DMACH_PCMIF_CH0_RX] = {
|
|
.name = "pcmif_ch0_rx",
|
|
.channels = MAP0(S3C_DMA0_PCM0_RX),
|
|
.hw_addr.from = S3C_DMA0_PCM0_RX,
|
|
.sdma_sel = 1 << S3C_DMA0_PCM0_RX,
|
|
},
|
|
#ifdef CONFIG_SND_S3C6410_SOC_PCMIF
|
|
[DMACH_PCMIF_CH1_TX] = {
|
|
.name = "pcmif_ch1_tx",
|
|
.channels = MAP3(S3C_DMA1_PCM1_TX),
|
|
.hw_addr.from = S3C_DMA1_PCM1_TX,
|
|
/* TODO: sdma_sel length is out order */
|
|
.sdma_sel = 1 << (S3C_DMA1_PCM1_TX+S3C_DMA3),
|
|
},
|
|
[DMACH_PCMIF_CH1_RX] = {
|
|
.name = "pcmif_ch1_rx",
|
|
.channels = MAP1(S3C_DMA1_PCM1_RX),
|
|
.hw_addr.from = S3C_DMA1_PCM1_RX,
|
|
.sdma_sel = 1 << (S3C_DMA1_PCM1_RX+S3C_DMA1),
|
|
},
|
|
#endif
|
|
};
|
|
|
|
static void s3c6400_dma_select(struct s3c2410_dma_chan *chan,
|
|
struct s3c24xx_dma_map *map)
|
|
{
|
|
chan->map = map;
|
|
}
|
|
|
|
static struct s3c24xx_dma_selection __initdata s3c6400_dma_sel = {
|
|
.select = s3c6400_dma_select,
|
|
.dcon_mask = 0,
|
|
.map = s3c6400_dma_mappings,
|
|
.map_size = ARRAY_SIZE(s3c6400_dma_mappings),
|
|
};
|
|
|
|
static int s3c6400_dma_add(struct sys_device *sysdev)
|
|
{
|
|
s3c24xx_dma_init(S3C2410_DMA_CHANNELS, IRQ_DMA0, 0x20);
|
|
return s3c24xx_dma_init_map(&s3c6400_dma_sel);
|
|
}
|
|
|
|
static struct sysdev_driver s3c6400_dma_driver = {
|
|
.add = s3c6400_dma_add,
|
|
};
|
|
|
|
static int __init s3c6400_dma_init(void)
|
|
{
|
|
return sysdev_driver_register(&s3c6400_sysclass, &s3c6400_dma_driver);
|
|
}
|
|
|
|
arch_initcall(s3c6400_dma_init);
|
|
|
|
|