1/* linux/arch/arm/mach-s3c2412/dma.c 2 * 3 * Copyright (c) 2006 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * 6 * S3C2412 DMA selection 7 * 8 * http://armlinux.simtec.co.uk/ 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13*/ 14 15#include <linux/kernel.h> 16#include <linux/init.h> 17#include <linux/device.h> 18#include <linux/serial_core.h> 19#include <linux/io.h> 20 21#include <mach/dma.h> 22 23#include <plat/dma-s3c24xx.h> 24#include <plat/cpu.h> 25 26#include <plat/regs-serial.h> 27#include <mach/regs-gpio.h> 28#include <plat/regs-ac97.h> 29#include <plat/regs-dma.h> 30#include <mach/regs-mem.h> 31#include <mach/regs-lcd.h> 32#include <mach/regs-sdi.h> 33#include <plat/regs-iis.h> 34#include <plat/regs-spi.h> 35 36#define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID } 37 38static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = { 39 [DMACH_XD0] = { 40 .name = "xdreq0", 41 .channels = MAP(S3C2412_DMAREQSEL_XDREQ0), 42 .channels_rx = MAP(S3C2412_DMAREQSEL_XDREQ0), 43 }, 44 [DMACH_XD1] = { 45 .name = "xdreq1", 46 .channels = MAP(S3C2412_DMAREQSEL_XDREQ1), 47 .channels_rx = MAP(S3C2412_DMAREQSEL_XDREQ1), 48 }, 49 [DMACH_SDI] = { 50 .name = "sdi", 51 .channels = MAP(S3C2412_DMAREQSEL_SDI), 52 .channels_rx = MAP(S3C2412_DMAREQSEL_SDI), 53 }, 54 [DMACH_SPI0] = { 55 .name = "spi0", 56 .channels = MAP(S3C2412_DMAREQSEL_SPI0TX), 57 .channels_rx = MAP(S3C2412_DMAREQSEL_SPI0RX), 58 }, 59 [DMACH_SPI1] = { 60 .name = "spi1", 61 .channels = MAP(S3C2412_DMAREQSEL_SPI1TX), 62 .channels_rx = MAP(S3C2412_DMAREQSEL_SPI1RX), 63 }, 64 [DMACH_UART0] = { 65 .name = "uart0", 66 .channels = MAP(S3C2412_DMAREQSEL_UART0_0), 67 .channels_rx = MAP(S3C2412_DMAREQSEL_UART0_0), 68 }, 69 [DMACH_UART1] = { 70 .name = "uart1", 71 .channels = MAP(S3C2412_DMAREQSEL_UART1_0), 72 .channels_rx = MAP(S3C2412_DMAREQSEL_UART1_0), 73 }, 74 [DMACH_UART2] = { 75 .name = "uart2", 76 .channels = MAP(S3C2412_DMAREQSEL_UART2_0), 77 .channels_rx = MAP(S3C2412_DMAREQSEL_UART2_0), 78 }, 79 [DMACH_UART0_SRC2] = { 80 .name = "uart0", 81 .channels = MAP(S3C2412_DMAREQSEL_UART0_1), 82 .channels_rx = MAP(S3C2412_DMAREQSEL_UART0_1), 83 }, 84 [DMACH_UART1_SRC2] = { 85 .name = "uart1", 86 .channels = MAP(S3C2412_DMAREQSEL_UART1_1), 87 .channels_rx = MAP(S3C2412_DMAREQSEL_UART1_1), 88 }, 89 [DMACH_UART2_SRC2] = { 90 .name = "uart2", 91 .channels = MAP(S3C2412_DMAREQSEL_UART2_1), 92 .channels_rx = MAP(S3C2412_DMAREQSEL_UART2_1), 93 }, 94 [DMACH_TIMER] = { 95 .name = "timer", 96 .channels = MAP(S3C2412_DMAREQSEL_TIMER), 97 .channels_rx = MAP(S3C2412_DMAREQSEL_TIMER), 98 }, 99 [DMACH_I2S_IN] = { 100 .name = "i2s-sdi", 101 .channels = MAP(S3C2412_DMAREQSEL_I2SRX), 102 .channels_rx = MAP(S3C2412_DMAREQSEL_I2SRX), 103 }, 104 [DMACH_I2S_OUT] = { 105 .name = "i2s-sdo", 106 .channels = MAP(S3C2412_DMAREQSEL_I2STX), 107 .channels_rx = MAP(S3C2412_DMAREQSEL_I2STX), 108 }, 109 [DMACH_USB_EP1] = { 110 .name = "usb-ep1", 111 .channels = MAP(S3C2412_DMAREQSEL_USBEP1), 112 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP1), 113 }, 114 [DMACH_USB_EP2] = { 115 .name = "usb-ep2", 116 .channels = MAP(S3C2412_DMAREQSEL_USBEP2), 117 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP2), 118 }, 119 [DMACH_USB_EP3] = { 120 .name = "usb-ep3", 121 .channels = MAP(S3C2412_DMAREQSEL_USBEP3), 122 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP3), 123 }, 124 [DMACH_USB_EP4] = { 125 .name = "usb-ep4", 126 .channels = MAP(S3C2412_DMAREQSEL_USBEP4), 127 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP4), 128 }, 129}; 130 131static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan, 132 struct s3c24xx_dma_map *map, 133 enum dma_data_direction dir) 134{ 135 unsigned long chsel; 136 137 if (dir == DMA_FROM_DEVICE) 138 chsel = map->channels_rx[0]; 139 else 140 chsel = map->channels[0]; 141 142 chsel &= ~DMA_CH_VALID; 143 chsel |= S3C2412_DMAREQSEL_HW; 144 145 writel(chsel, chan->regs + S3C2412_DMA_DMAREQSEL); 146} 147 148static void s3c2412_dma_select(struct s3c2410_dma_chan *chan, 149 struct s3c24xx_dma_map *map) 150{ 151 s3c2412_dma_direction(chan, map, chan->source); 152} 153 154static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = { 155 .select = s3c2412_dma_select, 156 .direction = s3c2412_dma_direction, 157 .dcon_mask = 0, 158 .map = s3c2412_dma_mappings, 159 .map_size = ARRAY_SIZE(s3c2412_dma_mappings), 160}; 161 162static int __init s3c2412_dma_add(struct device *dev, 163 struct subsys_interface *sif) 164{ 165 s3c2410_dma_init(); 166 return s3c24xx_dma_init_map(&s3c2412_dma_sel); 167} 168 169static struct subsys_interface s3c2412_dma_interface = { 170 .name = "s3c2412_dma", 171 .subsys = &s3c2412_subsys, 172 .add_dev = s3c2412_dma_add, 173}; 174 175static int __init s3c2412_dma_init(void) 176{ 177 return subsys_interface_register(&s3c2412_dma_interface); 178} 179 180arch_initcall(s3c2412_dma_init); 181