diff options
author | Arnd Bergmann <arnd@arndb.de> | 2015-01-23 23:09:54 -0500 |
---|---|---|
committer | Kukjin Kim <kgene@kernel.org> | 2015-01-23 23:09:54 -0500 |
commit | d50b9e2e788dce9b120b5ac1140f0cdd1bf905eb (patch) | |
tree | b34a10958fc998b0718f720289d3e40049584b58 /arch/arm/mach-s3c24xx | |
parent | 32b0aa9aaeb4a493135ea6368a614aa89c3c5488 (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/Kconfig | 42 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/Makefile | 7 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/dma-s3c2410.c | 182 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/dma-s3c2412.c | 150 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/dma-s3c2440.c | 193 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/dma-s3c2443.c | 179 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/dma.c | 1465 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/include/mach/dma.h | 159 |
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 | ||
117 | config 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 | |||
125 | config 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 | |||
132 | config 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 | |||
138 | config S3C2410_PM | 111 | config 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 | ||
328 | config S3C2412_DMA | ||
329 | bool | ||
330 | help | ||
331 | Internal config node for S3C2412 DMA support | ||
332 | |||
333 | config S3C2412_PM | 301 | config 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 | ||
439 | if CPU_S3C2440 | 407 | if CPU_S3C2440 |
440 | 408 | ||
441 | config S3C2440_DMA | ||
442 | bool | ||
443 | help | ||
444 | Support for S3C2440 specific DMA code5A | ||
445 | |||
446 | config S3C2440_XTAL_12000000 | 409 | config S3C2440_XTAL_12000000 |
447 | bool | 410 | bool |
448 | help | 411 | help |
@@ -601,11 +564,6 @@ endif # CPU_S3C2442 | |||
601 | 564 | ||
602 | if CPU_S3C2443 || CPU_S3C2416 | 565 | if CPU_S3C2443 || CPU_S3C2416 |
603 | 566 | ||
604 | config S3C2443_DMA | ||
605 | bool | ||
606 | help | ||
607 | Internal config node for S3C2443 DMA support | ||
608 | |||
609 | config S3C2443_SETUP_SPI | 567 | config 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 @@ | |||
12 | obj-y += common.o | 12 | obj-y += common.o |
13 | 13 | ||
14 | obj-$(CONFIG_CPU_S3C2410) += s3c2410.o | 14 | obj-$(CONFIG_CPU_S3C2410) += s3c2410.o |
15 | obj-$(CONFIG_S3C2410_DMA) += dma-s3c2410.o | ||
16 | obj-$(CONFIG_S3C2410_PLL) += pll-s3c2410.o | 15 | obj-$(CONFIG_S3C2410_PLL) += pll-s3c2410.o |
17 | obj-$(CONFIG_S3C2410_PM) += pm-s3c2410.o sleep-s3c2410.o | 16 | obj-$(CONFIG_S3C2410_PM) += pm-s3c2410.o sleep-s3c2410.o |
18 | 17 | ||
19 | obj-$(CONFIG_CPU_S3C2412) += s3c2412.o | 18 | obj-$(CONFIG_CPU_S3C2412) += s3c2412.o |
20 | obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o | ||
21 | obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o | 19 | obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o |
22 | obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o | 20 | obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o |
23 | 21 | ||
@@ -27,7 +25,6 @@ obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o | |||
27 | obj-$(CONFIG_CPU_S3C2440) += s3c2440.o | 25 | obj-$(CONFIG_CPU_S3C2440) += s3c2440.o |
28 | obj-$(CONFIG_CPU_S3C2442) += s3c2442.o | 26 | obj-$(CONFIG_CPU_S3C2442) += s3c2442.o |
29 | obj-$(CONFIG_CPU_S3C244X) += s3c244x.o | 27 | obj-$(CONFIG_CPU_S3C244X) += s3c244x.o |
30 | obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o | ||
31 | obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o | 28 | obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o |
32 | obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o | 29 | obj-$(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 | ||
42 | obj-$(CONFIG_S3C24XX_DMA) += dma.o | ||
43 | |||
44 | obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o | 39 | obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o |
45 | 40 | ||
46 | obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o | 41 | obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o |
47 | obj-$(CONFIG_S3C2412_IOTIMING) += iotiming-s3c2412.o | 42 | obj-$(CONFIG_S3C2412_IOTIMING) += iotiming-s3c2412.o |
48 | 43 | ||
49 | obj-$(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 | |||
32 | static 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 | |||
100 | static 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 | |||
106 | static 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 | |||
113 | static 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 | |||
131 | static 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) | ||
140 | static struct subsys_interface s3c2410_dma_interface = { | ||
141 | .name = "s3c2410_dma", | ||
142 | .subsys = &s3c2410_subsys, | ||
143 | .add_dev = s3c2410_dma_add, | ||
144 | }; | ||
145 | |||
146 | static int __init s3c2410_dma_drvinit(void) | ||
147 | { | ||
148 | return subsys_interface_register(&s3c2410_dma_interface); | ||
149 | } | ||
150 | |||
151 | arch_initcall(s3c2410_dma_drvinit); | ||
152 | |||
153 | static struct subsys_interface s3c2410a_dma_interface = { | ||
154 | .name = "s3c2410a_dma", | ||
155 | .subsys = &s3c2410a_subsys, | ||
156 | .add_dev = s3c2410_dma_add, | ||
157 | }; | ||
158 | |||
159 | static int __init s3c2410a_dma_drvinit(void) | ||
160 | { | ||
161 | return subsys_interface_register(&s3c2410a_dma_interface); | ||
162 | } | ||
163 | |||
164 | arch_initcall(s3c2410a_dma_drvinit); | ||
165 | #endif | ||
166 | |||
167 | #if defined(CONFIG_CPU_S3C2442) | ||
168 | /* S3C2442 DMA contains the same selection table as the S3C2410 */ | ||
169 | static struct subsys_interface s3c2442_dma_interface = { | ||
170 | .name = "s3c2442_dma", | ||
171 | .subsys = &s3c2442_subsys, | ||
172 | .add_dev = s3c2410_dma_add, | ||
173 | }; | ||
174 | |||
175 | static int __init s3c2442_dma_drvinit(void) | ||
176 | { | ||
177 | return subsys_interface_register(&s3c2442_dma_interface); | ||
178 | } | ||
179 | |||
180 | arch_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 | |||
34 | static 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 | |||
117 | static 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 | |||
125 | static 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 | |||
132 | static 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 | |||
139 | static struct subsys_interface s3c2412_dma_interface = { | ||
140 | .name = "s3c2412_dma", | ||
141 | .subsys = &s3c2412_subsys, | ||
142 | .add_dev = s3c2412_dma_add, | ||
143 | }; | ||
144 | |||
145 | static int __init s3c2412_dma_init(void) | ||
146 | { | ||
147 | return subsys_interface_register(&s3c2412_dma_interface); | ||
148 | } | ||
149 | |||
150 | arch_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 | |||
32 | static 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 | |||
117 | static 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 | |||
123 | static 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 | |||
130 | static 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 | |||
173 | static 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 | |||
181 | static struct subsys_interface s3c2440_dma_interface = { | ||
182 | .name = "s3c2440_dma", | ||
183 | .subsys = &s3c2440_subsys, | ||
184 | .add_dev = s3c2440_dma_add, | ||
185 | }; | ||
186 | |||
187 | static int __init s3c2440_dma_init(void) | ||
188 | { | ||
189 | return subsys_interface_register(&s3c2440_dma_interface); | ||
190 | } | ||
191 | |||
192 | arch_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 | |||
41 | static 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 | |||
128 | static 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 | |||
136 | static 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 | |||
143 | static 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 */ | ||
152 | static struct subsys_interface s3c2416_dma_interface = { | ||
153 | .name = "s3c2416_dma", | ||
154 | .subsys = &s3c2416_subsys, | ||
155 | .add_dev = s3c2443_dma_add, | ||
156 | }; | ||
157 | |||
158 | static int __init s3c2416_dma_init(void) | ||
159 | { | ||
160 | return subsys_interface_register(&s3c2416_dma_interface); | ||
161 | } | ||
162 | |||
163 | arch_initcall(s3c2416_dma_init); | ||
164 | #endif | ||
165 | |||
166 | #ifdef CONFIG_CPU_S3C2443 | ||
167 | static struct subsys_interface s3c2443_dma_interface = { | ||
168 | .name = "s3c2443_dma", | ||
169 | .subsys = &s3c2443_subsys, | ||
170 | .add_dev = s3c2443_dma_add, | ||
171 | }; | ||
172 | |||
173 | static int __init s3c2443_dma_init(void) | ||
174 | { | ||
175 | return subsys_interface_register(&s3c2443_dma_interface); | ||
176 | } | ||
177 | |||
178 | arch_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 */ | ||
38 | static void __iomem *dma_base; | ||
39 | static struct kmem_cache *dma_kmem; | ||
40 | |||
41 | static int dma_channels; | ||
42 | |||
43 | static 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 | ||
57 | static inline void | ||
58 | dma_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 | |||
69 | struct 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 | |||
84 | static void | ||
85 | dmadbg_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 | |||
94 | static void | ||
95 | dmadbg_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 | |||
104 | static void | ||
105 | dmadbg_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 | |||
118 | static void | ||
119 | dmadbg_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 | |||
139 | static void | ||
140 | s3c2410_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 | |||
158 | static int | ||
159 | s3c2410_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 | |||
203 | static inline int | ||
204 | s3c2410_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 | |||
277 | static void | ||
278 | s3c2410_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 | |||
291 | static inline void | ||
292 | s3c2410_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 | |||
310 | static 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 | |||
405 | static int | ||
406 | s3c2410_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 | |||
432 | int 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 | |||
515 | EXPORT_SYMBOL(s3c2410_dma_enqueue); | ||
516 | |||
517 | static inline void | ||
518 | s3c2410_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 | |||
537 | static inline void | ||
538 | s3c2410_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 | |||
578 | static irqreturn_t | ||
579 | s3c2410_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 | |||
707 | static 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 | |||
714 | int 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 | |||
772 | EXPORT_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 | |||
785 | int 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 | |||
826 | EXPORT_SYMBOL(s3c2410_dma_free); | ||
827 | |||
828 | static 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 | |||
862 | static 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 | |||
883 | static 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 | |||
939 | static 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 | |||
975 | int | ||
976 | s3c2410_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 | |||
1008 | EXPORT_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 | |||
1023 | int 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 | |||
1089 | EXPORT_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 | |||
1102 | int 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 | |||
1165 | EXPORT_SYMBOL(s3c2410_dma_devconfig); | ||
1166 | |||
1167 | /* s3c2410_dma_getposition | ||
1168 | * | ||
1169 | * returns the current transfer points for the dma source and destination | ||
1170 | */ | ||
1171 | |||
1172 | int 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 | |||
1188 | EXPORT_SYMBOL(s3c2410_dma_getposition); | ||
1189 | |||
1190 | /* system core operations */ | ||
1191 | |||
1192 | #ifdef CONFIG_PM | ||
1193 | |||
1194 | static 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 | |||
1212 | static 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 | |||
1223 | static 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 | |||
1243 | static 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 | |||
1257 | struct syscore_ops dma_syscore_ops = { | ||
1258 | .suspend = s3c2410_dma_suspend, | ||
1259 | .resume = s3c2410_dma_resume, | ||
1260 | }; | ||
1261 | |||
1262 | /* kmem cache implementation */ | ||
1263 | |||
1264 | static void s3c2410_dma_cache_ctor(void *p) | ||
1265 | { | ||
1266 | memset(p, 0, sizeof(struct s3c2410_dma_buf)); | ||
1267 | } | ||
1268 | |||
1269 | /* initialisation code */ | ||
1270 | |||
1271 | static int __init s3c24xx_dma_syscore_init(void) | ||
1272 | { | ||
1273 | register_syscore_ops(&dma_syscore_ops); | ||
1274 | |||
1275 | return 0; | ||
1276 | } | ||
1277 | |||
1278 | late_initcall(s3c24xx_dma_syscore_init); | ||
1279 | |||
1280 | int __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 | |||
1339 | int __init s3c2410_dma_init(void) | ||
1340 | { | ||
1341 | return s3c24xx_dma_init(4, IRQ_DMA0, 0x40); | ||
1342 | } | ||
1343 | |||
1344 | static inline int is_channel_valid(unsigned int channel) | ||
1345 | { | ||
1346 | return (channel & DMA_CH_VALID); | ||
1347 | } | ||
1348 | |||
1349 | static 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 | |||
1362 | static 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 | |||
1425 | static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch) | ||
1426 | { | ||
1427 | return 0; | ||
1428 | } | ||
1429 | |||
1430 | int __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 | |||
1450 | int __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 | ||
57 | static inline bool samsung_dma_has_circular(void) | ||
58 | { | ||
59 | return false; | ||
60 | } | ||
61 | |||
62 | static 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 | |||
80 | enum 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 | |||
114 | enum 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 | |||
132 | struct s3c2410_dma_buf; | ||
133 | |||
134 | /* s3c2410_dma_buf | ||
135 | * | ||
136 | * internally used buffer structure to describe a queued or running | ||
137 | * buffer. | ||
138 | */ | ||
139 | |||
140 | struct 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 | |||
151 | struct 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 | |||
159 | struct s3c2410_dma_map; | ||
160 | |||
161 | /* struct s3c2410_dma_chan | ||
162 | * | ||
163 | * full state information for each DMA channel | ||
164 | */ | ||
165 | |||
166 | struct 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 | |||
212 | typedef unsigned long dma_device_t; | ||
213 | |||
214 | #endif /* __ASM_ARCH_DMA_H */ | 55 | #endif /* __ASM_ARCH_DMA_H */ |