1/* linux/arch/arm/mach-s3c2410/dma.c 2 * 3 * Copyright (c) 2006 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * 6 * S3C2410 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/cpu.h> 24#include <asm/plat-s3c24xx/dma.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 s3c2410_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[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID, 48 .channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID, 49 .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO, 50 .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO, 51 }, 52 [DMACH_SPI0] = { 53 .name = "spi0", 54 .channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID, 55 .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT, 56 .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT, 57 }, 58 [DMACH_SPI1] = { 59 .name = "spi1", 60 .channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID, 61 .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT, 62 .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT, 63 }, 64 [DMACH_UART0] = { 65 .name = "uart0", 66 .channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID, 67 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH, 68 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH, 69 }, 70 [DMACH_UART1] = { 71 .name = "uart1", 72 .channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID, 73 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH, 74 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH, 75 }, 76 [DMACH_UART2] = { 77 .name = "uart2", 78 .channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID, 79 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH, 80 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH, 81 }, 82 [DMACH_TIMER] = { 83 .name = "timer", 84 .channels[0] = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID, 85 .channels[2] = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID, 86 .channels[3] = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID, 87 }, 88 [DMACH_I2S_IN] = { 89 .name = "i2s-sdi", 90 .channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID, 91 .channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID, 92 .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO, 93 }, 94 [DMACH_I2S_OUT] = { 95 .name = "i2s-sdo", 96 .channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID, 97 .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO, 98 }, 99 [DMACH_USB_EP1] = { 100 .name = "usb-ep1", 101 .channels[0] = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID, 102 }, 103 [DMACH_USB_EP2] = { 104 .name = "usb-ep2", 105 .channels[1] = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID, 106 }, 107 [DMACH_USB_EP3] = { 108 .name = "usb-ep3", 109 .channels[2] = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID, 110 }, 111 [DMACH_USB_EP4] = { 112 .name = "usb-ep4", 113 .channels[3] =S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID, 114 }, 115}; 116 117static void s3c2410_dma_select(struct s3c2410_dma_chan *chan, 118 struct s3c24xx_dma_map *map) 119{ 120 chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID; 121} 122 123static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = { 124 .select = s3c2410_dma_select, 125 .dcon_mask = 7 << 24, 126 .map = s3c2410_dma_mappings, 127 .map_size = ARRAY_SIZE(s3c2410_dma_mappings), 128}; 129 130static struct s3c24xx_dma_order __initdata s3c2410_dma_order = { 131 .channels = { 132 [DMACH_SDI] = { 133 .list = { 134 [0] = 3 | DMA_CH_VALID, 135 [1] = 2 | DMA_CH_VALID, 136 [2] = 0 | DMA_CH_VALID, 137 }, 138 }, 139 [DMACH_I2S_IN] = { 140 .list = { 141 [0] = 1 | DMA_CH_VALID, 142 [1] = 2 | DMA_CH_VALID, 143 }, 144 }, 145 }, 146}; 147 148static int s3c2410_dma_add(struct sys_device *sysdev) 149{ 150 s3c2410_dma_init(); 151 s3c24xx_dma_order_set(&s3c2410_dma_order); 152 return s3c24xx_dma_init_map(&s3c2410_dma_sel); 153} 154 155#if defined(CONFIG_CPU_S3C2410) 156static struct sysdev_driver s3c2410_dma_driver = { 157 .add = s3c2410_dma_add, 158}; 159 160static int __init s3c2410_dma_drvinit(void) 161{ 162 return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver); 163} 164 165arch_initcall(s3c2410_dma_drvinit); 166#endif 167 168#if defined(CONFIG_CPU_S3C2442) 169/* S3C2442 DMA contains the same selection table as the S3C2410 */ 170static struct sysdev_driver s3c2442_dma_driver = { 171 .add = s3c2410_dma_add, 172}; 173 174static int __init s3c2442_dma_drvinit(void) 175{ 176 return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver); 177} 178 179arch_initcall(s3c2442_dma_drvinit); 180#endif 181