Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  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
 23static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
 24{
 25	return cd->min_signal;
 26}
 27
 28static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
 29{
 30}
 31
 32/*
 33 * DMA0
 34 */
 35
 36static 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
120static const struct dma_slave_map s3c64xx_dma0_slave_map[] = {
121	{ "s3c6400-uart.0", "tx", &s3c64xx_dma0_info[0] },
122	{ "s3c6400-uart.0", "rx", &s3c64xx_dma0_info[1] },
123	{ "s3c6400-uart.1", "tx", &s3c64xx_dma0_info[2] },
124	{ "s3c6400-uart.1", "rx", &s3c64xx_dma0_info[3] },
125	{ "s3c6400-uart.2", "tx", &s3c64xx_dma0_info[4] },
126	{ "s3c6400-uart.2", "rx", &s3c64xx_dma0_info[5] },
127	{ "s3c6400-uart.3", "tx", &s3c64xx_dma0_info[6] },
128	{ "s3c6400-uart.3", "rx", &s3c64xx_dma0_info[7] },
129	{ "samsung-pcm.0", "tx", &s3c64xx_dma0_info[8] },
130	{ "samsung-pcm.0", "rx", &s3c64xx_dma0_info[9] },
131	{ "samsung-i2s.0", "tx", &s3c64xx_dma0_info[10] },
132	{ "samsung-i2s.0", "rx", &s3c64xx_dma0_info[11] },
133	{ "s3c6410-spi.0", "tx", &s3c64xx_dma0_info[12] },
134	{ "s3c6410-spi.0", "rx", &s3c64xx_dma0_info[13] },
135	{ "samsung-i2s.2", "tx", &s3c64xx_dma0_info[14] },
136	{ "samsung-i2s.2", "rx", &s3c64xx_dma0_info[15] },
137};
138
139struct pl08x_platform_data s3c64xx_dma0_plat_data = {
140	.memcpy_channel = {
141		.bus_id = "memcpy",
142		.cctl_memcpy =
143			(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
144			PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
145			PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
146			PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
147			PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
148			PL080_CONTROL_PROT_SYS),
149	},
150	.lli_buses = PL08X_AHB1,
151	.mem_buses = PL08X_AHB1,
152	.get_xfer_signal = pl08x_get_xfer_signal,
153	.put_xfer_signal = pl08x_put_xfer_signal,
154	.slave_channels = s3c64xx_dma0_info,
155	.num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
156	.slave_map = s3c64xx_dma0_slave_map,
157	.slave_map_len = ARRAY_SIZE(s3c64xx_dma0_slave_map),
158};
159
160static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
161			0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
162
163/*
164 * DMA1
165 */
166
167static struct pl08x_channel_data s3c64xx_dma1_info[] = {
168	{
169		.bus_id = "pcm1_tx",
170		.min_signal = 0,
171		.max_signal = 0,
172		.periph_buses = PL08X_AHB2,
173	}, {
174		.bus_id = "pcm1_rx",
175		.min_signal = 1,
176		.max_signal = 1,
177		.periph_buses = PL08X_AHB2,
178	}, {
179		.bus_id = "i2s1_tx",
180		.min_signal = 2,
181		.max_signal = 2,
182		.periph_buses = PL08X_AHB2,
183	}, {
184		.bus_id = "i2s1_rx",
185		.min_signal = 3,
186		.max_signal = 3,
187		.periph_buses = PL08X_AHB2,
188	}, {
189		.bus_id = "spi1_tx",
190		.min_signal = 4,
191		.max_signal = 4,
192		.periph_buses = PL08X_AHB2,
193	}, {
194		.bus_id = "spi1_rx",
195		.min_signal = 5,
196		.max_signal = 5,
197		.periph_buses = PL08X_AHB2,
198	}, {
199		.bus_id = "ac97_out",
200		.min_signal = 6,
201		.max_signal = 6,
202		.periph_buses = PL08X_AHB2,
203	}, {
204		.bus_id = "ac97_in",
205		.min_signal = 7,
206		.max_signal = 7,
207		.periph_buses = PL08X_AHB2,
208	}, {
209		.bus_id = "ac97_mic",
210		.min_signal = 8,
211		.max_signal = 8,
212		.periph_buses = PL08X_AHB2,
213	}, {
214		.bus_id = "pwm",
215		.min_signal = 9,
216		.max_signal = 9,
217		.periph_buses = PL08X_AHB2,
218	}, {
219		.bus_id = "irda",
220		.min_signal = 10,
221		.max_signal = 10,
222		.periph_buses = PL08X_AHB2,
223	}, {
224		.bus_id = "external",
225		.min_signal = 11,
226		.max_signal = 11,
227		.periph_buses = PL08X_AHB2,
228	},
229};
230
231static const struct dma_slave_map s3c64xx_dma1_slave_map[] = {
232	{ "samsung-pcm.1", "tx", &s3c64xx_dma1_info[0] },
233	{ "samsung-pcm.1", "rx", &s3c64xx_dma1_info[1] },
234	{ "samsung-i2s.1", "tx", &s3c64xx_dma1_info[2] },
235	{ "samsung-i2s.1", "rx", &s3c64xx_dma1_info[3] },
236	{ "s3c6410-spi.1", "tx", &s3c64xx_dma1_info[4] },
237	{ "s3c6410-spi.1", "rx", &s3c64xx_dma1_info[5] },
238};
239
240struct pl08x_platform_data s3c64xx_dma1_plat_data = {
241	.memcpy_channel = {
242		.bus_id = "memcpy",
243		.cctl_memcpy =
244			(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
245			PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
246			PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
247			PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
248			PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
249			PL080_CONTROL_PROT_SYS),
250	},
251	.lli_buses = PL08X_AHB1,
252	.mem_buses = PL08X_AHB1,
253	.get_xfer_signal = pl08x_get_xfer_signal,
254	.put_xfer_signal = pl08x_put_xfer_signal,
255	.slave_channels = s3c64xx_dma1_info,
256	.num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
257	.slave_map = s3c64xx_dma1_slave_map,
258	.slave_map_len = ARRAY_SIZE(s3c64xx_dma1_slave_map),
259};
260
261static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
262			0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
263
264static int __init s3c64xx_pl080_init(void)
265{
266	if (!soc_is_s3c64xx())
267		return 0;
268
269	/* Set all DMA configuration to be DMA, not SDMA */
270	writel(0xffffff, S3C64XX_SDMA_SEL);
271
272	if (of_have_populated_dt())
273		return 0;
274
275	amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
276	amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
277
278	return 0;
279}
280arch_initcall(s3c64xx_pl080_init);