• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Samsung's S3C64XX generic DMA support using amba-pl08x driver.
3  *
4  * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 
11 #include <linux/kernel.h>
12 #include <linux/amba/bus.h>
13 #include <linux/amba/pl080.h>
14 #include <linux/amba/pl08x.h>
15 #include <linux/of.h>
16 
17 #include <plat/cpu.h>
18 #include <mach/irqs.h>
19 #include <mach/map.h>
20 
21 #include "regs-sys.h"
22 
pl08x_get_xfer_signal(const struct pl08x_channel_data * cd)23 static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
24 {
25 	return cd->min_signal;
26 }
27 
pl08x_put_xfer_signal(const struct pl08x_channel_data * cd,int ch)28 static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
29 {
30 }
31 
32 /*
33  * DMA0
34  */
35 
36 static struct pl08x_channel_data s3c64xx_dma0_info[] = {
37 	{
38 		.bus_id = "uart0_tx",
39 		.min_signal = 0,
40 		.max_signal = 0,
41 		.periph_buses = PL08X_AHB2,
42 	}, {
43 		.bus_id = "uart0_rx",
44 		.min_signal = 1,
45 		.max_signal = 1,
46 		.periph_buses = PL08X_AHB2,
47 	}, {
48 		.bus_id = "uart1_tx",
49 		.min_signal = 2,
50 		.max_signal = 2,
51 		.periph_buses = PL08X_AHB2,
52 	}, {
53 		.bus_id = "uart1_rx",
54 		.min_signal = 3,
55 		.max_signal = 3,
56 		.periph_buses = PL08X_AHB2,
57 	}, {
58 		.bus_id = "uart2_tx",
59 		.min_signal = 4,
60 		.max_signal = 4,
61 		.periph_buses = PL08X_AHB2,
62 	}, {
63 		.bus_id = "uart2_rx",
64 		.min_signal = 5,
65 		.max_signal = 5,
66 		.periph_buses = PL08X_AHB2,
67 	}, {
68 		.bus_id = "uart3_tx",
69 		.min_signal = 6,
70 		.max_signal = 6,
71 		.periph_buses = PL08X_AHB2,
72 	}, {
73 		.bus_id = "uart3_rx",
74 		.min_signal = 7,
75 		.max_signal = 7,
76 		.periph_buses = PL08X_AHB2,
77 	}, {
78 		.bus_id = "pcm0_tx",
79 		.min_signal = 8,
80 		.max_signal = 8,
81 		.periph_buses = PL08X_AHB2,
82 	}, {
83 		.bus_id = "pcm0_rx",
84 		.min_signal = 9,
85 		.max_signal = 9,
86 		.periph_buses = PL08X_AHB2,
87 	}, {
88 		.bus_id = "i2s0_tx",
89 		.min_signal = 10,
90 		.max_signal = 10,
91 		.periph_buses = PL08X_AHB2,
92 	}, {
93 		.bus_id = "i2s0_rx",
94 		.min_signal = 11,
95 		.max_signal = 11,
96 		.periph_buses = PL08X_AHB2,
97 	}, {
98 		.bus_id = "spi0_tx",
99 		.min_signal = 12,
100 		.max_signal = 12,
101 		.periph_buses = PL08X_AHB2,
102 	}, {
103 		.bus_id = "spi0_rx",
104 		.min_signal = 13,
105 		.max_signal = 13,
106 		.periph_buses = PL08X_AHB2,
107 	}, {
108 		.bus_id = "i2s2_tx",
109 		.min_signal = 14,
110 		.max_signal = 14,
111 		.periph_buses = PL08X_AHB2,
112 	}, {
113 		.bus_id = "i2s2_rx",
114 		.min_signal = 15,
115 		.max_signal = 15,
116 		.periph_buses = PL08X_AHB2,
117 	}
118 };
119 
120 struct pl08x_platform_data s3c64xx_dma0_plat_data = {
121 	.memcpy_channel = {
122 		.bus_id = "memcpy",
123 		.cctl_memcpy =
124 			(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
125 			PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
126 			PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
127 			PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
128 			PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
129 			PL080_CONTROL_PROT_SYS),
130 	},
131 	.lli_buses = PL08X_AHB1,
132 	.mem_buses = PL08X_AHB1,
133 	.get_xfer_signal = pl08x_get_xfer_signal,
134 	.put_xfer_signal = pl08x_put_xfer_signal,
135 	.slave_channels = s3c64xx_dma0_info,
136 	.num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
137 };
138 
139 static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
140 			0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
141 
142 /*
143  * DMA1
144  */
145 
146 static struct pl08x_channel_data s3c64xx_dma1_info[] = {
147 	{
148 		.bus_id = "pcm1_tx",
149 		.min_signal = 0,
150 		.max_signal = 0,
151 		.periph_buses = PL08X_AHB2,
152 	}, {
153 		.bus_id = "pcm1_rx",
154 		.min_signal = 1,
155 		.max_signal = 1,
156 		.periph_buses = PL08X_AHB2,
157 	}, {
158 		.bus_id = "i2s1_tx",
159 		.min_signal = 2,
160 		.max_signal = 2,
161 		.periph_buses = PL08X_AHB2,
162 	}, {
163 		.bus_id = "i2s1_rx",
164 		.min_signal = 3,
165 		.max_signal = 3,
166 		.periph_buses = PL08X_AHB2,
167 	}, {
168 		.bus_id = "spi1_tx",
169 		.min_signal = 4,
170 		.max_signal = 4,
171 		.periph_buses = PL08X_AHB2,
172 	}, {
173 		.bus_id = "spi1_rx",
174 		.min_signal = 5,
175 		.max_signal = 5,
176 		.periph_buses = PL08X_AHB2,
177 	}, {
178 		.bus_id = "ac97_out",
179 		.min_signal = 6,
180 		.max_signal = 6,
181 		.periph_buses = PL08X_AHB2,
182 	}, {
183 		.bus_id = "ac97_in",
184 		.min_signal = 7,
185 		.max_signal = 7,
186 		.periph_buses = PL08X_AHB2,
187 	}, {
188 		.bus_id = "ac97_mic",
189 		.min_signal = 8,
190 		.max_signal = 8,
191 		.periph_buses = PL08X_AHB2,
192 	}, {
193 		.bus_id = "pwm",
194 		.min_signal = 9,
195 		.max_signal = 9,
196 		.periph_buses = PL08X_AHB2,
197 	}, {
198 		.bus_id = "irda",
199 		.min_signal = 10,
200 		.max_signal = 10,
201 		.periph_buses = PL08X_AHB2,
202 	}, {
203 		.bus_id = "external",
204 		.min_signal = 11,
205 		.max_signal = 11,
206 		.periph_buses = PL08X_AHB2,
207 	},
208 };
209 
210 struct pl08x_platform_data s3c64xx_dma1_plat_data = {
211 	.memcpy_channel = {
212 		.bus_id = "memcpy",
213 		.cctl_memcpy =
214 			(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
215 			PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
216 			PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
217 			PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
218 			PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
219 			PL080_CONTROL_PROT_SYS),
220 	},
221 	.lli_buses = PL08X_AHB1,
222 	.mem_buses = PL08X_AHB1,
223 	.get_xfer_signal = pl08x_get_xfer_signal,
224 	.put_xfer_signal = pl08x_put_xfer_signal,
225 	.slave_channels = s3c64xx_dma1_info,
226 	.num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
227 };
228 
229 static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
230 			0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
231 
s3c64xx_pl080_init(void)232 static int __init s3c64xx_pl080_init(void)
233 {
234 	if (!soc_is_s3c64xx())
235 		return 0;
236 
237 	/* Set all DMA configuration to be DMA, not SDMA */
238 	writel(0xffffff, S3C64XX_SDMA_SEL);
239 
240 	if (of_have_populated_dt())
241 		return 0;
242 
243 	amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
244 	amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
245 
246 	return 0;
247 }
248 arch_initcall(s3c64xx_pl080_init);
249