diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c index c9cd51439126ad2a122d1f46988a7d1536e77c21..1dd8649935662383989c81cc6d90fea834152390 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), diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index aae1b9cbaf44b77a0e9f4ea7e9f37c04cd1a1191..10ef3995b11483198025229a13b63e41b999f4db 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -1184,7 +1184,7 @@ int s3c2410_dma_devconfig(int channel, dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0)); chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST); - return 0; + break; case S3C2410_DMASRC_MEM: /* source is memory */ @@ -1195,11 +1195,19 @@ int s3c2410_dma_devconfig(int channel, dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3); chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC); - return 0; + break; + + default: + printk(KERN_ERR "dma%d: invalid source type (%d)\n", + channel, source); + + return -EINVAL; } - printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source); - return -EINVAL; + if (dma_sel.direction != NULL) + (dma_sel.direction)(chan, chan->map, source); + + return 0; } EXPORT_SYMBOL(s3c2410_dma_devconfig); diff --git a/include/asm-arm/plat-s3c24xx/dma.h b/include/asm-arm/plat-s3c24xx/dma.h index 2c59406435e56f1cc244c9258a60bc38c075cb14..c78efe316fc80ad351ed2f8e9bd07350ec133adc 100644 --- a/include/asm-arm/plat-s3c24xx/dma.h +++ b/include/asm-arm/plat-s3c24xx/dma.h @@ -32,6 +32,7 @@ struct s3c24xx_dma_map { struct s3c24xx_dma_addr hw_addr; unsigned long channels[S3C2410_DMA_CHANNELS]; + unsigned long channels_rx[S3C2410_DMA_CHANNELS]; }; struct s3c24xx_dma_selection { @@ -41,6 +42,10 @@ struct s3c24xx_dma_selection { 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);