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