From c6709e8ef5752314c22c75bc7575f9be390e215b Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 28 Jan 2008 13:01:20 +0100 Subject: [ARM] 4780/1: S3C2412: Allow for seperate DMA channels for TX and RX The current S3C24XX DMA code does not allow for an peripheral that has one channel for RX and another for TX. This patch adds a per-cpu dma operation to select the transmit or receive channel, and adds support to the S3C2412 for the seperate DMA channels for TX and RX. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2412/dma.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-s3c2412/dma.c') diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c index c9cd5143912..1dd86499356 100644 --- a/arch/arm/mach-s3c2412/dma.c +++ b/arch/arm/mach-s3c2412/dma.c @@ -40,106 +40,141 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = { [DMACH_XD0] = { .name = "xdreq0", .channels = MAP(S3C2412_DMAREQSEL_XDREQ0), + .channels_rx = MAP(S3C2412_DMAREQSEL_XDREQ0), }, [DMACH_XD1] = { .name = "xdreq1", .channels = MAP(S3C2412_DMAREQSEL_XDREQ1), + .channels_rx = MAP(S3C2412_DMAREQSEL_XDREQ1), }, [DMACH_SDI] = { .name = "sdi", .channels = MAP(S3C2412_DMAREQSEL_SDI), + .channels_rx = MAP(S3C2412_DMAREQSEL_SDI), .hw_addr.to = S3C2410_PA_SDI + S3C2410_SDIDATA, .hw_addr.from = S3C2410_PA_SDI + S3C2410_SDIDATA, }, [DMACH_SPI0] = { .name = "spi0", .channels = MAP(S3C2412_DMAREQSEL_SPI0TX), + .channels_rx = MAP(S3C2412_DMAREQSEL_SPI0RX), .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT, .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT, }, [DMACH_SPI1] = { .name = "spi1", .channels = MAP(S3C2412_DMAREQSEL_SPI1TX), + .channels_rx = MAP(S3C2412_DMAREQSEL_SPI1RX), .hw_addr.to = S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPTDAT, .hw_addr.from = S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPRDAT, }, [DMACH_UART0] = { .name = "uart0", .channels = MAP(S3C2412_DMAREQSEL_UART0_0), + .channels_rx = MAP(S3C2412_DMAREQSEL_UART0_0), .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH, .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH, }, [DMACH_UART1] = { .name = "uart1", .channels = MAP(S3C2412_DMAREQSEL_UART1_0), + .channels_rx = MAP(S3C2412_DMAREQSEL_UART1_0), .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH, .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH, }, [DMACH_UART2] = { .name = "uart2", .channels = MAP(S3C2412_DMAREQSEL_UART2_0), + .channels_rx = MAP(S3C2412_DMAREQSEL_UART2_0), .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH, .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH, }, [DMACH_UART0_SRC2] = { .name = "uart0", .channels = MAP(S3C2412_DMAREQSEL_UART0_1), + .channels_rx = MAP(S3C2412_DMAREQSEL_UART0_1), .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH, .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH, }, [DMACH_UART1_SRC2] = { .name = "uart1", .channels = MAP(S3C2412_DMAREQSEL_UART1_1), + .channels_rx = MAP(S3C2412_DMAREQSEL_UART1_1), .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH, .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH, }, [DMACH_UART2_SRC2] = { .name = "uart2", .channels = MAP(S3C2412_DMAREQSEL_UART2_1), + .channels_rx = MAP(S3C2412_DMAREQSEL_UART2_1), .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH, .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH, }, [DMACH_TIMER] = { .name = "timer", .channels = MAP(S3C2412_DMAREQSEL_TIMER), + .channels_rx = MAP(S3C2412_DMAREQSEL_TIMER), }, [DMACH_I2S_IN] = { .name = "i2s-sdi", .channels = MAP(S3C2412_DMAREQSEL_I2SRX), + .channels_rx = MAP(S3C2412_DMAREQSEL_I2SRX), .hw_addr.from = S3C2410_PA_IIS + S3C2412_IISRXD, }, [DMACH_I2S_OUT] = { .name = "i2s-sdo", .channels = MAP(S3C2412_DMAREQSEL_I2STX), + .channels_rx = MAP(S3C2412_DMAREQSEL_I2STX), .hw_addr.to = S3C2410_PA_IIS + S3C2412_IISTXD, }, [DMACH_USB_EP1] = { .name = "usb-ep1", .channels = MAP(S3C2412_DMAREQSEL_USBEP1), + .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP1), }, [DMACH_USB_EP2] = { .name = "usb-ep2", .channels = MAP(S3C2412_DMAREQSEL_USBEP2), + .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP2), }, [DMACH_USB_EP3] = { .name = "usb-ep3", .channels = MAP(S3C2412_DMAREQSEL_USBEP3), + .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP3), }, [DMACH_USB_EP4] = { .name = "usb-ep4", .channels = MAP(S3C2412_DMAREQSEL_USBEP4), + .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP4), }, }; +static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan, + struct s3c24xx_dma_map *map, + enum s3c2410_dmasrc dir) +{ + unsigned long chsel; + + if (dir == S3C2410_DMASRC_HW) + chsel = map->channels_rx[0]; + else + chsel = map->channels[0]; + + chsel &= ~DMA_CH_VALID; + chsel |= S3C2412_DMAREQSEL_HW; + + writel(chsel, chan->regs + S3C2412_DMA_DMAREQSEL); +} + static void s3c2412_dma_select(struct s3c2410_dma_chan *chan, struct s3c24xx_dma_map *map) { - writel(map->channels[0] | S3C2412_DMAREQSEL_HW, - chan->regs + S3C2412_DMA_DMAREQSEL); + s3c2412_dma_direction(chan, map, chan->source); } static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = { .select = s3c2412_dma_select, + .direction = s3c2412_dma_direction, .dcon_mask = 0, .map = s3c2412_dma_mappings, .map_size = ARRAY_SIZE(s3c2412_dma_mappings), -- cgit v1.2.3