Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM/dmaengine: pl08x: pass reasonable memcpy settings

We cannot use bits from configuration registers as API between
platforms and driver like this, abstract it out to two enums
and mimic the stuff passed as device tree data.

This is done to make it possible for the driver to generate the
ccfg word on-the-fly so we can support more PL08x derivatives.

Acked-by: Olof Johansson <olof@lixom.net>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>

authored by

Linus Walleij and committed by
Vinod Koul
4166a56a 2ea659a9

+138 -82
+3
arch/arm/mach-lpc32xx/phy3250.c
··· 137 137 } 138 138 139 139 static struct pl08x_platform_data pl08x_pd = { 140 + /* Some reasonable memcpy defaults */ 141 + .memcpy_burst_size = PL08X_BURST_SZ_256, 142 + .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS, 140 143 .slave_channels = &pl08x_slave_channels[0], 141 144 .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels), 142 145 .get_xfer_signal = pl08x_get_signal,
+8 -20
arch/arm/mach-s3c64xx/pl080.c
··· 137 137 }; 138 138 139 139 struct 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 - }, 140 + .memcpy_burst_size = PL08X_BURST_SZ_4, 141 + .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS, 142 + .memcpy_prot_buff = true, 143 + .memcpy_prot_cache = true, 150 144 .lli_buses = PL08X_AHB1, 151 145 .mem_buses = PL08X_AHB1, 152 146 .get_xfer_signal = pl08x_get_xfer_signal, ··· 232 238 }; 233 239 234 240 struct pl08x_platform_data s3c64xx_dma1_plat_data = { 235 - .memcpy_channel = { 236 - .bus_id = "memcpy", 237 - .cctl_memcpy = 238 - (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT | 239 - PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT | 240 - PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | 241 - PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | 242 - PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | 243 - PL080_CONTROL_PROT_SYS), 244 - }, 241 + .memcpy_burst_size = PL08X_BURST_SZ_4, 242 + .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS, 243 + .memcpy_prot_buff = true, 244 + .memcpy_prot_cache = true, 245 245 .lli_buses = PL08X_AHB1, 246 246 .mem_buses = PL08X_AHB1, 247 247 .get_xfer_signal = pl08x_get_xfer_signal,
+4 -10
arch/arm/mach-spear/spear3xx.c
··· 44 44 45 45 /* dmac device registration */ 46 46 struct pl08x_platform_data pl080_plat_data = { 47 - .memcpy_channel = { 48 - .bus_id = "memcpy", 49 - .cctl_memcpy = 50 - (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \ 51 - PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \ 52 - PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \ 53 - PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \ 54 - PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \ 55 - PL080_CONTROL_PROT_SYS), 56 - }, 47 + .memcpy_burst_size = PL08X_BURST_SZ_16, 48 + .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS, 49 + .memcpy_prot_buff = true, 50 + .memcpy_prot_cache = true, 57 51 .lli_buses = PL08X_AHB1, 58 52 .mem_buses = PL08X_AHB1, 59 53 .get_xfer_signal = pl080_get_signal,
+4 -10
arch/arm/mach-spear/spear6xx.c
··· 322 322 }; 323 323 324 324 static struct pl08x_platform_data spear6xx_pl080_plat_data = { 325 - .memcpy_channel = { 326 - .bus_id = "memcpy", 327 - .cctl_memcpy = 328 - (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \ 329 - PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \ 330 - PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \ 331 - PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \ 332 - PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \ 333 - PL080_CONTROL_PROT_SYS), 334 - }, 325 + .memcpy_burst_size = PL08X_BURST_SZ_16, 326 + .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS, 327 + .memcpy_prot_buff = true, 328 + .memcpy_prot_cache = true, 335 329 .lli_buses = PL08X_AHB1, 336 330 .mem_buses = PL08X_AHB1, 337 331 .get_xfer_signal = pl080_get_signal,
+93 -38
drivers/dma/amba-pl08x.c
··· 1433 1433 struct pl08x_driver_data *pl08x = plchan->host; 1434 1434 struct pl08x_txd *txd; 1435 1435 struct pl08x_sg *dsg; 1436 + u32 cctl = 0; 1436 1437 int ret; 1437 1438 1438 1439 txd = pl08x_get_txd(plchan); ··· 1456 1455 1457 1456 /* Set platform data for m2m */ 1458 1457 txd->ccfg |= PL080_FLOW_MEM2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT; 1459 - txd->cctl = pl08x->pd->memcpy_channel.cctl_memcpy & 1460 - ~(PL080_CONTROL_DST_AHB2 | PL080_CONTROL_SRC_AHB2); 1458 + 1459 + /* Conjure cctl */ 1460 + switch (pl08x->pd->memcpy_burst_size) { 1461 + default: 1462 + dev_err(&pl08x->adev->dev, 1463 + "illegal burst size for memcpy, set to 1\n"); 1464 + /* Fall through */ 1465 + case PL08X_BURST_SZ_1: 1466 + cctl |= PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT | 1467 + PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT; 1468 + break; 1469 + case PL08X_BURST_SZ_4: 1470 + cctl |= PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT | 1471 + PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT; 1472 + break; 1473 + case PL08X_BURST_SZ_8: 1474 + cctl |= PL080_BSIZE_8 << PL080_CONTROL_SB_SIZE_SHIFT | 1475 + PL080_BSIZE_8 << PL080_CONTROL_DB_SIZE_SHIFT; 1476 + break; 1477 + case PL08X_BURST_SZ_16: 1478 + cctl |= PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | 1479 + PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT; 1480 + break; 1481 + case PL08X_BURST_SZ_32: 1482 + cctl |= PL080_BSIZE_32 << PL080_CONTROL_SB_SIZE_SHIFT | 1483 + PL080_BSIZE_32 << PL080_CONTROL_DB_SIZE_SHIFT; 1484 + break; 1485 + case PL08X_BURST_SZ_64: 1486 + cctl |= PL080_BSIZE_64 << PL080_CONTROL_SB_SIZE_SHIFT | 1487 + PL080_BSIZE_64 << PL080_CONTROL_DB_SIZE_SHIFT; 1488 + break; 1489 + case PL08X_BURST_SZ_128: 1490 + cctl |= PL080_BSIZE_128 << PL080_CONTROL_SB_SIZE_SHIFT | 1491 + PL080_BSIZE_128 << PL080_CONTROL_DB_SIZE_SHIFT; 1492 + break; 1493 + case PL08X_BURST_SZ_256: 1494 + cctl |= PL080_BSIZE_256 << PL080_CONTROL_SB_SIZE_SHIFT | 1495 + PL080_BSIZE_256 << PL080_CONTROL_DB_SIZE_SHIFT; 1496 + break; 1497 + } 1498 + 1499 + switch (pl08x->pd->memcpy_bus_width) { 1500 + default: 1501 + dev_err(&pl08x->adev->dev, 1502 + "illegal bus width for memcpy, set to 8 bits\n"); 1503 + /* Fall through */ 1504 + case PL08X_BUS_WIDTH_8_BITS: 1505 + cctl |= PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT | 1506 + PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT; 1507 + break; 1508 + case PL08X_BUS_WIDTH_16_BITS: 1509 + cctl |= PL080_WIDTH_16BIT << PL080_CONTROL_SWIDTH_SHIFT | 1510 + PL080_WIDTH_16BIT << PL080_CONTROL_DWIDTH_SHIFT; 1511 + break; 1512 + case PL08X_BUS_WIDTH_32_BITS: 1513 + cctl |= PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | 1514 + PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT; 1515 + break; 1516 + } 1517 + 1518 + /* Protection flags */ 1519 + if (pl08x->pd->memcpy_prot_buff) 1520 + cctl |= PL080_CONTROL_PROT_BUFF; 1521 + if (pl08x->pd->memcpy_prot_cache) 1522 + cctl |= PL080_CONTROL_PROT_CACHE; 1523 + 1524 + /* We are the kernel, so we are in privileged mode */ 1525 + cctl |= PL080_CONTROL_PROT_SYS; 1461 1526 1462 1527 /* Both to be incremented or the code will break */ 1463 - txd->cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR; 1528 + cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR; 1464 1529 1465 1530 if (pl08x->vd->dualmaster) 1466 - txd->cctl |= pl08x_select_bus(pl08x->mem_buses, 1467 - pl08x->mem_buses); 1531 + cctl |= pl08x_select_bus(pl08x->mem_buses, 1532 + pl08x->mem_buses); 1533 + 1534 + txd->cctl = cctl; 1468 1535 1469 1536 ret = pl08x_fill_llis_for_desc(plchan->host, txd); 1470 1537 if (!ret) { ··· 1994 1925 chan->signal = i; 1995 1926 pl08x_dma_slave_init(chan); 1996 1927 } else { 1997 - chan->cd = &pl08x->pd->memcpy_channel; 1928 + chan->cd = kzalloc(sizeof(*chan->cd), GFP_KERNEL); 1929 + if (!chan->cd) { 1930 + kfree(chan); 1931 + return -ENOMEM; 1932 + } 1933 + chan->cd->bus_id = "memcpy"; 1934 + chan->cd->periph_buses = pl08x->pd->mem_buses; 1998 1935 chan->name = kasprintf(GFP_KERNEL, "memcpy%d", i); 1999 1936 if (!chan->name) { 1937 + kfree(chan->cd); 2000 1938 kfree(chan); 2001 1939 return -ENOMEM; 2002 1940 } ··· 2175 2099 { 2176 2100 struct pl08x_platform_data *pd; 2177 2101 struct pl08x_channel_data *chanp = NULL; 2178 - u32 cctl_memcpy = 0; 2179 2102 u32 val; 2180 2103 int ret; 2181 2104 int i; ··· 2214 2139 dev_err(&adev->dev, "illegal burst size for memcpy, set to 1\n"); 2215 2140 /* Fall through */ 2216 2141 case 1: 2217 - cctl_memcpy |= PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT | 2218 - PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT; 2142 + pd->memcpy_burst_size = PL08X_BURST_SZ_1; 2219 2143 break; 2220 2144 case 4: 2221 - cctl_memcpy |= PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT | 2222 - PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT; 2145 + pd->memcpy_burst_size = PL08X_BURST_SZ_4; 2223 2146 break; 2224 2147 case 8: 2225 - cctl_memcpy |= PL080_BSIZE_8 << PL080_CONTROL_SB_SIZE_SHIFT | 2226 - PL080_BSIZE_8 << PL080_CONTROL_DB_SIZE_SHIFT; 2148 + pd->memcpy_burst_size = PL08X_BURST_SZ_8; 2227 2149 break; 2228 2150 case 16: 2229 - cctl_memcpy |= PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | 2230 - PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT; 2151 + pd->memcpy_burst_size = PL08X_BURST_SZ_16; 2231 2152 break; 2232 2153 case 32: 2233 - cctl_memcpy |= PL080_BSIZE_32 << PL080_CONTROL_SB_SIZE_SHIFT | 2234 - PL080_BSIZE_32 << PL080_CONTROL_DB_SIZE_SHIFT; 2154 + pd->memcpy_burst_size = PL08X_BURST_SZ_32; 2235 2155 break; 2236 2156 case 64: 2237 - cctl_memcpy |= PL080_BSIZE_64 << PL080_CONTROL_SB_SIZE_SHIFT | 2238 - PL080_BSIZE_64 << PL080_CONTROL_DB_SIZE_SHIFT; 2157 + pd->memcpy_burst_size = PL08X_BURST_SZ_64; 2239 2158 break; 2240 2159 case 128: 2241 - cctl_memcpy |= PL080_BSIZE_128 << PL080_CONTROL_SB_SIZE_SHIFT | 2242 - PL080_BSIZE_128 << PL080_CONTROL_DB_SIZE_SHIFT; 2160 + pd->memcpy_burst_size = PL08X_BURST_SZ_128; 2243 2161 break; 2244 2162 case 256: 2245 - cctl_memcpy |= PL080_BSIZE_256 << PL080_CONTROL_SB_SIZE_SHIFT | 2246 - PL080_BSIZE_256 << PL080_CONTROL_DB_SIZE_SHIFT; 2163 + pd->memcpy_burst_size = PL08X_BURST_SZ_256; 2247 2164 break; 2248 2165 } 2249 2166 ··· 2249 2182 dev_err(&adev->dev, "illegal bus width for memcpy, set to 8 bits\n"); 2250 2183 /* Fall through */ 2251 2184 case 8: 2252 - cctl_memcpy |= PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT | 2253 - PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT; 2185 + pd->memcpy_bus_width = PL08X_BUS_WIDTH_8_BITS; 2254 2186 break; 2255 2187 case 16: 2256 - cctl_memcpy |= PL080_WIDTH_16BIT << PL080_CONTROL_SWIDTH_SHIFT | 2257 - PL080_WIDTH_16BIT << PL080_CONTROL_DWIDTH_SHIFT; 2188 + pd->memcpy_bus_width = PL08X_BUS_WIDTH_16_BITS; 2258 2189 break; 2259 2190 case 32: 2260 - cctl_memcpy |= PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | 2261 - PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT; 2191 + pd->memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS; 2262 2192 break; 2263 2193 } 2264 - 2265 - /* This is currently the only thing making sense */ 2266 - cctl_memcpy |= PL080_CONTROL_PROT_SYS; 2267 - 2268 - /* Set up memcpy channel */ 2269 - pd->memcpy_channel.bus_id = "memcpy"; 2270 - pd->memcpy_channel.cctl_memcpy = cctl_memcpy; 2271 - /* Use the buses that can access memory, obviously */ 2272 - pd->memcpy_channel.periph_buses = pd->mem_buses; 2273 2194 2274 2195 /* 2275 2196 * Allocate channel data for all possible slave channels (one
+26 -4
include/linux/amba/pl08x.h
··· 47 47 * devices with static assignments 48 48 * @muxval: a number usually used to poke into some mux regiser to 49 49 * mux in the signal to this channel 50 - * @cctl_memcpy: options for the channel control register for memcpy 51 - * *** not used for slave channels *** 52 50 * @addr: source/target address in physical memory for this DMA channel, 53 51 * can be the address of a FIFO register for burst requests for example. 54 52 * This can be left undefined if the PrimeCell API is used for configuring ··· 61 63 int min_signal; 62 64 int max_signal; 63 65 u32 muxval; 64 - u32 cctl_memcpy; 65 66 dma_addr_t addr; 66 67 bool single; 67 68 u8 periph_buses; 69 + }; 70 + 71 + enum pl08x_burst_size { 72 + PL08X_BURST_SZ_1, 73 + PL08X_BURST_SZ_4, 74 + PL08X_BURST_SZ_8, 75 + PL08X_BURST_SZ_16, 76 + PL08X_BURST_SZ_32, 77 + PL08X_BURST_SZ_64, 78 + PL08X_BURST_SZ_128, 79 + PL08X_BURST_SZ_256, 80 + }; 81 + 82 + enum pl08x_bus_width { 83 + PL08X_BUS_WIDTH_8_BITS, 84 + PL08X_BUS_WIDTH_16_BITS, 85 + PL08X_BUS_WIDTH_32_BITS, 68 86 }; 69 87 70 88 /** ··· 90 76 * platform, all inclusive, including multiplexed channels. The available 91 77 * physical channels will be multiplexed around these signals as they are 92 78 * requested, just enumerate all possible channels. 79 + * @num_slave_channels: number of elements in the slave channel array 80 + * @memcpy_burst_size: the appropriate burst size for memcpy operations 81 + * @memcpy_bus_width: memory bus width 82 + * @memcpy_prot_buff: whether memcpy DMA is bufferable 83 + * @memcpy_prot_cache: whether memcpy DMA is cacheable 93 84 * @get_xfer_signal: request a physical signal to be used for a DMA transfer 94 85 * immediately: if there is some multiplexing or similar blocking the use 95 86 * of the channel the transfer can be denied by returning less than zero, ··· 109 90 struct pl08x_platform_data { 110 91 struct pl08x_channel_data *slave_channels; 111 92 unsigned int num_slave_channels; 112 - struct pl08x_channel_data memcpy_channel; 93 + enum pl08x_burst_size memcpy_burst_size; 94 + enum pl08x_bus_width memcpy_bus_width; 95 + bool memcpy_prot_buff; 96 + bool memcpy_prot_cache; 113 97 int (*get_xfer_signal)(const struct pl08x_channel_data *); 114 98 void (*put_xfer_signal)(const struct pl08x_channel_data *, int); 115 99 u8 lli_buses;