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

dmaengine: sprd: Set request pending flag when DMA controller is active

On new Spreadtrum platforms, when the CPU enters idle, it will close
the DMA controllers' clock to save power if the DMA controller is not
busy. Moreover the DMA controller's busy signal depends on the DMA
enable flag and the request pending flag.

When DMA controller starts to transfer data, which means we already
set the DMA enable flag, but now we should also set the request pending
flag, in case the DMA clock will be closed accidentally if the CPU
can not detect the DMA controller's busy signal.

Signed-off-by: Zhenfang Wang <zhenfang.wang@unisoc.com>
Signed-off-by: Baolin Wang <baolin.wang7@gmail.com>
Link: https://lore.kernel.org/r/02adbe4364ec436ec2c5bc8fd2386bab98edd884.1584019223.git.baolin.wang7@gmail.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Zhenfang Wang and committed by
Vinod Koul
d0f19a48 3a5a8a27

+24
+24
drivers/dma/sprd-dma.c
··· 486 486 return 0; 487 487 } 488 488 489 + static void sprd_dma_set_pending(struct sprd_dma_chn *schan, bool enable) 490 + { 491 + struct sprd_dma_dev *sdev = to_sprd_dma_dev(&schan->vc.chan); 492 + u32 reg, val, req_id; 493 + 494 + if (schan->dev_id == SPRD_DMA_SOFTWARE_UID) 495 + return; 496 + 497 + /* The DMA request id always starts from 0. */ 498 + req_id = schan->dev_id - 1; 499 + 500 + if (req_id < 32) { 501 + reg = SPRD_DMA_GLB_REQ_PEND0_EN; 502 + val = BIT(req_id); 503 + } else { 504 + reg = SPRD_DMA_GLB_REQ_PEND1_EN; 505 + val = BIT(req_id - 32); 506 + } 507 + 508 + sprd_dma_glb_update(sdev, reg, val, enable ? val : 0); 509 + } 510 + 489 511 static void sprd_dma_set_chn_config(struct sprd_dma_chn *schan, 490 512 struct sprd_dma_desc *sdesc) 491 513 { ··· 554 532 */ 555 533 sprd_dma_set_chn_config(schan, schan->cur_desc); 556 534 sprd_dma_set_uid(schan); 535 + sprd_dma_set_pending(schan, true); 557 536 sprd_dma_enable_chn(schan); 558 537 559 538 if (schan->dev_id == SPRD_DMA_SOFTWARE_UID && ··· 566 543 static void sprd_dma_stop(struct sprd_dma_chn *schan) 567 544 { 568 545 sprd_dma_stop_and_disable(schan); 546 + sprd_dma_set_pending(schan, false); 569 547 sprd_dma_unset_uid(schan); 570 548 sprd_dma_clear_int(schan); 571 549 schan->cur_desc = NULL;