aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>2018-09-29 03:46:36 -0400
committerVinod Koul <vkoul@kernel.org>2018-10-05 11:00:57 -0400
commitd64e1b3f5cce41dd878a3ea008dd696a4d7d07d9 (patch)
treed1f745215db992ee0846a6945f6058675bc2f2f9
parent5b394b2ddf0347bef56e50c69a58773c94343ff3 (diff)
dmaengine: owl: Add Slave and Cyclic mode support for Actions Semi Owl S900 SoC
Add Slave and Cyclic mode support for Actions Semi Owl S900 SoC. The slave mode supports bus width of 4 bytes common for all peripherals and 1 byte specific for UART. The cyclic mode supports only block mode transfer. Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Signed-off-by: Vinod Koul <vkoul@kernel.org>
-rw-r--r--drivers/dma/owl-dma.c279
1 files changed, 272 insertions, 7 deletions
diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
index 7812a6338acd..1d26db4c9229 100644
--- a/drivers/dma/owl-dma.c
+++ b/drivers/dma/owl-dma.c
@@ -21,6 +21,7 @@
21#include <linux/mm.h> 21#include <linux/mm.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/of_device.h> 23#include <linux/of_device.h>
24#include <linux/of_dma.h>
24#include <linux/slab.h> 25#include <linux/slab.h>
25#include "virt-dma.h" 26#include "virt-dma.h"
26 27
@@ -165,6 +166,7 @@ struct owl_dma_lli {
165struct owl_dma_txd { 166struct owl_dma_txd {
166 struct virt_dma_desc vd; 167 struct virt_dma_desc vd;
167 struct list_head lli_list; 168 struct list_head lli_list;
169 bool cyclic;
168}; 170};
169 171
170/** 172/**
@@ -191,6 +193,8 @@ struct owl_dma_vchan {
191 struct virt_dma_chan vc; 193 struct virt_dma_chan vc;
192 struct owl_dma_pchan *pchan; 194 struct owl_dma_pchan *pchan;
193 struct owl_dma_txd *txd; 195 struct owl_dma_txd *txd;
196 struct dma_slave_config cfg;
197 u8 drq;
194}; 198};
195 199
196/** 200/**
@@ -336,9 +340,11 @@ static struct owl_dma_lli *owl_dma_alloc_lli(struct owl_dma *od)
336 340
337static struct owl_dma_lli *owl_dma_add_lli(struct owl_dma_txd *txd, 341static struct owl_dma_lli *owl_dma_add_lli(struct owl_dma_txd *txd,
338 struct owl_dma_lli *prev, 342 struct owl_dma_lli *prev,
339 struct owl_dma_lli *next) 343 struct owl_dma_lli *next,
344 bool is_cyclic)
340{ 345{
341 list_add_tail(&next->node, &txd->lli_list); 346 if (!is_cyclic)
347 list_add_tail(&next->node, &txd->lli_list);
342 348
343 if (prev) { 349 if (prev) {
344 prev->hw.next_lli = next->phys; 350 prev->hw.next_lli = next->phys;
@@ -351,7 +357,9 @@ static struct owl_dma_lli *owl_dma_add_lli(struct owl_dma_txd *txd,
351static inline int owl_dma_cfg_lli(struct owl_dma_vchan *vchan, 357static inline int owl_dma_cfg_lli(struct owl_dma_vchan *vchan,
352 struct owl_dma_lli *lli, 358 struct owl_dma_lli *lli,
353 dma_addr_t src, dma_addr_t dst, 359 dma_addr_t src, dma_addr_t dst,
354 u32 len, enum dma_transfer_direction dir) 360 u32 len, enum dma_transfer_direction dir,
361 struct dma_slave_config *sconfig,
362 bool is_cyclic)
355{ 363{
356 struct owl_dma_lli_hw *hw = &lli->hw; 364 struct owl_dma_lli_hw *hw = &lli->hw;
357 u32 mode; 365 u32 mode;
@@ -365,6 +373,32 @@ static inline int owl_dma_cfg_lli(struct owl_dma_vchan *vchan,
365 OWL_DMA_MODE_DAM_INC; 373 OWL_DMA_MODE_DAM_INC;
366 374
367 break; 375 break;
376 case DMA_MEM_TO_DEV:
377 mode |= OWL_DMA_MODE_TS(vchan->drq)
378 | OWL_DMA_MODE_ST_DCU | OWL_DMA_MODE_DT_DEV
379 | OWL_DMA_MODE_SAM_INC | OWL_DMA_MODE_DAM_CONST;
380
381 /*
382 * Hardware only supports 32bit and 8bit buswidth. Since the
383 * default is 32bit, select 8bit only when requested.
384 */
385 if (sconfig->dst_addr_width == DMA_SLAVE_BUSWIDTH_1_BYTE)
386 mode |= OWL_DMA_MODE_NDDBW_8BIT;
387
388 break;
389 case DMA_DEV_TO_MEM:
390 mode |= OWL_DMA_MODE_TS(vchan->drq)
391 | OWL_DMA_MODE_ST_DEV | OWL_DMA_MODE_DT_DCU
392 | OWL_DMA_MODE_SAM_CONST | OWL_DMA_MODE_DAM_INC;
393
394 /*
395 * Hardware only supports 32bit and 8bit buswidth. Since the
396 * default is 32bit, select 8bit only when requested.
397 */
398 if (sconfig->src_addr_width == DMA_SLAVE_BUSWIDTH_1_BYTE)
399 mode |= OWL_DMA_MODE_NDDBW_8BIT;
400
401 break;
368 default: 402 default:
369 return -EINVAL; 403 return -EINVAL;
370 } 404 }
@@ -381,7 +415,10 @@ static inline int owl_dma_cfg_lli(struct owl_dma_vchan *vchan,
381 OWL_DMA_LLC_SAV_LOAD_NEXT | 415 OWL_DMA_LLC_SAV_LOAD_NEXT |
382 OWL_DMA_LLC_DAV_LOAD_NEXT); 416 OWL_DMA_LLC_DAV_LOAD_NEXT);
383 417
384 hw->ctrlb = llc_hw_ctrlb(OWL_DMA_INTCTL_SUPER_BLOCK); 418 if (is_cyclic)
419 hw->ctrlb = llc_hw_ctrlb(OWL_DMA_INTCTL_BLOCK);
420 else
421 hw->ctrlb = llc_hw_ctrlb(OWL_DMA_INTCTL_SUPER_BLOCK);
385 422
386 return 0; 423 return 0;
387} 424}
@@ -443,6 +480,16 @@ static void owl_dma_terminate_pchan(struct owl_dma *od,
443 spin_unlock_irqrestore(&od->lock, flags); 480 spin_unlock_irqrestore(&od->lock, flags);
444} 481}
445 482
483static void owl_dma_pause_pchan(struct owl_dma_pchan *pchan)
484{
485 pchan_writel(pchan, 1, OWL_DMAX_PAUSE);
486}
487
488static void owl_dma_resume_pchan(struct owl_dma_pchan *pchan)
489{
490 pchan_writel(pchan, 0, OWL_DMAX_PAUSE);
491}
492
446static int owl_dma_start_next_txd(struct owl_dma_vchan *vchan) 493static int owl_dma_start_next_txd(struct owl_dma_vchan *vchan)
447{ 494{
448 struct owl_dma *od = to_owl_dma(vchan->vc.chan.device); 495 struct owl_dma *od = to_owl_dma(vchan->vc.chan.device);
@@ -464,7 +511,10 @@ static int owl_dma_start_next_txd(struct owl_dma_vchan *vchan)
464 lli = list_first_entry(&txd->lli_list, 511 lli = list_first_entry(&txd->lli_list,
465 struct owl_dma_lli, node); 512 struct owl_dma_lli, node);
466 513
467 int_ctl = OWL_DMA_INTCTL_SUPER_BLOCK; 514 if (txd->cyclic)
515 int_ctl = OWL_DMA_INTCTL_BLOCK;
516 else
517 int_ctl = OWL_DMA_INTCTL_SUPER_BLOCK;
468 518
469 pchan_writel(pchan, OWL_DMAX_MODE, OWL_DMA_MODE_LME); 519 pchan_writel(pchan, OWL_DMAX_MODE, OWL_DMA_MODE_LME);
470 pchan_writel(pchan, OWL_DMAX_LINKLIST_CTL, 520 pchan_writel(pchan, OWL_DMAX_LINKLIST_CTL,
@@ -627,6 +677,54 @@ static int owl_dma_terminate_all(struct dma_chan *chan)
627 return 0; 677 return 0;
628} 678}
629 679
680static int owl_dma_config(struct dma_chan *chan,
681 struct dma_slave_config *config)
682{
683 struct owl_dma_vchan *vchan = to_owl_vchan(chan);
684
685 /* Reject definitely invalid configurations */
686 if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
687 config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
688 return -EINVAL;
689
690 memcpy(&vchan->cfg, config, sizeof(struct dma_slave_config));
691
692 return 0;
693}
694
695static int owl_dma_pause(struct dma_chan *chan)
696{
697 struct owl_dma_vchan *vchan = to_owl_vchan(chan);
698 unsigned long flags;
699
700 spin_lock_irqsave(&vchan->vc.lock, flags);
701
702 owl_dma_pause_pchan(vchan->pchan);
703
704 spin_unlock_irqrestore(&vchan->vc.lock, flags);
705
706 return 0;
707}
708
709static int owl_dma_resume(struct dma_chan *chan)
710{
711 struct owl_dma_vchan *vchan = to_owl_vchan(chan);
712 unsigned long flags;
713
714 if (!vchan->pchan && !vchan->txd)
715 return 0;
716
717 dev_dbg(chan2dev(chan), "vchan %p: resume\n", &vchan->vc);
718
719 spin_lock_irqsave(&vchan->vc.lock, flags);
720
721 owl_dma_resume_pchan(vchan->pchan);
722
723 spin_unlock_irqrestore(&vchan->vc.lock, flags);
724
725 return 0;
726}
727
630static u32 owl_dma_getbytes_chan(struct owl_dma_vchan *vchan) 728static u32 owl_dma_getbytes_chan(struct owl_dma_vchan *vchan)
631{ 729{
632 struct owl_dma_pchan *pchan; 730 struct owl_dma_pchan *pchan;
@@ -754,13 +852,14 @@ static struct dma_async_tx_descriptor
754 bytes = min_t(size_t, (len - offset), OWL_DMA_FRAME_MAX_LENGTH); 852 bytes = min_t(size_t, (len - offset), OWL_DMA_FRAME_MAX_LENGTH);
755 853
756 ret = owl_dma_cfg_lli(vchan, lli, src + offset, dst + offset, 854 ret = owl_dma_cfg_lli(vchan, lli, src + offset, dst + offset,
757 bytes, DMA_MEM_TO_MEM); 855 bytes, DMA_MEM_TO_MEM,
856 &vchan->cfg, txd->cyclic);
758 if (ret) { 857 if (ret) {