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