aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/ste_dma40_ll.c
diff options
context:
space:
mode:
authorJonas Aaberg <jonas.aberg@stericsson.com>2010-08-09 08:08:56 -0400
committerDan Williams <dan.j.williams@intel.com>2010-09-22 17:53:46 -0400
commit698e4732e7c9cf9f1f3eac2b8cdce8d4fe2b90bd (patch)
tree9716c813accd1f8f5f5fe6d4ad389fd64396c26d /drivers/dma/ste_dma40_ll.c
parent69f93faa57ed6c91b32aae1dcff7282fcb2872f5 (diff)
DMAENGINE: ste_dma40: rewrote LCLA entries allocation code
LLI allocation is now done on job level instead of channel level. Previously the maximum length of a linked job in hw on a logical channel was 8, since the LLIs where evenly divided. Now only executing jobs have allocated LLIs which increase the length to a maximum of 64 links in HW. Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma/ste_dma40_ll.c')
-rw-r--r--drivers/dma/ste_dma40_ll.c161
1 files changed, 55 insertions, 106 deletions
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index 92a0960fba08..86a306dbe1b4 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -37,16 +37,13 @@ void d40_log_cfg(struct stedma40_chan_cfg *cfg,
37 cfg->dir == STEDMA40_PERIPH_TO_PERIPH) 37 cfg->dir == STEDMA40_PERIPH_TO_PERIPH)
38 l3 |= 1 << D40_MEM_LCSP3_DCFG_MST_POS; 38 l3 |= 1 << D40_MEM_LCSP3_DCFG_MST_POS;
39 39
40 l3 |= 1 << D40_MEM_LCSP3_DCFG_TIM_POS;
41 l3 |= 1 << D40_MEM_LCSP3_DCFG_EIM_POS; 40 l3 |= 1 << D40_MEM_LCSP3_DCFG_EIM_POS;
42 l3 |= cfg->dst_info.psize << D40_MEM_LCSP3_DCFG_PSIZE_POS; 41 l3 |= cfg->dst_info.psize << D40_MEM_LCSP3_DCFG_PSIZE_POS;
43 l3 |= cfg->dst_info.data_width << D40_MEM_LCSP3_DCFG_ESIZE_POS; 42 l3 |= cfg->dst_info.data_width << D40_MEM_LCSP3_DCFG_ESIZE_POS;
44 l3 |= 1 << D40_MEM_LCSP3_DTCP_POS;
45 43
46 l1 |= 1 << D40_MEM_LCSP1_SCFG_EIM_POS; 44 l1 |= 1 << D40_MEM_LCSP1_SCFG_EIM_POS;
47 l1 |= cfg->src_info.psize << D40_MEM_LCSP1_SCFG_PSIZE_POS; 45 l1 |= cfg->src_info.psize << D40_MEM_LCSP1_SCFG_PSIZE_POS;
48 l1 |= cfg->src_info.data_width << D40_MEM_LCSP1_SCFG_ESIZE_POS; 46 l1 |= cfg->src_info.data_width << D40_MEM_LCSP1_SCFG_ESIZE_POS;
49 l1 |= 1 << D40_MEM_LCSP1_STCP_POS;
50 47
51 *lcsp1 = l1; 48 *lcsp1 = l1;
52 *lcsp3 = l3; 49 *lcsp3 = l3;
@@ -235,7 +232,7 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
235 } 232 }
236 233
237 return total_size; 234 return total_size;
238 err: 235err:
239 return err; 236 return err;
240} 237}
241 238
@@ -268,11 +265,59 @@ void d40_phy_lli_write(void __iomem *virtbase,
268 265
269/* DMA logical lli operations */ 266/* DMA logical lli operations */
270 267
268static void d40_log_lli_link(struct d40_log_lli *lli_dst,
269 struct d40_log_lli *lli_src,
270 int next)
271{
272 u32 slos = 0;
273 u32 dlos = 0;
274
275 if (next != -EINVAL) {
276 slos = next * 2;
277 dlos = next * 2 + 1;
278 } else {
279 lli_dst->lcsp13 |= D40_MEM_LCSP1_SCFG_TIM_MASK;
280 lli_dst->lcsp13 |= D40_MEM_LCSP3_DTCP_MASK;
281 }
282
283 lli_src->lcsp13 = (lli_src->lcsp13 & ~D40_MEM_LCSP1_SLOS_MASK) |
284 (slos << D40_MEM_LCSP1_SLOS_POS);
285
286 lli_dst->lcsp13 = (lli_dst->lcsp13 & ~D40_MEM_LCSP1_SLOS_MASK) |
287 (dlos << D40_MEM_LCSP1_SLOS_POS);
288}
289
290void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
291 struct d40_log_lli *lli_dst,
292 struct d40_log_lli *lli_src,
293 int next)
294{
295 d40_log_lli_link(lli_dst, lli_src, next);
296
297 writel(lli_src->lcsp02, &lcpa[0].lcsp0);
298 writel(lli_src->lcsp13, &lcpa[0].lcsp1);
299 writel(lli_dst->lcsp02, &lcpa[0].lcsp2);
300 writel(lli_dst->lcsp13, &lcpa[0].lcsp3);
301}
302
303void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
304 struct d40_log_lli *lli_dst,
305 struct d40_log_lli *lli_src,
306 int next)
307{
308 d40_log_lli_link(lli_dst, lli_src, next);
309
310 writel(lli_src->lcsp02, &lcla[0].lcsp02);
311 writel(lli_src->lcsp13, &lcla[0].lcsp13);
312 writel(lli_dst->lcsp02, &lcla[1].lcsp02);
313 writel(lli_dst->lcsp13, &lcla[1].lcsp13);
314}
315
271void d40_log_fill_lli(struct d40_log_lli *lli, 316void d40_log_fill_lli(struct d40_log_lli *lli,
272 dma_addr_t data, u32 data_size, 317 dma_addr_t data, u32 data_size,
273 u32 lli_next_off, u32 reg_cfg, 318 u32 reg_cfg,
274 u32 data_width, 319 u32 data_width,
275 bool term_int, bool addr_inc) 320 bool addr_inc)
276{ 321{
277 lli->lcsp13 = reg_cfg; 322 lli->lcsp13 = reg_cfg;
278 323
@@ -287,165 +332,69 @@ void d40_log_fill_lli(struct d40_log_lli *lli,
287 if (addr_inc) 332 if (addr_inc)
288 lli->lcsp13 |= D40_MEM_LCSP1_SCFG_INCR_MASK; 333 lli->lcsp13 |= D40_MEM_LCSP1_SCFG_INCR_MASK;
289 334
290 lli->lcsp13 |= D40_MEM_LCSP3_DTCP_MASK;
291 /* If this scatter list entry is the last one, no next link */
292 lli->lcsp13 |= (lli_next_off << D40_MEM_LCSP1_SLOS_POS) &
293 D40_MEM_LCSP1_SLOS_MASK;
294
295 if (term_int)
296 lli->lcsp13 |= D40_MEM_LCSP1_SCFG_TIM_MASK;
297 else
298 lli->lcsp13 &= ~D40_MEM_LCSP1_SCFG_TIM_MASK;
299} 335}
300 336
301int d40_log_sg_to_dev(struct d40_lcla_elem *lcla, 337int d40_log_sg_to_dev(struct scatterlist *sg,
302 struct scatterlist *sg,
303 int sg_len, 338 int sg_len,
304 struct d40_log_lli_bidir *lli, 339 struct d40_log_lli_bidir *lli,
305 struct d40_def_lcsp *lcsp, 340 struct d40_def_lcsp *lcsp,
306 u32 src_data_width, 341 u32 src_data_width,
307 u32 dst_data_width, 342 u32 dst_data_width,
308 enum dma_data_direction direction, 343 enum dma_data_direction direction,
309 dma_addr_t dev_addr, int max_len, 344 dma_addr_t dev_addr)
310 int llis_per_log)
311{ 345{
312 int total_size = 0; 346 int total_size = 0;
313 struct scatterlist *current_sg = sg; 347 struct scatterlist *current_sg = sg;
314 int i; 348 int i;
315 u32 next_lli_off_dst = 0;
316 u32 next_lli_off_src = 0;
317 349
318 for_each_sg(sg, current_sg, sg_len, i) { 350 for_each_sg(sg, current_sg, sg_len, i) {
319 total_size += sg_dma_len(current_sg); 351 total_size += sg_dma_len(current_sg);
320 352
321 /*
322 * If this scatter list entry is the last one or
323 * max length, terminate link.
324 */
325 if (sg_len - 1 == i || ((i+1) % max_len == 0)) {
326 next_lli_off_src = 0;
327 next_lli_off_dst = 0;
328 } else {
329 if (next_lli_off_dst == 0 &&
330 next_lli_off_src == 0) {
331 /* The first lli will be at next_lli_off */
332 next_lli_off_dst = (lcla->dst_id *
333 llis_per_log + 1);
334 next_lli_off_src = (lcla->src_id *
335 llis_per_log + 1);
336 } else {
337 next_lli_off_dst++;
338 next_lli_off_src++;
339 }
340 }
341
342 if (direction == DMA_TO_DEVICE) { 353 if (direction == DMA_TO_DEVICE) {
343 d40_log_fill_lli(&lli->src[i], 354 d40_log_fill_lli(&lli->src[i],
344 sg_phys(current_sg), 355 sg_phys(current_sg),
345 sg_dma_len(current_sg), 356 sg_dma_len(current_sg),
346 next_lli_off_src,
347 lcsp->lcsp1, src_data_width, 357 lcsp->lcsp1, src_data_width,
348 false,
349 true); 358 true);
350 d40_log_fill_lli(&lli->dst[i], 359 d40_log_fill_lli(&lli->dst[i],
351 dev_addr, 360 dev_addr,
352 sg_dma_len(current_sg), 361 sg_dma_len(current_sg),
353 next_lli_off_dst,
354 lcsp->lcsp3, dst_data_width, 362 lcsp->lcsp3, dst_data_width,
355 /* No next == terminal interrupt */
356 !next_lli_off_dst,
357 false); 363 false);
358 } else { 364 } else {
359 d40_log_fill_lli(&lli->dst[i], 365 d40_log_fill_lli(&lli->dst[i],
360 sg_phys(current_sg), 366 sg_phys(current_sg),
361 sg_dma_len(current_sg), 367 sg_dma_len(current_sg),
362 next_lli_off_dst,
363 lcsp->lcsp3, dst_data_width, 368 lcsp->lcsp3, dst_data_width,
364 /* No next == terminal interrupt */
365 !next_lli_off_dst,
366 true); 369 true);
367 d40_log_fill_lli(&lli->src[i], 370 d40_log_fill_lli(&lli->src[i],
368 dev_addr, 371 dev_addr,
369 sg_dma_len(current_sg), 372 sg_dma_len(current_sg),
370 next_lli_off_src,
371 lcsp->lcsp1, src_data_width, 373 lcsp->lcsp1, src_data_width,
372 false,
373 false); 374 false);
374 } 375 }
375 } 376 }
376 return total_size; 377 return total_size;
377} 378}
378 379
379int d40_log_sg_to_lli(int lcla_id, 380int d40_log_sg_to_lli(struct scatterlist *sg,
380 struct scatterlist *sg,
381 int sg_len, 381 int sg_len,
382 struct d40_log_lli *lli_sg, 382 struct d40_log_lli *lli_sg,
383 u32 lcsp13, /* src or dst*/ 383 u32 lcsp13, /* src or dst*/
384 u32 data_width, 384 u32 data_width)
385 int max_len, int llis_per_log)
386{ 385{
387 int total_size = 0; 386 int total_size = 0;
388 struct scatterlist *current_sg = sg; 387 struct scatterlist *current_sg = sg;
389 int i; 388 int i;
390 u32 next_lli_off = 0;
391 389
392 for_each_sg(sg, current_sg, sg_len, i) { 390 for_each_sg(sg, current_sg, sg_len, i) {
393 total_size += sg_dma_len(current_sg); 391 total_size += sg_dma_len(current_sg);
394 392
395 /*
396 * If this scatter list entry is the last one or
397 * max length, terminate link.
398 */
399 if (sg_len - 1 == i || ((i+1) % max_len == 0))
400 next_lli_off = 0;
401 else {
402 if (next_lli_off == 0)
403 /* The first lli will be at next_lli_off */
404 next_lli_off = lcla_id * llis_per_log + 1;
405 else
406 next_lli_off++;
407 }
408
409 d40_log_fill_lli(&lli_sg[i], 393 d40_log_fill_lli(&lli_sg[i],
410 sg_phys(current_sg), 394 sg_phys(current_sg),
411 sg_dma_len(current_sg), 395 sg_dma_len(current_sg),
412 next_lli_off,
413 lcsp13, data_width, 396 lcsp13, data_width,
414 !next_lli_off,
415 true); 397 true);
416 } 398 }
417 return total_size; 399 return total_size;
418} 400}
419
420int d40_log_lli_write(struct d40_log_lli_full *lcpa,
421 struct d40_log_lli *lcla_src,
422 struct d40_log_lli *lcla_dst,
423 struct d40_log_lli *lli_dst,
424 struct d40_log_lli *lli_src,
425 int llis_per_log)
426{
427 u32 slos;
428 u32 dlos;
429 int i;
430
431 writel(lli_src->lcsp02, &lcpa->lcsp0);
432 writel(lli_src->lcsp13, &lcpa->lcsp1);
433 writel(lli_dst->lcsp02, &lcpa->lcsp2);
434 writel(lli_dst->lcsp13, &lcpa->lcsp3);
435
436 slos = lli_src->lcsp13 & D40_MEM_LCSP1_SLOS_MASK;
437 dlos = lli_dst->lcsp13 & D40_MEM_LCSP3_DLOS_MASK;
438
439 for (i = 0; (i < llis_per_log) && slos && dlos; i++) {
440 writel(lli_src[i + 1].lcsp02, &lcla_src[i].lcsp02);
441 writel(lli_src[i + 1].lcsp13, &lcla_src[i].lcsp13);
442 writel(lli_dst[i + 1].lcsp02, &lcla_dst[i].lcsp02);
443 writel(lli_dst[i + 1].lcsp13, &lcla_dst[i].lcsp13);
444
445 slos = lli_src[i + 1].lcsp13 & D40_MEM_LCSP1_SLOS_MASK;
446 dlos = lli_dst[i + 1].lcsp13 & D40_MEM_LCSP3_DLOS_MASK;
447 }
448
449 return i;
450
451}