171b9114dSArnd Bergmann // SPDX-License-Identifier: GPL-2.0 271b9114dSArnd Bergmann // 371b9114dSArnd Bergmann // Samsung's S3C64XX generic DMA support using amba-pl08x driver. 471b9114dSArnd Bergmann // 571b9114dSArnd Bergmann // Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com> 671b9114dSArnd Bergmann 771b9114dSArnd Bergmann #include <linux/kernel.h> 871b9114dSArnd Bergmann #include <linux/amba/bus.h> 971b9114dSArnd Bergmann #include <linux/amba/pl080.h> 1071b9114dSArnd Bergmann #include <linux/amba/pl08x.h> 1171b9114dSArnd Bergmann #include <linux/of.h> 1271b9114dSArnd Bergmann 13*c6ff132dSArnd Bergmann #include "cpu.h" 1471b9114dSArnd Bergmann #include <mach/irqs.h> 15*c6ff132dSArnd Bergmann #include "map.h" 1671b9114dSArnd Bergmann 1771b9114dSArnd Bergmann #include "regs-sys-s3c64xx.h" 1871b9114dSArnd Bergmann 1971b9114dSArnd Bergmann static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd) 2071b9114dSArnd Bergmann { 2171b9114dSArnd Bergmann return cd->min_signal; 2271b9114dSArnd Bergmann } 2371b9114dSArnd Bergmann 2471b9114dSArnd Bergmann static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch) 2571b9114dSArnd Bergmann { 2671b9114dSArnd Bergmann } 2771b9114dSArnd Bergmann 2871b9114dSArnd Bergmann /* 2971b9114dSArnd Bergmann * DMA0 3071b9114dSArnd Bergmann */ 3171b9114dSArnd Bergmann 3271b9114dSArnd Bergmann static struct pl08x_channel_data s3c64xx_dma0_info[] = { 3371b9114dSArnd Bergmann { 3471b9114dSArnd Bergmann .bus_id = "uart0_tx", 3571b9114dSArnd Bergmann .min_signal = 0, 3671b9114dSArnd Bergmann .max_signal = 0, 3771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 3871b9114dSArnd Bergmann }, { 3971b9114dSArnd Bergmann .bus_id = "uart0_rx", 4071b9114dSArnd Bergmann .min_signal = 1, 4171b9114dSArnd Bergmann .max_signal = 1, 4271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 4371b9114dSArnd Bergmann }, { 4471b9114dSArnd Bergmann .bus_id = "uart1_tx", 4571b9114dSArnd Bergmann .min_signal = 2, 4671b9114dSArnd Bergmann .max_signal = 2, 4771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 4871b9114dSArnd Bergmann }, { 4971b9114dSArnd Bergmann .bus_id = "uart1_rx", 5071b9114dSArnd Bergmann .min_signal = 3, 5171b9114dSArnd Bergmann .max_signal = 3, 5271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 5371b9114dSArnd Bergmann }, { 5471b9114dSArnd Bergmann .bus_id = "uart2_tx", 5571b9114dSArnd Bergmann .min_signal = 4, 5671b9114dSArnd Bergmann .max_signal = 4, 5771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 5871b9114dSArnd Bergmann }, { 5971b9114dSArnd Bergmann .bus_id = "uart2_rx", 6071b9114dSArnd Bergmann .min_signal = 5, 6171b9114dSArnd Bergmann .max_signal = 5, 6271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 6371b9114dSArnd Bergmann }, { 6471b9114dSArnd Bergmann .bus_id = "uart3_tx", 6571b9114dSArnd Bergmann .min_signal = 6, 6671b9114dSArnd Bergmann .max_signal = 6, 6771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 6871b9114dSArnd Bergmann }, { 6971b9114dSArnd Bergmann .bus_id = "uart3_rx", 7071b9114dSArnd Bergmann .min_signal = 7, 7171b9114dSArnd Bergmann .max_signal = 7, 7271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 7371b9114dSArnd Bergmann }, { 7471b9114dSArnd Bergmann .bus_id = "pcm0_tx", 7571b9114dSArnd Bergmann .min_signal = 8, 7671b9114dSArnd Bergmann .max_signal = 8, 7771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 7871b9114dSArnd Bergmann }, { 7971b9114dSArnd Bergmann .bus_id = "pcm0_rx", 8071b9114dSArnd Bergmann .min_signal = 9, 8171b9114dSArnd Bergmann .max_signal = 9, 8271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 8371b9114dSArnd Bergmann }, { 8471b9114dSArnd Bergmann .bus_id = "i2s0_tx", 8571b9114dSArnd Bergmann .min_signal = 10, 8671b9114dSArnd Bergmann .max_signal = 10, 8771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 8871b9114dSArnd Bergmann }, { 8971b9114dSArnd Bergmann .bus_id = "i2s0_rx", 9071b9114dSArnd Bergmann .min_signal = 11, 9171b9114dSArnd Bergmann .max_signal = 11, 9271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 9371b9114dSArnd Bergmann }, { 9471b9114dSArnd Bergmann .bus_id = "spi0_tx", 9571b9114dSArnd Bergmann .min_signal = 12, 9671b9114dSArnd Bergmann .max_signal = 12, 9771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 9871b9114dSArnd Bergmann }, { 9971b9114dSArnd Bergmann .bus_id = "spi0_rx", 10071b9114dSArnd Bergmann .min_signal = 13, 10171b9114dSArnd Bergmann .max_signal = 13, 10271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 10371b9114dSArnd Bergmann }, { 10471b9114dSArnd Bergmann .bus_id = "i2s2_tx", 10571b9114dSArnd Bergmann .min_signal = 14, 10671b9114dSArnd Bergmann .max_signal = 14, 10771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 10871b9114dSArnd Bergmann }, { 10971b9114dSArnd Bergmann .bus_id = "i2s2_rx", 11071b9114dSArnd Bergmann .min_signal = 15, 11171b9114dSArnd Bergmann .max_signal = 15, 11271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 11371b9114dSArnd Bergmann } 11471b9114dSArnd Bergmann }; 11571b9114dSArnd Bergmann 11671b9114dSArnd Bergmann static const struct dma_slave_map s3c64xx_dma0_slave_map[] = { 11771b9114dSArnd Bergmann { "s3c6400-uart.0", "tx", &s3c64xx_dma0_info[0] }, 11871b9114dSArnd Bergmann { "s3c6400-uart.0", "rx", &s3c64xx_dma0_info[1] }, 11971b9114dSArnd Bergmann { "s3c6400-uart.1", "tx", &s3c64xx_dma0_info[2] }, 12071b9114dSArnd Bergmann { "s3c6400-uart.1", "rx", &s3c64xx_dma0_info[3] }, 12171b9114dSArnd Bergmann { "s3c6400-uart.2", "tx", &s3c64xx_dma0_info[4] }, 12271b9114dSArnd Bergmann { "s3c6400-uart.2", "rx", &s3c64xx_dma0_info[5] }, 12371b9114dSArnd Bergmann { "s3c6400-uart.3", "tx", &s3c64xx_dma0_info[6] }, 12471b9114dSArnd Bergmann { "s3c6400-uart.3", "rx", &s3c64xx_dma0_info[7] }, 12571b9114dSArnd Bergmann { "samsung-pcm.0", "tx", &s3c64xx_dma0_info[8] }, 12671b9114dSArnd Bergmann { "samsung-pcm.0", "rx", &s3c64xx_dma0_info[9] }, 12771b9114dSArnd Bergmann { "samsung-i2s.0", "tx", &s3c64xx_dma0_info[10] }, 12871b9114dSArnd Bergmann { "samsung-i2s.0", "rx", &s3c64xx_dma0_info[11] }, 12971b9114dSArnd Bergmann { "s3c6410-spi.0", "tx", &s3c64xx_dma0_info[12] }, 13071b9114dSArnd Bergmann { "s3c6410-spi.0", "rx", &s3c64xx_dma0_info[13] }, 13171b9114dSArnd Bergmann { "samsung-i2s.2", "tx", &s3c64xx_dma0_info[14] }, 13271b9114dSArnd Bergmann { "samsung-i2s.2", "rx", &s3c64xx_dma0_info[15] }, 13371b9114dSArnd Bergmann }; 13471b9114dSArnd Bergmann 13571b9114dSArnd Bergmann struct pl08x_platform_data s3c64xx_dma0_plat_data = { 13671b9114dSArnd Bergmann .memcpy_burst_size = PL08X_BURST_SZ_4, 13771b9114dSArnd Bergmann .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS, 13871b9114dSArnd Bergmann .memcpy_prot_buff = true, 13971b9114dSArnd Bergmann .memcpy_prot_cache = true, 14071b9114dSArnd Bergmann .lli_buses = PL08X_AHB1, 14171b9114dSArnd Bergmann .mem_buses = PL08X_AHB1, 14271b9114dSArnd Bergmann .get_xfer_signal = pl08x_get_xfer_signal, 14371b9114dSArnd Bergmann .put_xfer_signal = pl08x_put_xfer_signal, 14471b9114dSArnd Bergmann .slave_channels = s3c64xx_dma0_info, 14571b9114dSArnd Bergmann .num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info), 14671b9114dSArnd Bergmann .slave_map = s3c64xx_dma0_slave_map, 14771b9114dSArnd Bergmann .slave_map_len = ARRAY_SIZE(s3c64xx_dma0_slave_map), 14871b9114dSArnd Bergmann }; 14971b9114dSArnd Bergmann 15071b9114dSArnd Bergmann static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0, 15171b9114dSArnd Bergmann 0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data); 15271b9114dSArnd Bergmann 15371b9114dSArnd Bergmann /* 15471b9114dSArnd Bergmann * DMA1 15571b9114dSArnd Bergmann */ 15671b9114dSArnd Bergmann 15771b9114dSArnd Bergmann static struct pl08x_channel_data s3c64xx_dma1_info[] = { 15871b9114dSArnd Bergmann { 15971b9114dSArnd Bergmann .bus_id = "pcm1_tx", 16071b9114dSArnd Bergmann .min_signal = 0, 16171b9114dSArnd Bergmann .max_signal = 0, 16271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 16371b9114dSArnd Bergmann }, { 16471b9114dSArnd Bergmann .bus_id = "pcm1_rx", 16571b9114dSArnd Bergmann .min_signal = 1, 16671b9114dSArnd Bergmann .max_signal = 1, 16771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 16871b9114dSArnd Bergmann }, { 16971b9114dSArnd Bergmann .bus_id = "i2s1_tx", 17071b9114dSArnd Bergmann .min_signal = 2, 17171b9114dSArnd Bergmann .max_signal = 2, 17271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 17371b9114dSArnd Bergmann }, { 17471b9114dSArnd Bergmann .bus_id = "i2s1_rx", 17571b9114dSArnd Bergmann .min_signal = 3, 17671b9114dSArnd Bergmann .max_signal = 3, 17771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 17871b9114dSArnd Bergmann }, { 17971b9114dSArnd Bergmann .bus_id = "spi1_tx", 18071b9114dSArnd Bergmann .min_signal = 4, 18171b9114dSArnd Bergmann .max_signal = 4, 18271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 18371b9114dSArnd Bergmann }, { 18471b9114dSArnd Bergmann .bus_id = "spi1_rx", 18571b9114dSArnd Bergmann .min_signal = 5, 18671b9114dSArnd Bergmann .max_signal = 5, 18771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 18871b9114dSArnd Bergmann }, { 18971b9114dSArnd Bergmann .bus_id = "ac97_out", 19071b9114dSArnd Bergmann .min_signal = 6, 19171b9114dSArnd Bergmann .max_signal = 6, 19271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 19371b9114dSArnd Bergmann }, { 19471b9114dSArnd Bergmann .bus_id = "ac97_in", 19571b9114dSArnd Bergmann .min_signal = 7, 19671b9114dSArnd Bergmann .max_signal = 7, 19771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 19871b9114dSArnd Bergmann }, { 19971b9114dSArnd Bergmann .bus_id = "ac97_mic", 20071b9114dSArnd Bergmann .min_signal = 8, 20171b9114dSArnd Bergmann .max_signal = 8, 20271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 20371b9114dSArnd Bergmann }, { 20471b9114dSArnd Bergmann .bus_id = "pwm", 20571b9114dSArnd Bergmann .min_signal = 9, 20671b9114dSArnd Bergmann .max_signal = 9, 20771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 20871b9114dSArnd Bergmann }, { 20971b9114dSArnd Bergmann .bus_id = "irda", 21071b9114dSArnd Bergmann .min_signal = 10, 21171b9114dSArnd Bergmann .max_signal = 10, 21271b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 21371b9114dSArnd Bergmann }, { 21471b9114dSArnd Bergmann .bus_id = "external", 21571b9114dSArnd Bergmann .min_signal = 11, 21671b9114dSArnd Bergmann .max_signal = 11, 21771b9114dSArnd Bergmann .periph_buses = PL08X_AHB2, 21871b9114dSArnd Bergmann }, 21971b9114dSArnd Bergmann }; 22071b9114dSArnd Bergmann 22171b9114dSArnd Bergmann static const struct dma_slave_map s3c64xx_dma1_slave_map[] = { 22271b9114dSArnd Bergmann { "samsung-pcm.1", "tx", &s3c64xx_dma1_info[0] }, 22371b9114dSArnd Bergmann { "samsung-pcm.1", "rx", &s3c64xx_dma1_info[1] }, 22471b9114dSArnd Bergmann { "samsung-i2s.1", "tx", &s3c64xx_dma1_info[2] }, 22571b9114dSArnd Bergmann { "samsung-i2s.1", "rx", &s3c64xx_dma1_info[3] }, 22671b9114dSArnd Bergmann { "s3c6410-spi.1", "tx", &s3c64xx_dma1_info[4] }, 22771b9114dSArnd Bergmann { "s3c6410-spi.1", "rx", &s3c64xx_dma1_info[5] }, 22871b9114dSArnd Bergmann }; 22971b9114dSArnd Bergmann 23071b9114dSArnd Bergmann struct pl08x_platform_data s3c64xx_dma1_plat_data = { 23171b9114dSArnd Bergmann .memcpy_burst_size = PL08X_BURST_SZ_4, 23271b9114dSArnd Bergmann .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS, 23371b9114dSArnd Bergmann .memcpy_prot_buff = true, 23471b9114dSArnd Bergmann .memcpy_prot_cache = true, 23571b9114dSArnd Bergmann .lli_buses = PL08X_AHB1, 23671b9114dSArnd Bergmann .mem_buses = PL08X_AHB1, 23771b9114dSArnd Bergmann .get_xfer_signal = pl08x_get_xfer_signal, 23871b9114dSArnd Bergmann .put_xfer_signal = pl08x_put_xfer_signal, 23971b9114dSArnd Bergmann .slave_channels = s3c64xx_dma1_info, 24071b9114dSArnd Bergmann .num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info), 24171b9114dSArnd Bergmann .slave_map = s3c64xx_dma1_slave_map, 24271b9114dSArnd Bergmann .slave_map_len = ARRAY_SIZE(s3c64xx_dma1_slave_map), 24371b9114dSArnd Bergmann }; 24471b9114dSArnd Bergmann 24571b9114dSArnd Bergmann static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0, 24671b9114dSArnd Bergmann 0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data); 24771b9114dSArnd Bergmann 24871b9114dSArnd Bergmann static int __init s3c64xx_pl080_init(void) 24971b9114dSArnd Bergmann { 25071b9114dSArnd Bergmann if (!soc_is_s3c64xx()) 25171b9114dSArnd Bergmann return 0; 25271b9114dSArnd Bergmann 25371b9114dSArnd Bergmann /* Set all DMA configuration to be DMA, not SDMA */ 25471b9114dSArnd Bergmann writel(0xffffff, S3C64XX_SDMA_SEL); 25571b9114dSArnd Bergmann 25671b9114dSArnd Bergmann if (of_have_populated_dt()) 25771b9114dSArnd Bergmann return 0; 25871b9114dSArnd Bergmann 25971b9114dSArnd Bergmann amba_device_register(&s3c64xx_dma0_device, &iomem_resource); 26071b9114dSArnd Bergmann amba_device_register(&s3c64xx_dma1_device, &iomem_resource); 26171b9114dSArnd Bergmann 26271b9114dSArnd Bergmann return 0; 26371b9114dSArnd Bergmann } 26471b9114dSArnd Bergmann arch_initcall(s3c64xx_pl080_init); 265