1/* linux/arch/arm/mach-s3c2440/dma.c 2 * 3 * Copyright (c) 2006 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * 6 * S3C2440 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 20#include <asm/dma.h> 21#include <asm/arch/dma.h> 22 23#include <asm/plat-s3c24xx/dma.h> 24#include <asm/plat-s3c24xx/cpu.h> 25 26#include <asm/arch/regs-serial.h> 27#include <asm/arch/regs-gpio.h> 28#include <asm/arch/regs-ac97.h> 29#include <asm/arch/regs-mem.h> 30#include <asm/arch/regs-lcd.h> 31#include <asm/arch/regs-sdi.h> 32#include <asm/arch/regs-iis.h> 33#include <asm/arch/regs-spi.h> 34 35static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = { 36 [DMACH_XD0] = { 37 .name = "xdreq0", 38 .channels[0] = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID, 39 }, 40 [DMACH_XD1] = { 41 .name = "xdreq1", 42 .channels[1] = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID, 43 }, 44 [DMACH_SDI] = { 45 .name = "sdi", 46 .channels[0] = S3C2410_DCON_CH0_SDI | DMA_CH_VALID, 47 .channels[1] = S3C2440_DCON_CH1_SDI | DMA_CH_VALID, 48 .channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID, 49 .channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID, 50 .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO, 51 .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO, 52 }, 53 [DMACH_SPI0] = { 54 .name = "spi0", 55 .channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID, 56 .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT, 57 .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT, 58 }, 59 [DMACH_SPI1] = { 60 .name = "spi1", 61 .channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID, 62 .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT, 63 .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT, 64 }, 65 [DMACH_UART0] = { 66 .name = "uart0", 67 .channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID, 68 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH, 69 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH, 70 }, 71 [DMACH_UART1] = { 72 .name = "uart1", 73 .channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID, 74 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH, 75 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH, 76 }, 77 [DMACH_UART2] = { 78 .name = "uart2", 79 .channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID, 80 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH, 81 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH, 82 }, 83 [DMACH_TIMER] = { 84 .name = "timer", 85 .channels[0] = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID, 86 .channels[2] = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID, 87 .channels[3] = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID, 88 }, 89 [DMACH_I2S_IN] = { 90 .name = "i2s-sdi", 91 .channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID, 92 .channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID, 93 .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO, 94 }, 95 [DMACH_I2S_OUT] = { 96 .name = "i2s-sdo", 97 .channels[0] = S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID, 98 .channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID, 99 .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO, 100 }, 101 [DMACH_PCM_IN] = { 102 .name = "pcm-in", 103 .channels[0] = S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID, 104 .channels[2] = S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID, 105 .hw_addr.from = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA, 106 }, 107 [DMACH_PCM_OUT] = { 108 .name = "pcm-out", 109 .channels[1] = S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID, 110 .channels[3] = S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID, 111 .hw_addr.to = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA, 112 }, 113 [DMACH_MIC_IN] = { 114 .name = "mic-in", 115 .channels[2] = S3C2440_DCON_CH2_MICIN | DMA_CH_VALID, 116 .channels[3] = S3C2440_DCON_CH3_MICIN | DMA_CH_VALID, 117 .hw_addr.from = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA, 118 }, 119 [DMACH_USB_EP1] = { 120 .name = "usb-ep1", 121 .channels[0] = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID, 122 }, 123 [DMACH_USB_EP2] = { 124 .name = "usb-ep2", 125 .channels[1] = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID, 126 }, 127 [DMACH_USB_EP3] = { 128 .name = "usb-ep3", 129 .channels[2] = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID, 130 }, 131 [DMACH_USB_EP4] = { 132 .name = "usb-ep4", 133 .channels[3] = S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID, 134 }, 135}; 136 137static void s3c2440_dma_select(struct s3c2410_dma_chan *chan, 138 struct s3c24xx_dma_map *map) 139{ 140 chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID; 141} 142 143static struct s3c24xx_dma_selection __initdata s3c2440_dma_sel = { 144 .select = s3c2440_dma_select, 145 .dcon_mask = 7 << 24, 146 .map = s3c2440_dma_mappings, 147 .map_size = ARRAY_SIZE(s3c2440_dma_mappings), 148}; 149 150static struct s3c24xx_dma_order __initdata s3c2440_dma_order = { 151 .channels = { 152 [DMACH_SDI] = { 153 .list = { 154 [0] = 3 | DMA_CH_VALID, 155 [1] = 2 | DMA_CH_VALID, 156 [2] = 1 | DMA_CH_VALID, 157 [3] = 0 | DMA_CH_VALID, 158 }, 159 }, 160 [DMACH_I2S_IN] = { 161 .list = { 162 [0] = 1 | DMA_CH_VALID, 163 [1] = 2 | DMA_CH_VALID, 164 }, 165 }, 166 [DMACH_I2S_OUT] = { 167 .list = { 168 [0] = 2 | DMA_CH_VALID, 169 [1] = 1 | DMA_CH_VALID, 170 }, 171 }, 172 [DMACH_PCM_IN] = { 173 .list = { 174 [0] = 2 | DMA_CH_VALID, 175 [1] = 1 | DMA_CH_VALID, 176 }, 177 }, 178 [DMACH_PCM_OUT] = { 179 .list = { 180 [0] = 1 | DMA_CH_VALID, 181 [1] = 3 | DMA_CH_VALID, 182 }, 183 }, 184 [DMACH_MIC_IN] = { 185 .list = { 186 [0] = 3 | DMA_CH_VALID, 187 [1] = 2 | DMA_CH_VALID, 188 }, 189 }, 190 }, 191}; 192 193static int s3c2440_dma_add(struct sys_device *sysdev) 194{ 195 s3c2410_dma_init(); 196 s3c24xx_dma_order_set(&s3c2440_dma_order); 197 return s3c24xx_dma_init_map(&s3c2440_dma_sel); 198} 199 200static struct sysdev_driver s3c2440_dma_driver = { 201 .add = s3c2440_dma_add, 202}; 203 204static int __init s3c2440_dma_init(void) 205{ 206 return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_dma_driver); 207} 208 209arch_initcall(s3c2440_dma_init); 210