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/sysdev.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 .hw_addr.to = S3C2410_PA_SDI + S3C2410_SDIDATA, 54 .hw_addr.from = S3C2410_PA_SDI + S3C2410_SDIDATA, 55 }, 56 [DMACH_SPI0] = { 57 .name = "spi0", 58 .channels = MAP(S3C2412_DMAREQSEL_SPI0TX), 59 .channels_rx = MAP(S3C2412_DMAREQSEL_SPI0RX), 60 .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT, 61 .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT, 62 }, 63 [DMACH_SPI1] = { 64 .name = "spi1", 65 .channels = MAP(S3C2412_DMAREQSEL_SPI1TX), 66 .channels_rx = MAP(S3C2412_DMAREQSEL_SPI1RX), 67 .hw_addr.to = S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPTDAT, 68 .hw_addr.from = S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPRDAT, 69 }, 70 [DMACH_UART0] = { 71 .name = "uart0", 72 .channels = MAP(S3C2412_DMAREQSEL_UART0_0), 73 .channels_rx = MAP(S3C2412_DMAREQSEL_UART0_0), 74 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH, 75 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH, 76 }, 77 [DMACH_UART1] = { 78 .name = "uart1", 79 .channels = MAP(S3C2412_DMAREQSEL_UART1_0), 80 .channels_rx = MAP(S3C2412_DMAREQSEL_UART1_0), 81 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH, 82 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH, 83 }, 84 [DMACH_UART2] = { 85 .name = "uart2", 86 .channels = MAP(S3C2412_DMAREQSEL_UART2_0), 87 .channels_rx = MAP(S3C2412_DMAREQSEL_UART2_0), 88 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH, 89 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH, 90 }, 91 [DMACH_UART0_SRC2] = { 92 .name = "uart0", 93 .channels = MAP(S3C2412_DMAREQSEL_UART0_1), 94 .channels_rx = MAP(S3C2412_DMAREQSEL_UART0_1), 95 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH, 96 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH, 97 }, 98 [DMACH_UART1_SRC2] = { 99 .name = "uart1", 100 .channels = MAP(S3C2412_DMAREQSEL_UART1_1), 101 .channels_rx = MAP(S3C2412_DMAREQSEL_UART1_1), 102 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH, 103 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH, 104 }, 105 [DMACH_UART2_SRC2] = { 106 .name = "uart2", 107 .channels = MAP(S3C2412_DMAREQSEL_UART2_1), 108 .channels_rx = MAP(S3C2412_DMAREQSEL_UART2_1), 109 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH, 110 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH, 111 }, 112 [DMACH_TIMER] = { 113 .name = "timer", 114 .channels = MAP(S3C2412_DMAREQSEL_TIMER), 115 .channels_rx = MAP(S3C2412_DMAREQSEL_TIMER), 116 }, 117 [DMACH_I2S_IN] = { 118 .name = "i2s-sdi", 119 .channels = MAP(S3C2412_DMAREQSEL_I2SRX), 120 .channels_rx = MAP(S3C2412_DMAREQSEL_I2SRX), 121 }, 122 [DMACH_I2S_OUT] = { 123 .name = "i2s-sdo", 124 .channels = MAP(S3C2412_DMAREQSEL_I2STX), 125 .channels_rx = MAP(S3C2412_DMAREQSEL_I2STX), 126 }, 127 [DMACH_USB_EP1] = { 128 .name = "usb-ep1", 129 .channels = MAP(S3C2412_DMAREQSEL_USBEP1), 130 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP1), 131 }, 132 [DMACH_USB_EP2] = { 133 .name = "usb-ep2", 134 .channels = MAP(S3C2412_DMAREQSEL_USBEP2), 135 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP2), 136 }, 137 [DMACH_USB_EP3] = { 138 .name = "usb-ep3", 139 .channels = MAP(S3C2412_DMAREQSEL_USBEP3), 140 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP3), 141 }, 142 [DMACH_USB_EP4] = { 143 .name = "usb-ep4", 144 .channels = MAP(S3C2412_DMAREQSEL_USBEP4), 145 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP4), 146 }, 147}; 148 149static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan, 150 struct s3c24xx_dma_map *map, 151 enum s3c2410_dmasrc dir) 152{ 153 unsigned long chsel; 154 155 if (dir == S3C2410_DMASRC_HW) 156 chsel = map->channels_rx[0]; 157 else 158 chsel = map->channels[0]; 159 160 chsel &= ~DMA_CH_VALID; 161 chsel |= S3C2412_DMAREQSEL_HW; 162 163 writel(chsel, chan->regs + S3C2412_DMA_DMAREQSEL); 164} 165 166static void s3c2412_dma_select(struct s3c2410_dma_chan *chan, 167 struct s3c24xx_dma_map *map) 168{ 169 s3c2412_dma_direction(chan, map, chan->source); 170} 171 172static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = { 173 .select = s3c2412_dma_select, 174 .direction = s3c2412_dma_direction, 175 .dcon_mask = 0, 176 .map = s3c2412_dma_mappings, 177 .map_size = ARRAY_SIZE(s3c2412_dma_mappings), 178}; 179 180static int __init s3c2412_dma_add(struct sys_device *sysdev) 181{ 182 s3c2410_dma_init(); 183 return s3c24xx_dma_init_map(&s3c2412_dma_sel); 184} 185 186static struct sysdev_driver s3c2412_dma_driver = { 187 .add = s3c2412_dma_add, 188}; 189 190static int __init s3c2412_dma_init(void) 191{ 192 return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_dma_driver); 193} 194 195arch_initcall(s3c2412_dma_init); 196