| // SPDX-License-Identifier: GPL-2.0 | |
| // | |
| // Samsung's S3C64XX generic DMA support using amba-pl08x driver. | |
| // | |
| // Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com> | |
| #include <linux/kernel.h> | |
| #include <linux/amba/bus.h> | |
| #include <linux/amba/pl080.h> | |
| #include <linux/amba/pl08x.h> | |
| #include <linux/of.h> | |
| #include "cpu.h" | |
| #include <mach/irqs.h> | |
| #include "map.h" | |
| #include "regs-sys-s3c64xx.h" | |
| static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd) | |
| { | |
| return cd->min_signal; | |
| } | |
| static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch) | |
| { | |
| } | |
| /* | |
| * DMA0 | |
| */ | |
| static struct pl08x_channel_data s3c64xx_dma0_info[] = { | |
| { | |
| .bus_id = "uart0_tx", | |
| .min_signal = 0, | |
| .max_signal = 0, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "uart0_rx", | |
| .min_signal = 1, | |
| .max_signal = 1, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "uart1_tx", | |
| .min_signal = 2, | |
| .max_signal = 2, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "uart1_rx", | |
| .min_signal = 3, | |
| .max_signal = 3, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "uart2_tx", | |
| .min_signal = 4, | |
| .max_signal = 4, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "uart2_rx", | |
| .min_signal = 5, | |
| .max_signal = 5, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "uart3_tx", | |
| .min_signal = 6, | |
| .max_signal = 6, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "uart3_rx", | |
| .min_signal = 7, | |
| .max_signal = 7, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "pcm0_tx", | |
| .min_signal = 8, | |
| .max_signal = 8, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "pcm0_rx", | |
| .min_signal = 9, | |
| .max_signal = 9, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "i2s0_tx", | |
| .min_signal = 10, | |
| .max_signal = 10, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "i2s0_rx", | |
| .min_signal = 11, | |
| .max_signal = 11, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "spi0_tx", | |
| .min_signal = 12, | |
| .max_signal = 12, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "spi0_rx", | |
| .min_signal = 13, | |
| .max_signal = 13, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "i2s2_tx", | |
| .min_signal = 14, | |
| .max_signal = 14, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "i2s2_rx", | |
| .min_signal = 15, | |
| .max_signal = 15, | |
| .periph_buses = PL08X_AHB2, | |
| } | |
| }; | |
| static const struct dma_slave_map s3c64xx_dma0_slave_map[] = { | |
| { "s3c6400-uart.0", "tx", &s3c64xx_dma0_info[0] }, | |
| { "s3c6400-uart.0", "rx", &s3c64xx_dma0_info[1] }, | |
| { "s3c6400-uart.1", "tx", &s3c64xx_dma0_info[2] }, | |
| { "s3c6400-uart.1", "rx", &s3c64xx_dma0_info[3] }, | |
| { "s3c6400-uart.2", "tx", &s3c64xx_dma0_info[4] }, | |
| { "s3c6400-uart.2", "rx", &s3c64xx_dma0_info[5] }, | |
| { "s3c6400-uart.3", "tx", &s3c64xx_dma0_info[6] }, | |
| { "s3c6400-uart.3", "rx", &s3c64xx_dma0_info[7] }, | |
| { "samsung-pcm.0", "tx", &s3c64xx_dma0_info[8] }, | |
| { "samsung-pcm.0", "rx", &s3c64xx_dma0_info[9] }, | |
| { "samsung-i2s.0", "tx", &s3c64xx_dma0_info[10] }, | |
| { "samsung-i2s.0", "rx", &s3c64xx_dma0_info[11] }, | |
| { "s3c6410-spi.0", "tx", &s3c64xx_dma0_info[12] }, | |
| { "s3c6410-spi.0", "rx", &s3c64xx_dma0_info[13] }, | |
| { "samsung-i2s.2", "tx", &s3c64xx_dma0_info[14] }, | |
| { "samsung-i2s.2", "rx", &s3c64xx_dma0_info[15] }, | |
| }; | |
| struct pl08x_platform_data s3c64xx_dma0_plat_data = { | |
| .memcpy_burst_size = PL08X_BURST_SZ_4, | |
| .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS, | |
| .memcpy_prot_buff = true, | |
| .memcpy_prot_cache = true, | |
| .lli_buses = PL08X_AHB1, | |
| .mem_buses = PL08X_AHB1, | |
| .get_xfer_signal = pl08x_get_xfer_signal, | |
| .put_xfer_signal = pl08x_put_xfer_signal, | |
| .slave_channels = s3c64xx_dma0_info, | |
| .num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info), | |
| .slave_map = s3c64xx_dma0_slave_map, | |
| .slave_map_len = ARRAY_SIZE(s3c64xx_dma0_slave_map), | |
| }; | |
| static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0, | |
| 0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data); | |
| /* | |
| * DMA1 | |
| */ | |
| static struct pl08x_channel_data s3c64xx_dma1_info[] = { | |
| { | |
| .bus_id = "pcm1_tx", | |
| .min_signal = 0, | |
| .max_signal = 0, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "pcm1_rx", | |
| .min_signal = 1, | |
| .max_signal = 1, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "i2s1_tx", | |
| .min_signal = 2, | |
| .max_signal = 2, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "i2s1_rx", | |
| .min_signal = 3, | |
| .max_signal = 3, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "spi1_tx", | |
| .min_signal = 4, | |
| .max_signal = 4, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "spi1_rx", | |
| .min_signal = 5, | |
| .max_signal = 5, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "ac97_out", | |
| .min_signal = 6, | |
| .max_signal = 6, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "ac97_in", | |
| .min_signal = 7, | |
| .max_signal = 7, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "ac97_mic", | |
| .min_signal = 8, | |
| .max_signal = 8, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "pwm", | |
| .min_signal = 9, | |
| .max_signal = 9, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "irda", | |
| .min_signal = 10, | |
| .max_signal = 10, | |
| .periph_buses = PL08X_AHB2, | |
| }, { | |
| .bus_id = "external", | |
| .min_signal = 11, | |
| .max_signal = 11, | |
| .periph_buses = PL08X_AHB2, | |
| }, | |
| }; | |
| static const struct dma_slave_map s3c64xx_dma1_slave_map[] = { | |
| { "samsung-pcm.1", "tx", &s3c64xx_dma1_info[0] }, | |
| { "samsung-pcm.1", "rx", &s3c64xx_dma1_info[1] }, | |
| { "samsung-i2s.1", "tx", &s3c64xx_dma1_info[2] }, | |
| { "samsung-i2s.1", "rx", &s3c64xx_dma1_info[3] }, | |
| { "s3c6410-spi.1", "tx", &s3c64xx_dma1_info[4] }, | |
| { "s3c6410-spi.1", "rx", &s3c64xx_dma1_info[5] }, | |
| }; | |
| struct pl08x_platform_data s3c64xx_dma1_plat_data = { | |
| .memcpy_burst_size = PL08X_BURST_SZ_4, | |
| .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS, | |
| .memcpy_prot_buff = true, | |
| .memcpy_prot_cache = true, | |
| .lli_buses = PL08X_AHB1, | |
| .mem_buses = PL08X_AHB1, | |
| .get_xfer_signal = pl08x_get_xfer_signal, | |
| .put_xfer_signal = pl08x_put_xfer_signal, | |
| .slave_channels = s3c64xx_dma1_info, | |
| .num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info), | |
| .slave_map = s3c64xx_dma1_slave_map, | |
| .slave_map_len = ARRAY_SIZE(s3c64xx_dma1_slave_map), | |
| }; | |
| static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0, | |
| 0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data); | |
| static int __init s3c64xx_pl080_init(void) | |
| { | |
| if (!soc_is_s3c64xx()) | |
| return 0; | |
| /* Set all DMA configuration to be DMA, not SDMA */ | |
| writel(0xffffff, S3C64XX_SDMA_SEL); | |
| if (of_have_populated_dt()) | |
| return 0; | |
| amba_device_register(&s3c64xx_dma0_device, &iomem_resource); | |
| amba_device_register(&s3c64xx_dma1_device, &iomem_resource); | |
| return 0; | |
| } | |
| arch_initcall(s3c64xx_pl080_init); |