162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// Samsung's S3C64XX generic DMA support using amba-pl08x driver.
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/kernel.h>
862306a36Sopenharmony_ci#include <linux/amba/bus.h>
962306a36Sopenharmony_ci#include <linux/amba/pl080.h>
1062306a36Sopenharmony_ci#include <linux/amba/pl08x.h>
1162306a36Sopenharmony_ci#include <linux/of.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "cpu.h"
1462306a36Sopenharmony_ci#include "irqs.h"
1562306a36Sopenharmony_ci#include "map.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "regs-sys-s3c64xx.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	return cd->min_signal;
2262306a36Sopenharmony_ci}
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistatic void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci}
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * DMA0
3062306a36Sopenharmony_ci */
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic struct pl08x_channel_data s3c64xx_dma0_info[] = {
3362306a36Sopenharmony_ci	{
3462306a36Sopenharmony_ci		.bus_id = "uart0_tx",
3562306a36Sopenharmony_ci		.min_signal = 0,
3662306a36Sopenharmony_ci		.max_signal = 0,
3762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
3862306a36Sopenharmony_ci	}, {
3962306a36Sopenharmony_ci		.bus_id = "uart0_rx",
4062306a36Sopenharmony_ci		.min_signal = 1,
4162306a36Sopenharmony_ci		.max_signal = 1,
4262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
4362306a36Sopenharmony_ci	}, {
4462306a36Sopenharmony_ci		.bus_id = "uart1_tx",
4562306a36Sopenharmony_ci		.min_signal = 2,
4662306a36Sopenharmony_ci		.max_signal = 2,
4762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
4862306a36Sopenharmony_ci	}, {
4962306a36Sopenharmony_ci		.bus_id = "uart1_rx",
5062306a36Sopenharmony_ci		.min_signal = 3,
5162306a36Sopenharmony_ci		.max_signal = 3,
5262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
5362306a36Sopenharmony_ci	}, {
5462306a36Sopenharmony_ci		.bus_id = "uart2_tx",
5562306a36Sopenharmony_ci		.min_signal = 4,
5662306a36Sopenharmony_ci		.max_signal = 4,
5762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
5862306a36Sopenharmony_ci	}, {
5962306a36Sopenharmony_ci		.bus_id = "uart2_rx",
6062306a36Sopenharmony_ci		.min_signal = 5,
6162306a36Sopenharmony_ci		.max_signal = 5,
6262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
6362306a36Sopenharmony_ci	}, {
6462306a36Sopenharmony_ci		.bus_id = "uart3_tx",
6562306a36Sopenharmony_ci		.min_signal = 6,
6662306a36Sopenharmony_ci		.max_signal = 6,
6762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
6862306a36Sopenharmony_ci	}, {
6962306a36Sopenharmony_ci		.bus_id = "uart3_rx",
7062306a36Sopenharmony_ci		.min_signal = 7,
7162306a36Sopenharmony_ci		.max_signal = 7,
7262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
7362306a36Sopenharmony_ci	}, {
7462306a36Sopenharmony_ci		.bus_id = "pcm0_tx",
7562306a36Sopenharmony_ci		.min_signal = 8,
7662306a36Sopenharmony_ci		.max_signal = 8,
7762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
7862306a36Sopenharmony_ci	}, {
7962306a36Sopenharmony_ci		.bus_id = "pcm0_rx",
8062306a36Sopenharmony_ci		.min_signal = 9,
8162306a36Sopenharmony_ci		.max_signal = 9,
8262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
8362306a36Sopenharmony_ci	}, {
8462306a36Sopenharmony_ci		.bus_id = "i2s0_tx",
8562306a36Sopenharmony_ci		.min_signal = 10,
8662306a36Sopenharmony_ci		.max_signal = 10,
8762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
8862306a36Sopenharmony_ci	}, {
8962306a36Sopenharmony_ci		.bus_id = "i2s0_rx",
9062306a36Sopenharmony_ci		.min_signal = 11,
9162306a36Sopenharmony_ci		.max_signal = 11,
9262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
9362306a36Sopenharmony_ci	}, {
9462306a36Sopenharmony_ci		.bus_id = "spi0_tx",
9562306a36Sopenharmony_ci		.min_signal = 12,
9662306a36Sopenharmony_ci		.max_signal = 12,
9762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
9862306a36Sopenharmony_ci	}, {
9962306a36Sopenharmony_ci		.bus_id = "spi0_rx",
10062306a36Sopenharmony_ci		.min_signal = 13,
10162306a36Sopenharmony_ci		.max_signal = 13,
10262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
10362306a36Sopenharmony_ci	}, {
10462306a36Sopenharmony_ci		.bus_id = "i2s2_tx",
10562306a36Sopenharmony_ci		.min_signal = 14,
10662306a36Sopenharmony_ci		.max_signal = 14,
10762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
10862306a36Sopenharmony_ci	}, {
10962306a36Sopenharmony_ci		.bus_id = "i2s2_rx",
11062306a36Sopenharmony_ci		.min_signal = 15,
11162306a36Sopenharmony_ci		.max_signal = 15,
11262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci};
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic const struct dma_slave_map s3c64xx_dma0_slave_map[] = {
11762306a36Sopenharmony_ci	{ "s3c6400-uart.0", "tx", &s3c64xx_dma0_info[0] },
11862306a36Sopenharmony_ci	{ "s3c6400-uart.0", "rx", &s3c64xx_dma0_info[1] },
11962306a36Sopenharmony_ci	{ "s3c6400-uart.1", "tx", &s3c64xx_dma0_info[2] },
12062306a36Sopenharmony_ci	{ "s3c6400-uart.1", "rx", &s3c64xx_dma0_info[3] },
12162306a36Sopenharmony_ci	{ "s3c6400-uart.2", "tx", &s3c64xx_dma0_info[4] },
12262306a36Sopenharmony_ci	{ "s3c6400-uart.2", "rx", &s3c64xx_dma0_info[5] },
12362306a36Sopenharmony_ci	{ "s3c6400-uart.3", "tx", &s3c64xx_dma0_info[6] },
12462306a36Sopenharmony_ci	{ "s3c6400-uart.3", "rx", &s3c64xx_dma0_info[7] },
12562306a36Sopenharmony_ci	{ "samsung-pcm.0", "tx", &s3c64xx_dma0_info[8] },
12662306a36Sopenharmony_ci	{ "samsung-pcm.0", "rx", &s3c64xx_dma0_info[9] },
12762306a36Sopenharmony_ci	{ "samsung-i2s.0", "tx", &s3c64xx_dma0_info[10] },
12862306a36Sopenharmony_ci	{ "samsung-i2s.0", "rx", &s3c64xx_dma0_info[11] },
12962306a36Sopenharmony_ci	{ "s3c6410-spi.0", "tx", &s3c64xx_dma0_info[12] },
13062306a36Sopenharmony_ci	{ "s3c6410-spi.0", "rx", &s3c64xx_dma0_info[13] },
13162306a36Sopenharmony_ci	{ "samsung-i2s.2", "tx", &s3c64xx_dma0_info[14] },
13262306a36Sopenharmony_ci	{ "samsung-i2s.2", "rx", &s3c64xx_dma0_info[15] },
13362306a36Sopenharmony_ci};
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistruct pl08x_platform_data s3c64xx_dma0_plat_data = {
13662306a36Sopenharmony_ci	.memcpy_burst_size = PL08X_BURST_SZ_4,
13762306a36Sopenharmony_ci	.memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
13862306a36Sopenharmony_ci	.memcpy_prot_buff = true,
13962306a36Sopenharmony_ci	.memcpy_prot_cache = true,
14062306a36Sopenharmony_ci	.lli_buses = PL08X_AHB1,
14162306a36Sopenharmony_ci	.mem_buses = PL08X_AHB1,
14262306a36Sopenharmony_ci	.get_xfer_signal = pl08x_get_xfer_signal,
14362306a36Sopenharmony_ci	.put_xfer_signal = pl08x_put_xfer_signal,
14462306a36Sopenharmony_ci	.slave_channels = s3c64xx_dma0_info,
14562306a36Sopenharmony_ci	.num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
14662306a36Sopenharmony_ci	.slave_map = s3c64xx_dma0_slave_map,
14762306a36Sopenharmony_ci	.slave_map_len = ARRAY_SIZE(s3c64xx_dma0_slave_map),
14862306a36Sopenharmony_ci};
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cistatic AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
15162306a36Sopenharmony_ci			0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci/*
15462306a36Sopenharmony_ci * DMA1
15562306a36Sopenharmony_ci */
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic struct pl08x_channel_data s3c64xx_dma1_info[] = {
15862306a36Sopenharmony_ci	{
15962306a36Sopenharmony_ci		.bus_id = "pcm1_tx",
16062306a36Sopenharmony_ci		.min_signal = 0,
16162306a36Sopenharmony_ci		.max_signal = 0,
16262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
16362306a36Sopenharmony_ci	}, {
16462306a36Sopenharmony_ci		.bus_id = "pcm1_rx",
16562306a36Sopenharmony_ci		.min_signal = 1,
16662306a36Sopenharmony_ci		.max_signal = 1,
16762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
16862306a36Sopenharmony_ci	}, {
16962306a36Sopenharmony_ci		.bus_id = "i2s1_tx",
17062306a36Sopenharmony_ci		.min_signal = 2,
17162306a36Sopenharmony_ci		.max_signal = 2,
17262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
17362306a36Sopenharmony_ci	}, {
17462306a36Sopenharmony_ci		.bus_id = "i2s1_rx",
17562306a36Sopenharmony_ci		.min_signal = 3,
17662306a36Sopenharmony_ci		.max_signal = 3,
17762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
17862306a36Sopenharmony_ci	}, {
17962306a36Sopenharmony_ci		.bus_id = "spi1_tx",
18062306a36Sopenharmony_ci		.min_signal = 4,
18162306a36Sopenharmony_ci		.max_signal = 4,
18262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
18362306a36Sopenharmony_ci	}, {
18462306a36Sopenharmony_ci		.bus_id = "spi1_rx",
18562306a36Sopenharmony_ci		.min_signal = 5,
18662306a36Sopenharmony_ci		.max_signal = 5,
18762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
18862306a36Sopenharmony_ci	}, {
18962306a36Sopenharmony_ci		.bus_id = "ac97_out",
19062306a36Sopenharmony_ci		.min_signal = 6,
19162306a36Sopenharmony_ci		.max_signal = 6,
19262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
19362306a36Sopenharmony_ci	}, {
19462306a36Sopenharmony_ci		.bus_id = "ac97_in",
19562306a36Sopenharmony_ci		.min_signal = 7,
19662306a36Sopenharmony_ci		.max_signal = 7,
19762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
19862306a36Sopenharmony_ci	}, {
19962306a36Sopenharmony_ci		.bus_id = "ac97_mic",
20062306a36Sopenharmony_ci		.min_signal = 8,
20162306a36Sopenharmony_ci		.max_signal = 8,
20262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
20362306a36Sopenharmony_ci	}, {
20462306a36Sopenharmony_ci		.bus_id = "pwm",
20562306a36Sopenharmony_ci		.min_signal = 9,
20662306a36Sopenharmony_ci		.max_signal = 9,
20762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
20862306a36Sopenharmony_ci	}, {
20962306a36Sopenharmony_ci		.bus_id = "irda",
21062306a36Sopenharmony_ci		.min_signal = 10,
21162306a36Sopenharmony_ci		.max_signal = 10,
21262306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
21362306a36Sopenharmony_ci	}, {
21462306a36Sopenharmony_ci		.bus_id = "external",
21562306a36Sopenharmony_ci		.min_signal = 11,
21662306a36Sopenharmony_ci		.max_signal = 11,
21762306a36Sopenharmony_ci		.periph_buses = PL08X_AHB2,
21862306a36Sopenharmony_ci	},
21962306a36Sopenharmony_ci};
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic const struct dma_slave_map s3c64xx_dma1_slave_map[] = {
22262306a36Sopenharmony_ci	{ "samsung-pcm.1", "tx", &s3c64xx_dma1_info[0] },
22362306a36Sopenharmony_ci	{ "samsung-pcm.1", "rx", &s3c64xx_dma1_info[1] },
22462306a36Sopenharmony_ci	{ "samsung-i2s.1", "tx", &s3c64xx_dma1_info[2] },
22562306a36Sopenharmony_ci	{ "samsung-i2s.1", "rx", &s3c64xx_dma1_info[3] },
22662306a36Sopenharmony_ci	{ "s3c6410-spi.1", "tx", &s3c64xx_dma1_info[4] },
22762306a36Sopenharmony_ci	{ "s3c6410-spi.1", "rx", &s3c64xx_dma1_info[5] },
22862306a36Sopenharmony_ci};
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistruct pl08x_platform_data s3c64xx_dma1_plat_data = {
23162306a36Sopenharmony_ci	.memcpy_burst_size = PL08X_BURST_SZ_4,
23262306a36Sopenharmony_ci	.memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
23362306a36Sopenharmony_ci	.memcpy_prot_buff = true,
23462306a36Sopenharmony_ci	.memcpy_prot_cache = true,
23562306a36Sopenharmony_ci	.lli_buses = PL08X_AHB1,
23662306a36Sopenharmony_ci	.mem_buses = PL08X_AHB1,
23762306a36Sopenharmony_ci	.get_xfer_signal = pl08x_get_xfer_signal,
23862306a36Sopenharmony_ci	.put_xfer_signal = pl08x_put_xfer_signal,
23962306a36Sopenharmony_ci	.slave_channels = s3c64xx_dma1_info,
24062306a36Sopenharmony_ci	.num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
24162306a36Sopenharmony_ci	.slave_map = s3c64xx_dma1_slave_map,
24262306a36Sopenharmony_ci	.slave_map_len = ARRAY_SIZE(s3c64xx_dma1_slave_map),
24362306a36Sopenharmony_ci};
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_cistatic AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
24662306a36Sopenharmony_ci			0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic int __init s3c64xx_pl080_init(void)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	if (!soc_is_s3c64xx())
25162306a36Sopenharmony_ci		return 0;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	/* Set all DMA configuration to be DMA, not SDMA */
25462306a36Sopenharmony_ci	writel(0xffffff, S3C64XX_SDMA_SEL);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	if (of_have_populated_dt())
25762306a36Sopenharmony_ci		return 0;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
26062306a36Sopenharmony_ci	amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	return 0;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ciarch_initcall(s3c64xx_pl080_init);
265