aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c24xx
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2015-01-23 23:09:54 -0500
committerKukjin Kim <kgene@kernel.org>2015-01-23 23:09:54 -0500
commitd50b9e2e788dce9b120b5ac1140f0cdd1bf905eb (patch)
treeb34a10958fc998b0718f720289d3e40049584b58 /arch/arm/mach-s3c24xx
parent32b0aa9aaeb4a493135ea6368a614aa89c3c5488 (diff)
ARM: SAMSUNG: remove unused DMA infrastructure
Everything uses dmaengine now, so there is no reason to keep this around any longer. Thanks to everyone who was involved in moving the users over to use the dmaengine APIs. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Heiko Stuebner <heiko@sntech.de> Acked-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Kukjin Kim <kgene@kernel.org>
Diffstat (limited to 'arch/arm/mach-s3c24xx')
-rw-r--r--arch/arm/mach-s3c24xx/Kconfig42
-rw-r--r--arch/arm/mach-s3c24xx/Makefile7
-rw-r--r--arch/arm/mach-s3c24xx/dma-s3c2410.c182
-rw-r--r--arch/arm/mach-s3c24xx/dma-s3c2412.c150
-rw-r--r--arch/arm/mach-s3c24xx/dma-s3c2440.c193
-rw-r--r--arch/arm/mach-s3c24xx/dma-s3c2443.c179
-rw-r--r--arch/arm/mach-s3c24xx/dma.c1465
-rw-r--r--arch/arm/mach-s3c24xx/include/mach/dma.h159
8 files changed, 0 insertions, 2377 deletions
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig
index 9eb22297cbe1..79c49ff77f6e 100644
--- a/arch/arm/mach-s3c24xx/Kconfig
+++ b/arch/arm/mach-s3c24xx/Kconfig
@@ -29,7 +29,6 @@ config CPU_S3C2410
29 default y 29 default y
30 select CPU_ARM920T 30 select CPU_ARM920T
31 select S3C2410_COMMON_CLK 31 select S3C2410_COMMON_CLK
32 select S3C2410_DMA if S3C24XX_DMA
33 select ARM_S3C2410_CPUFREQ if ARM_S3C24XX_CPUFREQ 32 select ARM_S3C2410_CPUFREQ if ARM_S3C24XX_CPUFREQ
34 select S3C2410_PM if PM 33 select S3C2410_PM if PM
35 help 34 help
@@ -40,7 +39,6 @@ config CPU_S3C2412
40 bool "SAMSUNG S3C2412" 39 bool "SAMSUNG S3C2412"
41 select CPU_ARM926T 40 select CPU_ARM926T
42 select S3C2412_COMMON_CLK 41 select S3C2412_COMMON_CLK
43 select S3C2412_DMA if S3C24XX_DMA
44 select S3C2412_PM if PM 42 select S3C2412_PM if PM
45 help 43 help
46 Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line 44 Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
@@ -50,7 +48,6 @@ config CPU_S3C2416
50 select CPU_ARM926T 48 select CPU_ARM926T
51 select S3C2416_PM if PM 49 select S3C2416_PM if PM
52 select S3C2443_COMMON_CLK 50 select S3C2443_COMMON_CLK
53 select S3C2443_DMA if S3C24XX_DMA
54 help 51 help
55 Support for the S3C2416 SoC from the S3C24XX line 52 Support for the S3C2416 SoC from the S3C24XX line
56 53
@@ -59,7 +56,6 @@ config CPU_S3C2440
59 select CPU_ARM920T 56 select CPU_ARM920T
60 select S3C2410_COMMON_CLK 57 select S3C2410_COMMON_CLK
61 select S3C2410_PM if PM 58 select S3C2410_PM if PM
62 select S3C2440_DMA if S3C24XX_DMA
63 help 59 help
64 Support for S3C2440 Samsung Mobile CPU based systems. 60 Support for S3C2440 Samsung Mobile CPU based systems.
65 61
@@ -67,7 +63,6 @@ config CPU_S3C2442
67 bool "SAMSUNG S3C2442" 63 bool "SAMSUNG S3C2442"
68 select CPU_ARM920T 64 select CPU_ARM920T
69 select S3C2410_COMMON_CLK 65 select S3C2410_COMMON_CLK
70 select S3C2410_DMA if S3C24XX_DMA
71 select S3C2410_PM if PM 66 select S3C2410_PM if PM
72 help 67 help
73 Support for S3C2442 Samsung Mobile CPU based systems. 68 Support for S3C2442 Samsung Mobile CPU based systems.
@@ -80,7 +75,6 @@ config CPU_S3C2443
80 bool "SAMSUNG S3C2443" 75 bool "SAMSUNG S3C2443"
81 select CPU_ARM920T 76 select CPU_ARM920T
82 select S3C2443_COMMON_CLK 77 select S3C2443_COMMON_CLK
83 select S3C2443_DMA if S3C24XX_DMA
84 help 78 help
85 Support for the S3C2443 SoC from the S3C24XX line 79 Support for the S3C2443 SoC from the S3C24XX line
86 80
@@ -114,27 +108,6 @@ config S3C24XX_SETUP_TS
114 help 108 help
115 Compile in platform device definition for Samsung TouchScreen. 109 Compile in platform device definition for Samsung TouchScreen.
116 110
117config S3C24XX_DMA
118 bool "S3C2410 DMA support (deprecated)"
119 select S3C_DMA
120 help
121 S3C2410 DMA support. This is needed for drivers like sound which
122 use the S3C2410's DMA system to move data to and from the
123 peripheral blocks.
124
125config S3C2410_DMA_DEBUG
126 bool "S3C2410 DMA support debug"
127 depends on S3C2410_DMA
128 help
129 Enable debugging output for the DMA code. This option sends info
130 to the kernel log, at priority KERN_DEBUG.
131
132config S3C2410_DMA
133 bool
134 depends on S3C24XX_DMA && (CPU_S3C2410 || CPU_S3C2442)
135 help
136 DMA device selection for S3C2410 and compatible CPUs
137
138config S3C2410_PM 111config S3C2410_PM
139 bool 112 bool
140 help 113 help
@@ -325,11 +298,6 @@ config CPU_S3C2412_ONLY
325 !CPU_S3C2442 && !CPU_S3C2443 298 !CPU_S3C2442 && !CPU_S3C2443
326 default y 299 default y
327 300
328config S3C2412_DMA
329 bool
330 help
331 Internal config node for S3C2412 DMA support
332
333config S3C2412_PM 301config S3C2412_PM
334 bool 302 bool
335 select S3C2412_PM_SLEEP 303 select S3C2412_PM_SLEEP
@@ -438,11 +406,6 @@ endif # CPU_S3C2416
438 406
439if CPU_S3C2440 407if CPU_S3C2440
440 408
441config S3C2440_DMA
442 bool
443 help
444 Support for S3C2440 specific DMA code5A
445
446config S3C2440_XTAL_12000000 409config S3C2440_XTAL_12000000
447 bool 410 bool
448 help 411 help
@@ -601,11 +564,6 @@ endif # CPU_S3C2442
601 564
602if CPU_S3C2443 || CPU_S3C2416 565if CPU_S3C2443 || CPU_S3C2416
603 566
604config S3C2443_DMA
605 bool
606 help
607 Internal config node for S3C2443 DMA support
608
609config S3C2443_SETUP_SPI 567config S3C2443_SETUP_SPI
610 bool 568 bool
611 help 569 help
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile
index b92071638733..b40a22fe082a 100644
--- a/arch/arm/mach-s3c24xx/Makefile
+++ b/arch/arm/mach-s3c24xx/Makefile
@@ -12,12 +12,10 @@
12obj-y += common.o 12obj-y += common.o
13 13
14obj-$(CONFIG_CPU_S3C2410) += s3c2410.o 14obj-$(CONFIG_CPU_S3C2410) += s3c2410.o
15obj-$(CONFIG_S3C2410_DMA) += dma-s3c2410.o
16obj-$(CONFIG_S3C2410_PLL) += pll-s3c2410.o 15obj-$(CONFIG_S3C2410_PLL) += pll-s3c2410.o
17obj-$(CONFIG_S3C2410_PM) += pm-s3c2410.o sleep-s3c2410.o 16obj-$(CONFIG_S3C2410_PM) += pm-s3c2410.o sleep-s3c2410.o
18 17
19obj-$(CONFIG_CPU_S3C2412) += s3c2412.o 18obj-$(CONFIG_CPU_S3C2412) += s3c2412.o
20obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o
21obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o 19obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o
22obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o 20obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o
23 21
@@ -27,7 +25,6 @@ obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o
27obj-$(CONFIG_CPU_S3C2440) += s3c2440.o 25obj-$(CONFIG_CPU_S3C2440) += s3c2440.o
28obj-$(CONFIG_CPU_S3C2442) += s3c2442.o 26obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
29obj-$(CONFIG_CPU_S3C244X) += s3c244x.o 27obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
30obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o
31obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o 28obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o
32obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o 29obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o
33 30
@@ -39,15 +36,11 @@ obj-$(CONFIG_PM) += pm.o irq-pm.o sleep.o
39 36
40# common code 37# common code
41 38
42obj-$(CONFIG_S3C24XX_DMA) += dma.o
43
44obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o 39obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o
45 40
46obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o 41obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o
47obj-$(CONFIG_S3C2412_IOTIMING) += iotiming-s3c2412.o 42obj-$(CONFIG_S3C2412_IOTIMING) += iotiming-s3c2412.o
48 43
49obj-$(CONFIG_S3C2443_DMA) += dma-s3c2443.o
50
51# 44#
52# machine support 45# machine support
53# following is ordered alphabetically by option text. 46# following is ordered alphabetically by option text.
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2410.c b/arch/arm/mach-s3c24xx/dma-s3c2410.c
deleted file mode 100644
index 09aa12da1789..000000000000
--- a/arch/arm/mach-s3c24xx/dma-s3c2410.c
+++ /dev/null
@@ -1,182 +0,0 @@
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/device.h>
18#include <linux/serial_core.h>
19#include <linux/serial_s3c.h>
20
21#include <mach/map.h>
22#include <mach/dma.h>
23
24#include <plat/cpu.h>
25#include <plat/dma-s3c24xx.h>
26
27#include <mach/regs-gpio.h>
28#include <plat/regs-dma.h>
29#include <mach/regs-lcd.h>
30#include <plat/regs-spi.h>
31
32static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
33 [DMACH_XD0] = {
34 .name = "xdreq0",
35 .channels[0] = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
36 },
37 [DMACH_XD1] = {
38 .name = "xdreq1",
39 .channels[1] = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
40 },
41 [DMACH_SDI] = {
42 .name = "sdi",
43 .channels[0] = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
44 .channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
45 .channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
46 },
47 [DMACH_SPI0] = {
48 .name = "spi0",
49 .channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
50 },
51 [DMACH_SPI1] = {
52 .name = "spi1",
53 .channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
54 },
55 [DMACH_UART0] = {
56 .name = "uart0",
57 .channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
58 },
59 [DMACH_UART1] = {
60 .name = "uart1",
61 .channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
62 },
63 [DMACH_UART2] = {
64 .name = "uart2",
65 .channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
66 },
67 [DMACH_TIMER] = {
68 .name = "timer",
69 .channels[0] = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
70 .channels[2] = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
71 .channels[3] = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
72 },
73 [DMACH_I2S_IN] = {
74 .name = "i2s-sdi",
75 .channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
76 .channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
77 },
78 [DMACH_I2S_OUT] = {
79 .name = "i2s-sdo",
80 .channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
81 },
82 [DMACH_USB_EP1] = {
83 .name = "usb-ep1",
84 .channels[0] = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
85 },
86 [DMACH_USB_EP2] = {
87 .name = "usb-ep2",
88 .channels[1] = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
89 },
90 [DMACH_USB_EP3] = {
91 .name = "usb-ep3",
92 .channels[2] = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
93 },
94 [DMACH_USB_EP4] = {
95 .name = "usb-ep4",
96 .channels[3] =S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
97 },
98};
99
100static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
101 struct s3c24xx_dma_map *map)
102{
103 chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
104}
105
106static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
107 .select = s3c2410_dma_select,
108 .dcon_mask = 7 << 24,
109 .map = s3c2410_dma_mappings,
110 .map_size = ARRAY_SIZE(s3c2410_dma_mappings),
111};
112
113static struct s3c24xx_dma_order __initdata s3c2410_dma_order = {
114 .channels = {
115 [DMACH_SDI] = {
116 .list = {
117 [0] = 3 | DMA_CH_VALID,
118 [1] = 2 | DMA_CH_VALID,
119 [2] = 0 | DMA_CH_VALID,
120 },
121 },
122 [DMACH_I2S_IN] = {
123 .list = {
124 [0] = 1 | DMA_CH_VALID,
125 [1] = 2 | DMA_CH_VALID,
126 },
127 },
128 },
129};
130
131static int __init s3c2410_dma_add(struct device *dev,
132 struct subsys_interface *sif)
133{
134 s3c2410_dma_init();
135 s3c24xx_dma_order_set(&s3c2410_dma_order);
136 return s3c24xx_dma_init_map(&s3c2410_dma_sel);
137}
138
139#if defined(CONFIG_CPU_S3C2410)
140static struct subsys_interface s3c2410_dma_interface = {
141 .name = "s3c2410_dma",
142 .subsys = &s3c2410_subsys,
143 .add_dev = s3c2410_dma_add,
144};
145
146static int __init s3c2410_dma_drvinit(void)
147{
148 return subsys_interface_register(&s3c2410_dma_interface);
149}
150
151arch_initcall(s3c2410_dma_drvinit);
152
153static struct subsys_interface s3c2410a_dma_interface = {
154 .name = "s3c2410a_dma",
155 .subsys = &s3c2410a_subsys,
156 .add_dev = s3c2410_dma_add,
157};
158
159static int __init s3c2410a_dma_drvinit(void)
160{
161 return subsys_interface_register(&s3c2410a_dma_interface);
162}
163
164arch_initcall(s3c2410a_dma_drvinit);
165#endif
166
167#if defined(CONFIG_CPU_S3C2442)
168/* S3C2442 DMA contains the same selection table as the S3C2410 */
169static struct subsys_interface s3c2442_dma_interface = {
170 .name = "s3c2442_dma",
171 .subsys = &s3c2442_subsys,
172 .add_dev = s3c2410_dma_add,
173};
174
175static int __init s3c2442_dma_drvinit(void)
176{
177 return subsys_interface_register(&s3c2442_dma_interface);
178}
179
180arch_initcall(s3c2442_dma_drvinit);
181#endif
182
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2412.c b/arch/arm/mach-s3c24xx/dma-s3c2412.c
deleted file mode 100644
index 0c0106d1a4d1..000000000000
--- a/arch/arm/mach-s3c24xx/dma-s3c2412.c
+++ /dev/null
@@ -1,150 +0,0 @@
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/serial_s3c.h>
20#include <linux/io.h>
21
22#include <mach/dma.h>
23
24#include <plat/dma-s3c24xx.h>
25#include <plat/cpu.h>
26
27#include <mach/regs-gpio.h>
28#include <plat/regs-dma.h>
29#include <mach/regs-lcd.h>
30#include <plat/regs-spi.h>
31
32#define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
33
34static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
35 [DMACH_XD0] = {
36 .name = "xdreq0",
37 .channels = MAP(S3C2412_DMAREQSEL_XDREQ0),
38 },
39 [DMACH_XD1] = {
40 .name = "xdreq1",
41 .channels = MAP(S3C2412_DMAREQSEL_XDREQ1),
42 },
43 [DMACH_SDI] = {
44 .name = "sdi",
45 .channels = MAP(S3C2412_DMAREQSEL_SDI),
46 },
47 [DMACH_SPI0_RX] = {
48 .name = "spi0-rx",
49 .channels = MAP(S3C2412_DMAREQSEL_SPI0RX),
50 },
51 [DMACH_SPI0_TX] = {
52 .name = "spi0-tx",
53 .channels = MAP(S3C2412_DMAREQSEL_SPI0TX),
54 },
55 [DMACH_SPI1_RX] = {
56 .name = "spi1-rx",
57 .channels = MAP(S3C2412_DMAREQSEL_SPI1RX),
58 },
59 [DMACH_SPI1_TX] = {
60 .name = "spi1-tx",
61 .channels = MAP(S3C2412_DMAREQSEL_SPI1TX),
62 },
63 [DMACH_UART0] = {
64 .name = "uart0",
65 .channels = MAP(S3C2412_DMAREQSEL_UART0_0),
66 },
67 [DMACH_UART1] = {
68 .name = "uart1",
69 .channels = MAP(S3C2412_DMAREQSEL_UART1_0),
70 },
71 [DMACH_UART2] = {
72 .name = "uart2",
73 .channels = MAP(S3C2412_DMAREQSEL_UART2_0),
74 },
75 [DMACH_UART0_SRC2] = {
76 .name = "uart0",
77 .channels = MAP(S3C2412_DMAREQSEL_UART0_1),
78 },
79 [DMACH_UART1_SRC2] = {
80 .name = "uart1",
81 .channels = MAP(S3C2412_DMAREQSEL_UART1_1),
82 },
83 [DMACH_UART2_SRC2] = {
84 .name = "uart2",
85 .channels = MAP(S3C2412_DMAREQSEL_UART2_1),
86 },
87 [DMACH_TIMER] = {
88 .name = "timer",
89 .channels = MAP(S3C2412_DMAREQSEL_TIMER),
90 },
91 [DMACH_I2S_IN] = {
92 .name = "i2s-sdi",
93 .channels = MAP(S3C2412_DMAREQSEL_I2SRX),
94 },
95 [DMACH_I2S_OUT] = {
96 .name = "i2s-sdo",
97 .channels = MAP(S3C2412_DMAREQSEL_I2STX),
98 },
99 [DMACH_USB_EP1] = {
100 .name = "usb-ep1",
101 .channels = MAP(S3C2412_DMAREQSEL_USBEP1),
102 },
103 [DMACH_USB_EP2] = {
104 .name = "usb-ep2",
105 .channels = MAP(S3C2412_DMAREQSEL_USBEP2),
106 },
107 [DMACH_USB_EP3] = {
108 .name = "usb-ep3",
109 .channels = MAP(S3C2412_DMAREQSEL_USBEP3),
110 },
111 [DMACH_USB_EP4] = {
112 .name = "usb-ep4",
113 .channels = MAP(S3C2412_DMAREQSEL_USBEP4),
114 },
115};
116
117static void s3c2412_dma_select(struct s3c2410_dma_chan *chan,
118 struct s3c24xx_dma_map *map)
119{
120 unsigned long chsel = map->channels[0] & (~DMA_CH_VALID);
121 writel(chsel | S3C2412_DMAREQSEL_HW,
122 chan->regs + S3C2412_DMA_DMAREQSEL);
123}
124
125static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
126 .select = s3c2412_dma_select,
127 .dcon_mask = 0,
128 .map = s3c2412_dma_mappings,
129 .map_size = ARRAY_SIZE(s3c2412_dma_mappings),
130};
131
132static int __init s3c2412_dma_add(struct device *dev,
133 struct subsys_interface *sif)
134{
135 s3c2410_dma_init();
136 return s3c24xx_dma_init_map(&s3c2412_dma_sel);
137}
138
139static struct subsys_interface s3c2412_dma_interface = {
140 .name = "s3c2412_dma",
141 .subsys = &s3c2412_subsys,
142 .add_dev = s3c2412_dma_add,
143};
144
145static int __init s3c2412_dma_init(void)
146{
147 return subsys_interface_register(&s3c2412_dma_interface);
148}
149
150arch_initcall(s3c2412_dma_init);
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2440.c b/arch/arm/mach-s3c24xx/dma-s3c2440.c
deleted file mode 100644
index 2f8e8a3017df..000000000000
--- a/arch/arm/mach-s3c24xx/dma-s3c2440.c
+++ /dev/null
@@ -1,193 +0,0 @@
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/device.h>
18#include <linux/serial_core.h>
19#include <linux/serial_s3c.h>
20
21#include <mach/map.h>
22#include <mach/dma.h>
23
24#include <plat/dma-s3c24xx.h>
25#include <plat/cpu.h>
26
27#include <mach/regs-gpio.h>
28#include <plat/regs-dma.h>
29#include <mach/regs-lcd.h>
30#include <plat/regs-spi.h>
31
32static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
33 [DMACH_XD0] = {
34 .name = "xdreq0",
35 .channels[0] = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
36 },
37 [DMACH_XD1] = {
38 .name = "xdreq1",
39 .channels[1] = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
40 },
41 [DMACH_SDI] = {
42 .name = "sdi",
43 .channels[0] = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
44 .channels[1] = S3C2440_DCON_CH1_SDI | DMA_CH_VALID,
45 .channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
46 .channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
47 },
48 [DMACH_SPI0] = {
49 .name = "spi0",
50 .channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
51 },
52 [DMACH_SPI1] = {
53 .name = "spi1",
54 .channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
55 },
56 [DMACH_UART0] = {
57 .name = "uart0",
58 .channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
59 },
60 [DMACH_UART1] = {
61 .name = "uart1",
62 .channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
63 },
64 [DMACH_UART2] = {
65 .name = "uart2",
66 .channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
67 },
68 [DMACH_TIMER] = {
69 .name = "timer",
70 .channels[0] = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
71 .channels[2] = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
72 .channels[3] = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
73 },
74 [DMACH_I2S_IN] = {
75 .name = "i2s-sdi",
76 .channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
77 .channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
78 },
79 [DMACH_I2S_OUT] = {
80 .name = "i2s-sdo",
81 .channels[0] = S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID,
82 .channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
83 },
84 [DMACH_PCM_IN] = {
85 .name = "pcm-in",
86 .channels[0] = S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID,
87 .channels[2] = S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID,
88 },
89 [DMACH_PCM_OUT] = {
90 .name = "pcm-out",
91 .channels[1] = S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID,
92 .channels[3] = S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID,
93 },
94 [DMACH_MIC_IN] = {
95 .name = "mic-in",
96 .channels[2] = S3C2440_DCON_CH2_MICIN | DMA_CH_VALID,
97 .channels[3] = S3C2440_DCON_CH3_MICIN | DMA_CH_VALID,
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 s3c2440_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 s3c2440_dma_sel = {
124 .select = s3c2440_dma_select,
125 .dcon_mask = 7 << 24,
126 .map = s3c2440_dma_mappings,
127 .map_size = ARRAY_SIZE(s3c2440_dma_mappings),
128};
129
130static struct s3c24xx_dma_order __initdata s3c2440_dma_order = {
131 .channels = {
132 [DMACH_SDI] = {
133 .list = {
134 [0] = 3 | DMA_CH_VALID,
135 [1] = 2 | DMA_CH_VALID,
136 [2] = 1 | DMA_CH_VALID,
137 [3] = 0 | DMA_CH_VALID,
138 },
139 },
140 [DMACH_I2S_IN] = {
141 .list = {
142 [0] = 1 | DMA_CH_VALID,
143 [1] = 2 | DMA_CH_VALID,
144 },
145 },
146 [DMACH_I2S_OUT] = {
147 .list = {
148 [0] = 2 | DMA_CH_VALID,
149 [1] = 1 | DMA_CH_VALID,
150 },
151 },
152 [DMACH_PCM_IN] = {
153 .list = {
154 [0] = 2 | DMA_CH_VALID,
155 [1] = 1 | DMA_CH_VALID,
156 },
157 },
158 [DMACH_PCM_OUT] = {
159 .list = {
160 [0] = 1 | DMA_CH_VALID,
161 [1] = 3 | DMA_CH_VALID,
162 },
163 },
164 [DMACH_MIC_IN] = {
165 .list = {
166 [0] = 3 | DMA_CH_VALID,
167 [1] = 2 | DMA_CH_VALID,
168 },
169 },
170 },
171};
172
173static int __init s3c2440_dma_add(struct device *dev,
174 struct subsys_interface *sif)
175{
176 s3c2410_dma_init();
177 s3c24xx_dma_order_set(&s3c2440_dma_order);
178 return s3c24xx_dma_init_map(&s3c2440_dma_sel);
179}
180
181static struct subsys_interface s3c2440_dma_interface = {
182 .name = "s3c2440_dma",
183 .subsys = &s3c2440_subsys,
184 .add_dev = s3c2440_dma_add,
185};
186
187static int __init s3c2440_dma_init(void)
188{
189 return subsys_interface_register(&s3c2440_dma_interface);
190}
191
192arch_initcall(s3c2440_dma_init);
193
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2443.c b/arch/arm/mach-s3c24xx/dma-s3c2443.c
deleted file mode 100644
index f4096ec0700a..000000000000
--- a/arch/arm/mach-s3c24xx/dma-s3c2443.c
+++ /dev/null
@@ -1,179 +0,0 @@
1/* linux/arch/arm/mach-s3c2443/dma.c
2 *
3 * Copyright (c) 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2443 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/serial_s3c.h>
20#include <linux/io.h>
21
22#include <mach/dma.h>
23
24#include <plat/dma-s3c24xx.h>
25#include <plat/cpu.h>
26
27#include <mach/regs-gpio.h>
28#include <plat/regs-dma.h>
29#include <mach/regs-lcd.h>
30#include <plat/regs-spi.h>
31
32#define MAP(x) { \
33 [0] = (x) | DMA_CH_VALID, \
34 [1] = (x) | DMA_CH_VALID, \
35 [2] = (x) | DMA_CH_VALID, \
36 [3] = (x) | DMA_CH_VALID, \
37 [4] = (x) | DMA_CH_VALID, \
38 [5] = (x) | DMA_CH_VALID, \
39 }
40
41static struct s3c24xx_dma_map __initdata s3c2443_dma_mappings[] = {
42 [DMACH_XD0] = {
43 .name = "xdreq0",
44 .channels = MAP(S3C2443_DMAREQSEL_XDREQ0),
45 },
46 [DMACH_XD1] = {
47 .name = "xdreq1",
48 .channels = MAP(S3C2443_DMAREQSEL_XDREQ1),
49 },
50 [DMACH_SDI] = { /* only on S3C2443 */
51 .name = "sdi",
52 .channels = MAP(S3C2443_DMAREQSEL_SDI),
53 },
54 [DMACH_SPI0_RX] = {
55 .name = "spi0-rx",
56 .channels = MAP(S3C2443_DMAREQSEL_SPI0RX),
57 },
58 [DMACH_SPI0_TX] = {
59 .name = "spi0-tx",
60 .channels = MAP(S3C2443_DMAREQSEL_SPI0TX),
61 },
62 [DMACH_SPI1_RX] = { /* only on S3C2443/S3C2450 */
63 .name = "spi1-rx",
64 .channels = MAP(S3C2443_DMAREQSEL_SPI1RX),
65 },
66 [DMACH_SPI1_TX] = { /* only on S3C2443/S3C2450 */
67 .name = "spi1-tx",
68 .channels = MAP(S3C2443_DMAREQSEL_SPI1TX),
69 },
70 [DMACH_UART0] = {
71 .name = "uart0",
72 .channels = MAP(S3C2443_DMAREQSEL_UART0_0),
73 },
74 [DMACH_UART1] = {
75 .name = "uart1",
76 .channels = MAP(S3C2443_DMAREQSEL_UART1_0),
77 },
78 [DMACH_UART2] = {
79 .name = "uart2",
80 .channels = MAP(S3C2443_DMAREQSEL_UART2_0),
81 },
82 [DMACH_UART3] = {
83 .name = "uart3",
84 .channels = MAP(S3C2443_DMAREQSEL_UART3_0),
85 },
86 [DMACH_UART0_SRC2] = {
87 .name = "uart0",
88 .channels = MAP(S3C2443_DMAREQSEL_UART0_1),
89 },
90 [DMACH_UART1_SRC2] = {
91 .name = "uart1",
92 .channels = MAP(S3C2443_DMAREQSEL_UART1_1),
93 },
94 [DMACH_UART2_SRC2] = {
95 .name = "uart2",
96 .channels = MAP(S3C2443_DMAREQSEL_UART2_1),
97 },
98 [DMACH_UART3_SRC2] = {
99 .name = "uart3",
100 .channels = MAP(S3C2443_DMAREQSEL_UART3_1),
101 },
102 [DMACH_TIMER] = {
103 .name = "timer",
104 .channels = MAP(S3C2443_DMAREQSEL_TIMER),
105 },
106 [DMACH_I2S_IN] = {
107 .name = "i2s-sdi",
108 .channels = MAP(S3C2443_DMAREQSEL_I2SRX),
109 },
110 [DMACH_I2S_OUT] = {
111 .name = "i2s-sdo",
112 .channels = MAP(S3C2443_DMAREQSEL_I2STX),
113 },
114 [DMACH_PCM_IN] = {
115 .name = "pcm-in",
116 .channels = MAP(S3C2443_DMAREQSEL_PCMIN),
117 },
118 [DMACH_PCM_OUT] = {
119 .name = "pcm-out",
120 .channels = MAP(S3C2443_DMAREQSEL_PCMOUT),
121 },
122 [DMACH_MIC_IN] = {
123 .name = "mic-in",
124 .channels = MAP(S3C2443_DMAREQSEL_MICIN),
125 },
126};
127
128static void s3c2443_dma_select(struct s3c2410_dma_chan *chan,
129 struct s3c24xx_dma_map *map)
130{
131 unsigned long chsel = map->channels[0] & (~DMA_CH_VALID);
132 writel(chsel | S3C2443_DMAREQSEL_HW,
133 chan->regs + S3C2443_DMA_DMAREQSEL);
134}
135
136static struct s3c24xx_dma_selection __initdata s3c2443_dma_sel = {
137 .select = s3c2443_dma_select,
138 .dcon_mask = 0,
139 .map = s3c2443_dma_mappings,
140 .map_size = ARRAY_SIZE(s3c2443_dma_mappings),
141};
142
143static int __init s3c2443_dma_add(struct device *dev,
144 struct subsys_interface *sif)
145{
146 s3c24xx_dma_init(6, IRQ_S3C2443_DMA0, 0x100);
147 return s3c24xx_dma_init_map(&s3c2443_dma_sel);
148}
149
150#ifdef CONFIG_CPU_S3C2416
151/* S3C2416 DMA contains the same selection table as the S3C2443 */
152static struct subsys_interface s3c2416_dma_interface = {
153 .name = "s3c2416_dma",
154 .subsys = &s3c2416_subsys,
155 .add_dev = s3c2443_dma_add,
156};
157
158static int __init s3c2416_dma_init(void)
159{
160 return subsys_interface_register(&s3c2416_dma_interface);
161}
162
163arch_initcall(s3c2416_dma_init);
164#endif
165
166#ifdef CONFIG_CPU_S3C2443
167static struct subsys_interface s3c2443_dma_interface = {
168 .name = "s3c2443_dma",
169 .subsys = &s3c2443_subsys,
170 .add_dev = s3c2443_dma_add,
171};
172
173static int __init s3c2443_dma_init(void)
174{
175 return subsys_interface_register(&s3c2443_dma_interface);
176}
177
178arch_initcall(s3c2443_dma_init);
179#endif
diff --git a/arch/arm/mach-s3c24xx/dma.c b/arch/arm/mach-s3c24xx/dma.c
deleted file mode 100644
index a8dafc174fe3..000000000000
--- a/arch/arm/mach-s3c24xx/dma.c
+++ /dev/null
@@ -1,1465 +0,0 @@
1/*
2 * Copyright 2003-2006 Simtec Electronics
3 * Ben Dooks <ben@simtec.co.uk>
4 *
5 * S3C2410 DMA core
6 *
7 * http://armlinux.simtec.co.uk/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14
15#ifdef CONFIG_S3C2410_DMA_DEBUG
16#define DEBUG
17#endif
18
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/sched.h>
22#include <linux/spinlock.h>
23#include <linux/interrupt.h>
24#include <linux/syscore_ops.h>
25#include <linux/slab.h>
26#include <linux/errno.h>
27#include <linux/io.h>
28
29#include <asm/irq.h>
30#include <mach/hardware.h>
31#include <mach/dma.h>
32#include <mach/map.h>
33
34#include <plat/dma-s3c24xx.h>
35#include <plat/regs-dma.h>
36
37/* io map for dma */
38static void __iomem *dma_base;
39static struct kmem_cache *dma_kmem;
40
41static int dma_channels;
42
43static struct s3c24xx_dma_selection dma_sel;
44
45
46/* debugging functions */
47
48#define BUF_MAGIC (0xcafebabe)
49
50#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
51
52#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
53
54#if 1
55#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
56#else
57static inline void
58dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
59{
60 pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
61 writel(val, dma_regaddr(chan, reg));
62}
63#endif
64
65#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
66
67/* captured register state for debug */
68
69struct s3c2410_dma_regstate {
70 unsigned long dcsrc;
71 unsigned long disrc;
72 unsigned long dstat;
73 unsigned long dcon;
74 unsigned long dmsktrig;
75};
76
77#ifdef CONFIG_S3C2410_DMA_DEBUG
78
79/* dmadbg_showregs
80 *
81 * simple debug routine to print the current state of the dma registers
82*/
83
84static void
85dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
86{
87 regs->dcsrc = dma_rdreg(chan, S3C2410_DMA_DCSRC);
88 regs->disrc = dma_rdreg(chan, S3C2410_DMA_DISRC);
89 regs->dstat = dma_rdreg(chan, S3C2410_DMA_DSTAT);
90 regs->dcon = dma_rdreg(chan, S3C2410_DMA_DCON);
91 regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
92}
93
94static void
95dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
96 struct s3c2410_dma_regstate *regs)
97{
98 printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
99 chan->number, fname, line,
100 regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
101 regs->dcon);
102}
103
104static void
105dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
106{
107 struct s3c2410_dma_regstate state;
108
109 dmadbg_capture(chan, &state);
110
111 printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
112 chan->number, fname, line, chan->load_state,
113 chan->curr, chan->next, chan->end);
114
115 dmadbg_dumpregs(fname, line, chan, &state);
116}
117
118static void
119dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
120{
121 struct s3c2410_dma_regstate state;
122
123 dmadbg_capture(chan, &state);
124 dmadbg_dumpregs(fname, line, chan, &state);
125}
126
127#define dbg_showregs(chan) dmadbg_showregs(__func__, __LINE__, (chan))
128#define dbg_showchan(chan) dmadbg_showchan(__func__, __LINE__, (chan))
129#else
130#define dbg_showregs(chan) do { } while(0)
131#define dbg_showchan(chan) do { } while(0)
132#endif /* CONFIG_S3C2410_DMA_DEBUG */
133
134/* s3c2410_dma_stats_timeout
135 *
136 * Update DMA stats from timeout info
137*/
138
139static void
140s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
141{
142 if (stats == NULL)
143 return;
144
145 if (val > stats->timeout_longest)
146 stats->timeout_longest = val;
147 if (val < stats->timeout_shortest)
148 stats->timeout_shortest = val;
149
150 stats->timeout_avg += val;
151}
152
153/* s3c2410_dma_waitforload
154 *
155 * wait for the DMA engine to load a buffer, and update the state accordingly
156*/
157
158static int
159s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
160{
161 int timeout = chan->load_timeout;
162 int took;
163
164 if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
165 printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
166 return 0;
167 }
168
169 if (chan->stats != NULL)
170 chan->stats->loads++;
171
172 while (--timeout > 0) {
173 if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
174 took = chan->load_timeout - timeout;
175
176 s3c2410_dma_stats_timeout(chan->stats, took);
177
178 switch (chan->load_state) {
179 case S3C2410_DMALOAD_1LOADED:
180 chan->load_state = S3C2410_DMALOAD_1RUNNING;
181 break;
182
183 default:
184 printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
185 }
186
187 return 1;
188 }
189 }
190
191 if (chan->stats != NULL) {
192 chan->stats->timeout_failed++;
193 }
194
195 return 0;
196}
197
198/* s3c2410_dma_loadbuffer
199 *
200 * load a buffer, and update the channel state
201*/
202
203static inline int
204s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
205 struct s3c2410_dma_buf *buf)
206{
207 unsigned long reload;
208
209 if (buf == NULL) {
210 dmawarn("buffer is NULL\n");
211 return -EINVAL;
212 }
213
214 pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
215 buf, (unsigned long)buf->data, buf->size);
216
217 /* check the state of the channel before we do anything */
218
219 if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
220 dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
221 }
222
223 if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
224 dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
225 }
226
227 /* it would seem sensible if we are the last buffer to not bother
228 * with the auto-reload bit, so that the DMA engine will not try
229 * and load another transfer after this one has finished...
230 */
231 if (chan->load_state == S3C2410_DMALOAD_NONE) {
232 pr_debug("load_state is none, checking for noreload (next=%p)\n",
233 buf->next);
234 reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
235 } else {
236 //pr_debug("load_state is %d => autoreload\n", chan->load_state);
237 reload = S3C2410_DCON_AUTORELOAD;
238 }
239
240 if ((buf->data & 0xf0000000) != 0x30000000) {
241 dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
242 }
243
244 writel(buf->data, chan->addr_reg);
245
246 dma_wrreg(chan, S3C2410_DMA_DCON,
247 chan->dcon | reload | (buf->size/chan->xfer_unit));
248
249 chan->next = buf->next;
250
251 /* update the state of the channel */
252
253 switch (chan->load_state) {
254 case S3C2410_DMALOAD_NONE:
255 chan->load_state = S3C2410_DMALOAD_1LOADED;
256 break;
257
258 case S3C2410_DMALOAD_1RUNNING:
259 chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
260 break;
261
262 default:
263 dmawarn("dmaload: unknown state %d in loadbuffer\n",
264 chan->load_state);
265 break;
266 }
267
268 return 0;
269}
270
271/* s3c2410_dma_call_op
272 *
273 * small routine to call the op routine with the given op if it has been
274 * registered
275*/
276
277static void
278s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
279{
280 if (chan->op_fn != NULL) {
281 (chan->op_fn)(chan, op);
282 }
283}
284
285/* s3c2410_dma_buffdone
286 *
287 * small wrapper to check if callback routine needs to be called, and
288 * if so, call it
289*/
290
291static inline void
292s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
293 enum s3c2410_dma_buffresult result)
294{
295#if 0
296 pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
297 chan->callback_fn, buf, buf->id, buf->size, result);
298#endif
299
300 if (chan->callback_fn != NULL) {
301 (chan->callback_fn)(chan, buf->id, buf->size, result);
302 }
303}
304
305/* s3c2410_dma_start
306 *
307 * start a dma channel going
308*/
309
310static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
311{
312 unsigned long tmp;
313 unsigned long flags;
314
315 pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
316
317 local_irq_save(flags);
318
319 if (chan->state == S3C2410_DMA_RUNNING) {
320 pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
321 local_irq_restore(flags);
322 return 0;
323 }
324
325 chan->state = S3C2410_DMA_RUNNING;
326
327 /* check whether there is anything to load, and if not, see
328 * if we can find anything to load
329 */
330
331 if (chan->load_state == S3C2410_DMALOAD_NONE) {
332 if (chan->next == NULL) {
333 printk(KERN_ERR "dma%d: channel has nothing loaded\n",
334 chan->number);
335 chan->state = S3C2410_DMA_IDLE;
336 local_irq_restore(flags);
337 return -EINVAL;
338 }
339
340 s3c2410_dma_loadbuffer(chan, chan->next);
341 }
342
343 dbg_showchan(chan);
344
345 /* enable the channel */
346
347 if (!chan->irq_enabled) {
348 enable_irq(chan->irq);
349 chan->irq_enabled = 1;
350 }
351
352 /* start the channel going */
353
354 tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
355 tmp &= ~S3C2410_DMASKTRIG_STOP;
356 tmp |= S3C2410_DMASKTRIG_ON;
357 dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
358
359 pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
360
361#if 0
362 /* the dma buffer loads should take care of clearing the AUTO
363 * reloading feature */
364 tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
365 tmp &= ~S3C2410_DCON_NORELOAD;
366 dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
367#endif
368
369 s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
370
371 dbg_showchan(chan);
372
373 /* if we've only loaded one buffer onto the channel, then chec
374 * to see if we have another, and if so, try and load it so when
375 * the first buffer is finished, the new one will be loaded onto
376 * the channel */
377
378 if (chan->next != NULL) {
379 if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
380
381 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
382 pr_debug("%s: buff not yet loaded, no more todo\n",
383 __func__);
384 } else {
385 chan->load_state = S3C2410_DMALOAD_1RUNNING;
386 s3c2410_dma_loadbuffer(chan, chan->next);
387 }
388
389 } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
390 s3c2410_dma_loadbuffer(chan, chan->next);
391 }
392 }
393
394
395 local_irq_restore(flags);
396
397 return 0;
398}
399
400/* s3c2410_dma_canload
401 *
402 * work out if we can queue another buffer into the DMA engine
403*/
404
405static int
406s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
407{
408 if (chan->load_state == S3C2410_DMALOAD_NONE ||
409 chan->load_state == S3C2410_DMALOAD_1RUNNING)
410 return 1;
411
412 return 0;
413}
414
415/* s3c2410_dma_enqueue
416 *
417 * queue an given buffer for dma transfer.
418 *
419 * id the device driver's id information for this buffer
420 * data the physical address of the buffer data
421 * size the size of the buffer in bytes
422 *
423 * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
424 * is checked, and if set, the channel is started. If this flag isn't set,
425 * then an error will be returned.
426 *
427 * It is possible to queue more than one DMA buffer onto a channel at
428 * once, and the code will deal with the re-loading of the next buffer
429 * when necessary.
430*/
431
432int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
433 dma_addr_t data, int size)
434{
435 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
436 struct s3c2410_dma_buf *buf;
437 unsigned long flags;
438
439 if (chan == NULL)
440 return -EINVAL;
441
442 pr_debug("%s: id=%p, data=%08x, size=%d\n",
443 __func__, id, (unsigned int)data, size);
444
445 buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
446 if (buf == NULL) {
447 pr_debug("%s: out of memory (%ld alloc)\n",
448 __func__, (long)sizeof(*buf));
449 return -ENOMEM;
450 }
451
452 //pr_debug("%s: new buffer %p\n", __func__, buf);
453 //dbg_showchan(chan);
454
455 buf->next = NULL;
456 buf->data = buf->ptr = data;
457 buf->size = size;
458 buf->id = id;
459 buf->magic = BUF_MAGIC;
460
461 local_irq_save(flags);
462
463 if (chan->curr == NULL) {
464 /* we've got nothing loaded... */
465 pr_debug("%s: buffer %p queued onto empty channel\n",
466 __func__, buf);
467
468 chan->curr = buf;
469 chan->end = buf;
470 chan->next = NULL;
471 } else {
472 pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
473 chan->number, __func__, buf);
474
475 if (chan->end == NULL) {
476 pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
477 chan->number, __func__, chan);
478 } else {
479 chan->end->next = buf;
480 chan->end = buf;
481 }
482 }
483
484 /* if necessary, update the next buffer field */
485 if (chan->next == NULL)
486 chan->next = buf;
487
488 /* check to see if we can load a buffer */
489 if (chan->state == S3C2410_DMA_RUNNING) {
490 if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
491 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
492 printk(KERN_ERR "dma%d: loadbuffer:"
493 "timeout loading buffer\n",
494 chan->number);
495 dbg_showchan(chan);
496 local_irq_restore(flags);
497 return -EINVAL;
498 }
499 }
500
501 while (s3c2410_dma_canload(chan) && chan->next != NULL) {
502 s3c2410_dma_loadbuffer(chan, chan->next);
503 }
504 } else if (chan->state == S3C2410_DMA_IDLE) {
505 if (chan->flags & S3C2410_DMAF_AUTOSTART) {
506 s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
507 S3C2410_DMAOP_START);
508 }
509 }
510
511 local_irq_restore(flags);
512 return 0;
513}
514
515EXPORT_SYMBOL(s3c2410_dma_enqueue);
516
517static inline void
518s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
519{
520 int magicok = (buf->magic == BUF_MAGIC);
521
522 buf->magic = -1;
523
524 if (magicok) {
525 kmem_cache_free(dma_kmem, buf);
526 } else {
527 printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
528 }
529}
530
531/* s3c2410_dma_lastxfer
532 *
533 * called when the system is out of buffers, to ensure that the channel
534 * is prepared for shutdown.
535*/
536
537static inline void
538s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
539{
540#if 0
541 pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
542 chan->number, chan->load_state);
543#endif
544
545 switch (chan->load_state) {
546 case S3C2410_DMALOAD_NONE:
547 break;
548
549 case S3C2410_DMALOAD_1LOADED:
550 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
551 /* flag error? */
552 printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
553 chan->number, __func__);
554 return;
555 }
556 break;
557
558 case S3C2410_DMALOAD_1LOADED_1RUNNING:
559 /* I believe in this case we do not have anything to do
560 * until the next buffer comes along, and we turn off the
561 * reload */
562 return;
563
564 default:
565 pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
566 chan->number, chan->load_state);
567 return;
568
569 }
570
571 /* hopefully this'll shut the damned thing up after the transfer... */
572 dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
573}
574
575
576#define dmadbg2(x...)
577
578static irqreturn_t
579s3c2410_dma_irq(int irq, void *devpw)
580{
581 struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
582 struct s3c2410_dma_buf *buf;
583
584 buf = chan->curr;
585
586 dbg_showchan(chan);
587
588 /* modify the channel state */
589
590 switch (chan->load_state) {
591 case S3C2410_DMALOAD_1RUNNING:
592 /* TODO - if we are running only one buffer, we probably
593 * want to reload here, and then worry about the buffer
594 * callback */
595
596 chan->load_state = S3C2410_DMALOAD_NONE;
597 break;
598
599 case S3C2410_DMALOAD_1LOADED:
600 /* iirc, we should go back to NONE loaded here, we
601 * had a buffer, and it was never verified as being
602 * loaded.
603 */
604
605 chan->load_state = S3C2410_DMALOAD_NONE;
606 break;
607
608 case S3C2410_DMALOAD_1LOADED_1RUNNING:
609 /* we'll worry about checking to see if another buffer is
610 * ready after we've called back the owner. This should
611 * ensure we do not wait around too long for the DMA
612 * engine to start the next transfer
613 */
614
615 chan->load_state = S3C2410_DMALOAD_1LOADED;
616 break;
617
618 case S3C2410_DMALOAD_NONE:
619 printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
620 chan->number);
621 break;
622
623 default:
624 printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
625 chan->number, chan->load_state);
626 break;
627 }
628
629 if (buf != NULL) {
630 /* update the chain to make sure that if we load any more
631 * buffers when we call the callback function, things should
632 * work properly */
633
634 chan->curr = buf->next;
635 buf->next = NULL;
636
637 if (buf->magic != BUF_MAGIC) {
638 printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
639 chan->number, __func__, buf);
640 return IRQ_HANDLED;
641 }
642
643 s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
644
645 /* free resouces */
646 s3c2410_dma_freebuf(buf);
647 } else {
648 }
649
650 /* only reload if the channel is still running... our buffer done
651 * routine may have altered the state by requesting the dma channel
652 * to stop or shutdown... */
653
654 /* todo: check that when the channel is shut-down from inside this
655 * function, we cope with unsetting reload, etc */
656
657 if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
658 unsigned long flags;
659
660 switch (chan->load_state) {
661 case S3C2410_DMALOAD_1RUNNING:
662 /* don't need to do anything for this state */
663 break;
664
665 case S3C2410_DMALOAD_NONE:
666 /* can load buffer immediately */
667 break;
668
669 case S3C2410_DMALOAD_1LOADED:
670 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
671 /* flag error? */
672 printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
673 chan->number, __func__);
674 return IRQ_HANDLED;
675 }
676
677 break;
678
679 case S3C2410_DMALOAD_1LOADED_1RUNNING:
680 goto no_load;
681
682 default:
683 printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
684 chan->number, chan->load_state);
685 return IRQ_HANDLED;
686 }
687
688 local_irq_save(flags);
689 s3c2410_dma_loadbuffer(chan, chan->next);
690 local_irq_restore(flags);
691 } else {
692 s3c2410_dma_lastxfer(chan);
693
694 /* see if we can stop this channel.. */
695 if (chan->load_state == S3C2410_DMALOAD_NONE) {
696 pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
697 chan->number, jiffies);
698 s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
699 S3C2410_DMAOP_STOP);
700 }
701 }
702
703 no_load:
704 return IRQ_HANDLED;
705}
706
707static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
708
709/* s3c2410_request_dma
710 *
711 * get control of an dma channel
712*/
713
714int s3c2410_dma_request(enum dma_ch channel,
715 struct s3c2410_dma_client *client,
716 void *dev)
717{
718 struct s3c2410_dma_chan *chan;
719 unsigned long flags;
720 int err;
721
722 pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
723 channel, client->name, dev);
724
725 local_irq_save(flags);
726
727 chan = s3c2410_dma_map_channel(channel);
728 if (chan == NULL) {
729 local_irq_restore(flags);
730 return -EBUSY;
731 }
732
733 dbg_showchan(chan);
734
735 chan->client = client;
736 chan->in_use = 1;
737
738 if (!chan->irq_claimed) {
739 pr_debug("dma%d: %s : requesting irq %d\n",
740 channel, __func__, chan->irq);
741
742 chan->irq_claimed = 1;
743 local_irq_restore(flags);
744
745 err = request_irq(chan->irq, s3c2410_dma_irq, 0,
746 client->name, (void *)chan);
747
748 local_irq_save(flags);
749
750 if (err) {
751 chan->in_use = 0;
752 chan->irq_claimed = 0;
753 local_irq_restore(flags);
754
755 printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
756 client->name, chan->irq, chan->number);
757 return err;
758 }
759
760 chan->irq_enabled = 1;
761 }
762
763 local_irq_restore(flags);
764
765 /* need to setup */
766
767 pr_debug("%s: channel initialised, %p\n", __func__, chan);
768
769 return chan->number | DMACH_LOW_LEVEL;
770}
771
772EXPORT_SYMBOL(s3c2410_dma_request);
773
774/* s3c2410_dma_free
775 *
776 * release the given channel back to the system, will stop and flush
777 * any outstanding transfers, and ensure the channel is ready for the
778 * next claimant.
779 *
780 * Note, although a warning is currently printed if the freeing client
781 * info is not the same as the registrant's client info, the free is still
782 * allowed to go through.
783*/
784
785int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *client)
786{
787 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
788 unsigned long flags;
789
790 if (chan == NULL)
791 return -EINVAL;
792
793 local_irq_save(flags);
794
795 if (chan->client != client) {
796 printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
797 channel, chan->client, client);
798 }
799
800 /* sort out stopping and freeing the channel */
801
802 if (chan->state != S3C2410_DMA_IDLE) {
803 pr_debug("%s: need to stop dma channel %p\n",
804 __func__, chan);
805
806 /* possibly flush the channel */
807 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
808 }
809
810 chan->client = NULL;
811 chan->in_use = 0;
812
813 if (chan->irq_claimed)
814 free_irq(chan->irq, (void *)chan);
815
816 chan->irq_claimed = 0;
817
818 if (!(channel & DMACH_LOW_LEVEL))
819 s3c_dma_chan_map[channel] = NULL;
820
821 local_irq_restore(flags);
822
823 return 0;
824}
825
826EXPORT_SYMBOL(s3c2410_dma_free);
827
828static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
829{
830 unsigned long flags;
831 unsigned long tmp;
832
833 pr_debug("%s:\n", __func__);
834
835 dbg_showchan(chan);
836
837 local_irq_save(flags);
838
839 s3c2410_dma_call_op(chan, S3C2410_DMAOP_STOP);
840
841 tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
842 tmp |= S3C2410_DMASKTRIG_STOP;
843 //tmp &= ~S3C2410_DMASKTRIG_ON;
844 dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
845
846#if 0
847 /* should also clear interrupts, according to WinCE BSP */
848 tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
849 tmp |= S3C2410_DCON_NORELOAD;
850 dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
851#endif
852
853 /* should stop do this, or should we wait for flush? */
854 chan->state = S3C2410_DMA_IDLE;
855 chan->load_state = S3C2410_DMALOAD_NONE;
856
857 local_irq_restore(flags);
858
859 return 0;
860}
861
862static void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
863{
864 unsigned long tmp;
865 unsigned int timeout = 0x10000;
866
867 while (timeout-- > 0) {
868 tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
869
870 if (!(tmp & S3C2410_DMASKTRIG_ON))
871 return;
872 }
873
874 pr_debug("dma%d: failed to stop?\n", chan->number);
875}
876
877
878/* s3c2410_dma_flush
879 *
880 * stop the channel, and remove all current and pending transfers
881*/
882
883static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
884{
885 struct s3c2410_dma_buf *buf, *next;
886 unsigned long flags;
887
888 pr_debug("%s: chan %p (%d)\n", __func__, chan, chan->number);
889
890 dbg_showchan(chan);
891
892 local_irq_save(flags);
893
894 if (chan->state != S3C2410_DMA_IDLE) {
895 pr_debug("%s: stopping channel...\n", __func__ );
896 s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
897 }
898
899 buf = chan->curr;
900 if (buf == NULL)
901 buf = chan->next;
902
903 chan->curr = chan->next = chan->end = NULL;
904
905 if (buf != NULL) {
906 for ( ; buf != NULL; buf = next) {
907 next = buf->next;
908
909 pr_debug("%s: free buffer %p, next %p\n",
910 __func__, buf, buf->next);
911
912 s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
913 s3c2410_dma_freebuf(buf);
914 }
915 }
916
917 dbg_showregs(chan);
918
919 s3c2410_dma_waitforstop(chan);
920
921#if 0
922 /* should also clear interrupts, according to WinCE BSP */
923 {
924 unsigned long tmp;
925
926 tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
927 tmp |= S3C2410_DCON_NORELOAD;
928 dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
929 }
930#endif
931
932 dbg_showregs(chan);
933
934 local_irq_restore(flags);
935
936 return 0;
937}
938
939static int s3c2410_dma_started(struct s3c2410_dma_chan *chan)
940{
941 unsigned long flags;
942
943 local_irq_save(flags);
944
945 dbg_showchan(chan);
946
947 /* if we've only loaded one buffer onto the channel, then chec
948 * to see if we have another, and if so, try and load it so when
949 * the first buffer is finished, the new one will be loaded onto
950 * the channel */
951
952 if (chan->next != NULL) {
953 if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
954
955 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
956 pr_debug("%s: buff not yet loaded, no more todo\n",
957 __func__);
958 } else {
959 chan->load_state = S3C2410_DMALOAD_1RUNNING;
960 s3c2410_dma_loadbuffer(chan, chan->next);
961 }
962
963 } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
964 s3c2410_dma_loadbuffer(chan, chan->next);
965 }
966 }
967
968
969 local_irq_restore(flags);
970
971 return 0;
972
973}
974
975int
976s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op)
977{
978 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
979
980 if (chan == NULL)
981 return -EINVAL;
982
983 switch (op) {
984 case S3C2410_DMAOP_START:
985 return s3c2410_dma_start(chan);
986
987 case S3C2410_DMAOP_STOP:
988 return s3c2410_dma_dostop(chan);
989
990 case S3C2410_DMAOP_PAUSE:
991 case S3C2410_DMAOP_RESUME:
992 return -ENOENT;
993
994 case S3C2410_DMAOP_FLUSH:
995 return s3c2410_dma_flush(chan);
996
997 case S3C2410_DMAOP_STARTED:
998 return s3c2410_dma_started(chan);
999
1000 case S3C2410_DMAOP_TIMEOUT:
1001 return 0;
1002
1003 }
1004
1005 return -ENOENT; /* unknown, don't bother */
1006}
1007
1008EXPORT_SYMBOL(s3c2410_dma_ctrl);
1009
1010/* DMA configuration for each channel
1011 *
1012 * DISRCC -> source of the DMA (AHB,APB)
1013 * DISRC -> source address of the DMA
1014 * DIDSTC -> destination of the DMA (AHB,APD)
1015 * DIDST -> destination address of the DMA
1016*/
1017
1018/* s3c2410_dma_config
1019 *
1020 * xfersize: size of unit in bytes (1,2,4)
1021*/
1022
1023int s3c2410_dma_config(enum dma_ch channel,
1024 int xferunit)
1025{
1026 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
1027 unsigned int dcon;
1028
1029 pr_debug("%s: chan=%d, xfer_unit=%d\n", __func__, channel, xferunit);
1030
1031 if (chan == NULL)
1032 return -EINVAL;
1033
1034 dcon = chan->dcon & dma_sel.dcon_mask;
1035 pr_debug("%s: dcon is %08x\n", __func__, dcon);
1036
1037 switch (chan->req_ch) {
1038 case DMACH_I2S_IN:
1039 case DMACH_I2S_OUT:
1040 case DMACH_PCM_IN:
1041 case DMACH_PCM_OUT:
1042 case DMACH_MIC_IN:
1043 default:
1044 dcon |= S3C2410_DCON_HANDSHAKE;
1045 dcon |= S3C2410_DCON_SYNC_PCLK;
1046 break;
1047
1048 case DMACH_SDI:
1049 /* note, ensure if need HANDSHAKE or not */
1050 dcon |= S3C2410_DCON_SYNC_PCLK;
1051 break;
1052
1053 case DMACH_XD0:
1054 case DMACH_XD1:
1055 dcon |= S3C2410_DCON_HANDSHAKE;
1056 dcon |= S3C2410_DCON_SYNC_HCLK;
1057 break;
1058 }
1059
1060 switch (xferunit) {
1061 case 1:
1062 dcon |= S3C2410_DCON_BYTE;
1063 break;
1064
1065 case 2:
1066 dcon |= S3C2410_DCON_HALFWORD;
1067 break;
1068
1069 case 4:
1070 dcon |= S3C2410_DCON_WORD;
1071 break;
1072
1073 default:
1074 pr_debug("%s: bad transfer size %d\n", __func__, xferunit);
1075 return -EINVAL;
1076 }
1077
1078 dcon |= S3C2410_DCON_HWTRIG;
1079 dcon |= S3C2410_DCON_INTREQ;
1080
1081 pr_debug("%s: dcon now %08x\n", __func__, dcon);
1082
1083 chan->dcon = dcon;
1084 chan->xfer_unit = xferunit;
1085
1086 return 0;
1087}
1088
1089EXPORT_SYMBOL(s3c2410_dma_config);
1090
1091
1092/* s3c2410_dma_devconfig
1093 *
1094 * configure the dma source/destination hardware type and address
1095 *
1096 * source: DMA_FROM_DEVICE: source is hardware
1097 * DMA_TO_DEVICE: source is memory
1098 *
1099 * devaddr: physical address of the source
1100*/
1101
1102int s3c2410_dma_devconfig(enum dma_ch channel,
1103 enum dma_data_direction source,
1104 unsigned long devaddr)
1105{
1106 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
1107 unsigned int hwcfg;
1108
1109 if (chan == NULL)
1110 return -EINVAL;
1111
1112 pr_debug("%s: source=%d, devaddr=%08lx\n",
1113 __func__, (int)source, devaddr);
1114
1115 chan->source = source;
1116 chan->dev_addr = devaddr;
1117
1118 switch (chan->req_ch) {
1119 case DMACH_XD0:
1120 case DMACH_XD1:
1121 hwcfg = 0; /* AHB */
1122 break;
1123
1124 default:
1125 hwcfg = S3C2410_DISRCC_APB;
1126 }
1127
1128 /* always assume our peripheral desintation is a fixed
1129 * address in memory. */
1130 hwcfg |= S3C2410_DISRCC_INC;
1131
1132 switch (source) {
1133 case DMA_FROM_DEVICE:
1134 /* source is hardware */
1135 pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
1136 __func__, devaddr, hwcfg);
1137 dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
1138 dma_wrreg(chan, S3C2410_DMA_DISRC, devaddr);
1139 dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
1140
1141 chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
1142 break;
1143
1144 case DMA_TO_DEVICE:
1145 /* source is memory */
1146 pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",
1147 __func__, devaddr, hwcfg);
1148 dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
1149 dma_wrreg(chan, S3C2410_DMA_DIDST, devaddr);
1150 dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
1151
1152 chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
1153 break;
1154
1155 default:
1156 printk(KERN_ERR "dma%d: invalid source type (%d)\n",
1157 channel, source);
1158
1159 return -EINVAL;
1160 }
1161
1162 return 0;
1163}
1164
1165EXPORT_SYMBOL(s3c2410_dma_devconfig);
1166
1167/* s3c2410_dma_getposition
1168 *
1169 * returns the current transfer points for the dma source and destination
1170*/
1171
1172int s3c2410_dma_getposition(enum dma_ch channel, dma_addr_t *src, dma_addr_t *dst)
1173{
1174 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
1175
1176 if (chan == NULL)
1177 return -EINVAL;
1178
1179 if (src != NULL)
1180 *src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
1181
1182 if (dst != NULL)
1183 *dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
1184
1185 return 0;
1186}
1187
1188EXPORT_SYMBOL(s3c2410_dma_getposition);
1189
1190/* system core operations */
1191
1192#ifdef CONFIG_PM
1193
1194static void s3c2410_dma_suspend_chan(struct s3c2410_dma_chan *cp)
1195{
1196 printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
1197
1198 if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
1199 /* the dma channel is still working, which is probably
1200 * a bad thing to do over suspend/resume. We stop the
1201 * channel and assume that the client is either going to
1202 * retry after resume, or that it is broken.
1203 */
1204
1205 printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
1206 cp->number);
1207
1208 s3c2410_dma_dostop(cp);
1209 }
1210}
1211
1212static int s3c2410_dma_suspend(void)
1213{
1214 struct s3c2410_dma_chan *cp = s3c2410_chans;
1215 int channel;
1216
1217 for (channel = 0; channel < dma_channels; cp++, channel++)
1218 s3c2410_dma_suspend_chan(cp);
1219
1220 return 0;
1221}
1222
1223static void s3c2410_dma_resume_chan(struct s3c2410_dma_chan *cp)
1224{
1225 unsigned int no = cp->number | DMACH_LOW_LEVEL;
1226
1227 /* restore channel's hardware configuration */
1228
1229 if (!cp->in_use)
1230 return;
1231
1232 printk(KERN_INFO "dma%d: restoring configuration\n", cp->number);
1233
1234 s3c2410_dma_config(no, cp->xfer_unit);
1235 s3c2410_dma_devconfig(no, cp->source, cp->dev_addr);
1236
1237 /* re-select the dma source for this channel */
1238
1239 if (cp->map != NULL)
1240 dma_sel.select(cp, cp->map);
1241}
1242
1243static void s3c2410_dma_resume(void)
1244{
1245 struct s3c2410_dma_chan *cp = s3c2410_chans + dma_channels - 1;
1246 int channel;
1247
1248 for (channel = dma_channels - 1; channel >= 0; cp--, channel--)
1249 s3c2410_dma_resume_chan(cp);
1250}
1251
1252#else
1253#define s3c2410_dma_suspend NULL
1254#define s3c2410_dma_resume NULL
1255#endif /* CONFIG_PM */
1256
1257struct syscore_ops dma_syscore_ops = {
1258 .suspend = s3c2410_dma_suspend,
1259 .resume = s3c2410_dma_resume,
1260};
1261
1262/* kmem cache implementation */
1263
1264static void s3c2410_dma_cache_ctor(void *p)
1265{
1266 memset(p, 0, sizeof(struct s3c2410_dma_buf));
1267}
1268
1269/* initialisation code */
1270
1271static int __init s3c24xx_dma_syscore_init(void)
1272{
1273 register_syscore_ops(&dma_syscore_ops);
1274
1275 return 0;
1276}
1277
1278late_initcall(s3c24xx_dma_syscore_init);
1279
1280int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,
1281 unsigned int stride)
1282{
1283 struct s3c2410_dma_chan *cp;
1284 int channel;
1285 int ret;
1286
1287 printk("S3C24XX DMA Driver, Copyright 2003-2006 Simtec Electronics\n");
1288
1289 dma_channels = channels;
1290
1291 dma_base = ioremap(S3C24XX_PA_DMA, stride * channels);
1292 if (dma_base == NULL) {
1293 printk(KERN_ERR "dma failed to remap register block\n");
1294 return -ENOMEM;
1295 }
1296
1297 dma_kmem = kmem_cache_create("dma_desc",
1298 sizeof(struct s3c2410_dma_buf), 0,
1299 SLAB_HWCACHE_ALIGN,
1300 s3c2410_dma_cache_ctor);
1301
1302 if (dma_kmem == NULL) {
1303 printk(KERN_ERR "dma failed to make kmem cache\n");
1304 ret = -ENOMEM;
1305 goto err;
1306 }
1307
1308 for (channel = 0; channel < channels; channel++) {
1309 cp = &s3c2410_chans[channel];
1310
1311 memset(cp, 0, sizeof(struct s3c2410_dma_chan));
1312
1313 /* dma channel irqs are in order.. */
1314 cp->number = channel;
1315 cp->irq = channel + irq;
1316 cp->regs = dma_base + (channel * stride);
1317
1318 /* point current stats somewhere */
1319 cp->stats = &cp->stats_store;
1320 cp->stats_store.timeout_shortest = LONG_MAX;
1321
1322 /* basic channel configuration */
1323
1324 cp->load_timeout = 1<<18;
1325
1326 printk("DMA channel %d at %p, irq %d\n",
1327 cp->number, cp->regs, cp->irq);
1328 }
1329
1330 return 0;
1331
1332 err:
1333 kmem_cache_destroy(dma_kmem);
1334 iounmap(dma_base);
1335 dma_base = NULL;
1336 return ret;
1337}
1338
1339int __init s3c2410_dma_init(void)
1340{
1341 return s3c24xx_dma_init(4, IRQ_DMA0, 0x40);
1342}
1343
1344static inline int is_channel_valid(unsigned int channel)
1345{
1346 return (channel & DMA_CH_VALID);
1347}
1348
1349static struct s3c24xx_dma_order *dma_order;
1350
1351
1352/* s3c2410_dma_map_channel()
1353 *
1354 * turn the virtual channel number into a real, and un-used hardware
1355 * channel.
1356 *
1357 * first, try the dma ordering given to us by either the relevant
1358 * dma code, or the board. Then just find the first usable free
1359 * channel
1360*/
1361
1362static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
1363{
1364 struct s3c24xx_dma_order_ch *ord = NULL;
1365 struct s3c24xx_dma_map *ch_map;
1366 struct s3c2410_dma_chan *dmach;
1367 int ch;
1368
1369 if (dma_sel.map == NULL || channel > dma_sel.map_size)
1370 return NULL;
1371
1372 ch_map = dma_sel.map + channel;
1373
1374 /* first, try the board mapping */
1375
1376 if (dma_order) {
1377 ord = &dma_order->channels[channel];
1378
1379 for (ch = 0; ch < dma_channels; ch++) {
1380 int tmp;
1381 if (!is_channel_valid(ord->list[ch]))
1382 continue;
1383
1384 tmp = ord->list[ch] & ~DMA_CH_VALID;
1385 if (s3c2410_chans[tmp].in_use == 0) {
1386 ch = tmp;
1387 goto found;
1388 }
1389 }
1390
1391 if (ord->flags & DMA_CH_NEVER)
1392 return NULL;
1393 }
1394
1395 /* second, search the channel map for first free */
1396
1397 for (ch = 0; ch < dma_channels; ch++) {
1398 if (!is_channel_valid(ch_map->channels[ch]))
1399 continue;
1400
1401 if (s3c2410_chans[ch].in_use == 0) {
1402 printk("mapped channel %d to %d\n", channel, ch);
1403 break;
1404 }
1405 }
1406
1407 if (ch >= dma_channels)
1408 return NULL;
1409
1410 /* update our channel mapping */
1411
1412 found:
1413 dmach = &s3c2410_chans[ch];
1414 dmach->map = ch_map;
1415 dmach->req_ch = channel;
1416 s3c_dma_chan_map[channel] = dmach;
1417
1418 /* select the channel */
1419
1420 (dma_sel.select)(dmach, ch_map);
1421
1422 return dmach;
1423}
1424
1425static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
1426{
1427 return 0;
1428}
1429
1430int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
1431{
1432 struct s3c24xx_dma_map *nmap;
1433 size_t map_sz = sizeof(*nmap) * sel->map_size;
1434 int ptr;
1435
1436 nmap = kmemdup(sel->map, map_sz, GFP_KERNEL);
1437 if (nmap == NULL)
1438 return -ENOMEM;
1439
1440 memcpy(&dma_sel, sel, sizeof(*sel));
1441
1442 dma_sel.map = nmap;
1443
1444 for (ptr = 0; ptr < sel->map_size; ptr++)
1445 s3c24xx_dma_check_entry(nmap+ptr, ptr);
1446
1447 return 0;
1448}
1449
1450int __init s3c24xx_dma_order_set(struct s3c24xx_dma_order *ord)
1451{
1452 struct s3c24xx_dma_order *nord = dma_order;
1453
1454 if (nord == NULL)
1455 nord = kmalloc(sizeof(struct s3c24xx_dma_order), GFP_KERNEL);
1456
1457 if (nord == NULL) {
1458 printk(KERN_ERR "no memory to store dma channel order\n");
1459 return -ENOMEM;
1460 }
1461
1462 dma_order = nord;
1463 memcpy(nord, ord, sizeof(struct s3c24xx_dma_order));
1464 return 0;
1465}
diff --git a/arch/arm/mach-s3c24xx/include/mach/dma.h b/arch/arm/mach-s3c24xx/include/mach/dma.h
index b55da1d8cd8f..9e8117198e0c 100644
--- a/arch/arm/mach-s3c24xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c24xx/include/mach/dma.h
@@ -15,8 +15,6 @@
15 15
16#include <linux/device.h> 16#include <linux/device.h>
17 17
18#define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */
19
20/* We use `virtual` dma channels to hide the fact we have only a limited 18/* We use `virtual` dma channels to hide the fact we have only a limited
21 * number of DMA channels, and not of all of them (dependent on the device) 19 * number of DMA channels, and not of all of them (dependent on the device)
22 * can be attached to any DMA source. We therefore let the DMA core handle 20 * can be attached to any DMA source. We therefore let the DMA core handle
@@ -54,161 +52,4 @@ enum dma_ch {
54 DMACH_MAX, /* the end entry */ 52 DMACH_MAX, /* the end entry */
55}; 53};
56 54
57static inline bool samsung_dma_has_circular(void)
58{
59 return false;
60}
61
62static inline bool samsung_dma_is_dmadev(void)
63{
64 return false;
65}
66
67#include <plat/dma.h>
68
69#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
70
71/* we have 4 dma channels */
72#if !defined(CONFIG_CPU_S3C2443) && !defined(CONFIG_CPU_S3C2416)
73#define S3C_DMA_CHANNELS (4)
74#else
75#define S3C_DMA_CHANNELS (6)
76#endif
77
78/* types */
79
80enum s3c2410_dma_state {
81 S3C2410_DMA_IDLE,
82 S3C2410_DMA_RUNNING,
83 S3C2410_DMA_PAUSED
84};
85
86/* enum s3c2410_dma_loadst
87 *
88 * This represents the state of the DMA engine, wrt to the loaded / running
89 * transfers. Since we don't have any way of knowing exactly the state of
90 * the DMA transfers, we need to know the state to make decisions on whether
91 * we can
92 *
93 * S3C2410_DMA_NONE
94 *
95 * There are no buffers loaded (the channel should be inactive)
96 *
97 * S3C2410_DMA_1LOADED
98 *
99 * There is one buffer loaded, however it has not been confirmed to be
100 * loaded by the DMA engine. This may be because the channel is not
101 * yet running, or the DMA driver decided that it was too costly to
102 * sit and wait for it to happen.
103 *
104 * S3C2410_DMA_1RUNNING
105 *
106 * The buffer has been confirmed running, and not finisged
107 *
108 * S3C2410_DMA_1LOADED_1RUNNING
109 *
110 * There is a buffer waiting to be loaded by the DMA engine, and one
111 * currently running.
112*/
113
114enum s3c2410_dma_loadst {
115 S3C2410_DMALOAD_NONE,
116 S3C2410_DMALOAD_1LOADED,
117 S3C2410_DMALOAD_1RUNNING,
118 S3C2410_DMALOAD_1LOADED_1RUNNING,
119};
120
121
122/* flags */
123
124#define S3C2410_DMAF_SLOW (1<<0) /* slow, so don't worry about
125 * waiting for reloads */
126#define S3C2410_DMAF_AUTOSTART (1<<1) /* auto-start if buffer queued */
127
128#define S3C2410_DMAF_CIRCULAR (1 << 2) /* no circular dma support */
129
130/* dma buffer */
131
132struct s3c2410_dma_buf;
133
134/* s3c2410_dma_buf
135 *
136 * internally used buffer structure to describe a queued or running
137 * buffer.
138*/
139
140struct s3c2410_dma_buf {
141 struct s3c2410_dma_buf *next;
142 int magic; /* magic */
143 int size; /* buffer size in bytes */
144 dma_addr_t data; /* start of DMA data */
145 dma_addr_t ptr; /* where the DMA got to [1] */
146 void *id; /* client's id */
147};
148
149/* [1] is this updated for both recv/send modes? */
150
151struct s3c2410_dma_stats {
152 unsigned long loads;
153 unsigned long timeout_longest;
154 unsigned long timeout_shortest;
155 unsigned long timeout_avg;
156 unsigned long timeout_failed;
157};
158
159struct s3c2410_dma_map;
160
161/* struct s3c2410_dma_chan
162 *
163 * full state information for each DMA channel
164*/
165
166struct s3c2410_dma_chan {
167 /* channel state flags and information */
168 unsigned char number; /* number of this dma channel */
169 unsigned char in_use; /* channel allocated */
170 unsigned char irq_claimed; /* irq claimed for channel */
171 unsigned char irq_enabled; /* irq enabled for channel */
172 unsigned char xfer_unit; /* size of an transfer */
173
174 /* channel state */
175
176 enum s3c2410_dma_state state;
177 enum s3c2410_dma_loadst load_state;
178 struct s3c2410_dma_client *client;
179
180 /* channel configuration */
181 enum dma_data_direction source;
182 enum dma_ch req_ch;
183 unsigned long dev_addr;
184 unsigned long load_timeout;
185 unsigned int flags; /* channel flags */
186
187 struct s3c24xx_dma_map *map; /* channel hw maps */
188
189 /* channel's hardware position and configuration */
190 void __iomem *regs; /* channels registers */
191 void __iomem *addr_reg; /* data address register */
192 unsigned int irq; /* channel irq */
193 unsigned long dcon; /* default value of DCON */
194
195 /* driver handles */
196 s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */
197 s3c2410_dma_opfn_t op_fn; /* channel op callback */
198
199 /* stats gathering */
200 struct s3c2410_dma_stats *stats;
201 struct s3c2410_dma_stats stats_store;
202
203 /* buffer list and information */
204 struct s3c2410_dma_buf *curr; /* current dma buffer */
205 struct s3c2410_dma_buf *next; /* next buffer to load */
206 struct s3c2410_dma_buf *end; /* end of queue */
207
208 /* system device */
209 struct device dev;
210};
211
212typedef unsigned long dma_device_t;
213
214#endif /* __ASM_ARCH_DMA_H */ 55#endif /* __ASM_ARCH_DMA_H */