diff options
Diffstat (limited to 'drivers/dma/qcom/bam_dma.c')
-rw-r--r-- | drivers/dma/qcom/bam_dma.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index d5e0a9c3ad5d..969b48176745 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c | |||
@@ -342,7 +342,7 @@ static const struct reg_offset_data bam_v1_7_reg_info[] = { | |||
342 | 342 | ||
343 | #define BAM_DESC_FIFO_SIZE SZ_32K | 343 | #define BAM_DESC_FIFO_SIZE SZ_32K |
344 | #define MAX_DESCRIPTORS (BAM_DESC_FIFO_SIZE / sizeof(struct bam_desc_hw) - 1) | 344 | #define MAX_DESCRIPTORS (BAM_DESC_FIFO_SIZE / sizeof(struct bam_desc_hw) - 1) |
345 | #define BAM_MAX_DATA_SIZE (SZ_32K - 8) | 345 | #define BAM_FIFO_SIZE (SZ_32K - 8) |
346 | 346 | ||
347 | struct bam_chan { | 347 | struct bam_chan { |
348 | struct virt_dma_chan vc; | 348 | struct virt_dma_chan vc; |
@@ -387,6 +387,7 @@ struct bam_device { | |||
387 | 387 | ||
388 | /* execution environment ID, from DT */ | 388 | /* execution environment ID, from DT */ |
389 | u32 ee; | 389 | u32 ee; |
390 | bool controlled_remotely; | ||
390 | 391 | ||
391 | const struct reg_offset_data *layout; | 392 | const struct reg_offset_data *layout; |
392 | 393 | ||
@@ -458,7 +459,7 @@ static void bam_chan_init_hw(struct bam_chan *bchan, | |||
458 | */ | 459 | */ |
459 | writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)), | 460 | writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)), |
460 | bam_addr(bdev, bchan->id, BAM_P_DESC_FIFO_ADDR)); | 461 | bam_addr(bdev, bchan->id, BAM_P_DESC_FIFO_ADDR)); |
461 | writel_relaxed(BAM_DESC_FIFO_SIZE, | 462 | writel_relaxed(BAM_FIFO_SIZE, |
462 | bam_addr(bdev, bchan->id, BAM_P_FIFO_SIZES)); | 463 | bam_addr(bdev, bchan->id, BAM_P_FIFO_SIZES)); |
463 | 464 | ||
464 | /* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */ | 465 | /* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */ |
@@ -604,7 +605,7 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, | |||
604 | 605 | ||
605 | /* calculate number of required entries */ | 606 | /* calculate number of required entries */ |
606 | for_each_sg(sgl, sg, sg_len, i) | 607 | for_each_sg(sgl, sg, sg_len, i) |
607 | num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_MAX_DATA_SIZE); | 608 | num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_FIFO_SIZE); |
608 | 609 | ||
609 | /* allocate enough room to accomodate the number of entries */ | 610 | /* allocate enough room to accomodate the number of entries */ |
610 | async_desc = kzalloc(sizeof(*async_desc) + | 611 | async_desc = kzalloc(sizeof(*async_desc) + |
@@ -635,10 +636,10 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, | |||
635 | desc->addr = cpu_to_le32(sg_dma_address(sg) + | 636 | desc->addr = cpu_to_le32(sg_dma_address(sg) + |
636 | curr_offset); | 637 | curr_offset); |
637 | 638 | ||
638 | if (remainder > BAM_MAX_DATA_SIZE) { | 639 | if (remainder > BAM_FIFO_SIZE) { |
639 | desc->size = cpu_to_le16(BAM_MAX_DATA_SIZE); | 640 | desc->size = cpu_to_le16(BAM_FIFO_SIZE); |
640 | remainder -= BAM_MAX_DATA_SIZE; | 641 | remainder -= BAM_FIFO_SIZE; |
641 | curr_offset += BAM_MAX_DATA_SIZE; | 642 | curr_offset += BAM_FIFO_SIZE; |
642 | } else { | 643 | } else { |
643 | desc->size = cpu_to_le16(remainder); | 644 | desc->size = cpu_to_le16(remainder); |
644 | remainder = 0; | 645 | remainder = 0; |
@@ -801,13 +802,17 @@ static irqreturn_t bam_dma_irq(int irq, void *data) | |||
801 | if (srcs & P_IRQ) | 802 | if (srcs & P_IRQ) |
802 | tasklet_schedule(&bdev->task); | 803 | tasklet_schedule(&bdev->task); |
803 | 804 | ||
804 | if (srcs & BAM_IRQ) | 805 | if (srcs & BAM_IRQ) { |
805 | clr_mask = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_STTS)); | 806 | clr_mask = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_STTS)); |
806 | 807 | ||
807 | /* don't allow reorder of the various accesses to the BAM registers */ | 808 | /* |
808 | mb(); | 809 | * don't allow reorder of the various accesses to the BAM |
810 | * registers | ||
811 | */ | ||
812 | mb(); | ||
809 | 813 | ||
810 | writel_relaxed(clr_mask, bam_addr(bdev, 0, BAM_IRQ_CLR)); | 814 | writel_relaxed(clr_mask, bam_addr(bdev, 0, BAM_IRQ_CLR)); |
815 | } | ||
811 | 816 | ||
812 | return IRQ_HANDLED; | 817 | return IRQ_HANDLED; |
813 | } | 818 | } |
@@ -1038,6 +1043,9 @@ static int bam_init(struct bam_device *bdev) | |||
1038 | val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES)); | 1043 | val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES)); |
1039 | bdev->num_channels = val & BAM_NUM_PIPES_MASK; | 1044 | bdev->num_channels = val & BAM_NUM_PIPES_MASK; |
1040 | 1045 | ||
1046 | if (bdev->controlled_remotely) | ||
1047 | return 0; | ||
1048 | |||
1041 | /* s/w reset bam */ | 1049 | /* s/w reset bam */ |
1042 | /* after reset all pipes are disabled and idle */ | 1050 | /* after reset all pipes are disabled and idle */ |
1043 | val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL)); | 1051 | val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL)); |
@@ -1125,6 +1133,9 @@ static int bam_dma_probe(struct platform_device *pdev) | |||
1125 | return ret; | 1133 | return ret; |
1126 | } | 1134 | } |
1127 | 1135 | ||
1136 | bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node, | ||
1137 | "qcom,controlled-remotely"); | ||
1138 | |||
1128 | bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); | 1139 | bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); |
1129 | if (IS_ERR(bdev->bamclk)) | 1140 | if (IS_ERR(bdev->bamclk)) |
1130 | return PTR_ERR(bdev->bamclk); | 1141 | return PTR_ERR(bdev->bamclk); |
@@ -1163,7 +1174,7 @@ static int bam_dma_probe(struct platform_device *pdev) | |||
1163 | /* set max dma segment size */ | 1174 | /* set max dma segment size */ |
1164 | bdev->common.dev = bdev->dev; | 1175 | bdev->common.dev = bdev->dev; |
1165 | bdev->common.dev->dma_parms = &bdev->dma_parms; | 1176 | bdev->common.dev->dma_parms = &bdev->dma_parms; |
1166 | ret = dma_set_max_seg_size(bdev->common.dev, BAM_MAX_DATA_SIZE); | 1177 | ret = dma_set_max_seg_size(bdev->common.dev, BAM_FIFO_SIZE); |
1167 | if (ret) { | 1178 | if (ret) { |
1168 | dev_err(bdev->dev, "cannot set maximum segment size\n"); | 1179 | dev_err(bdev->dev, "cannot set maximum segment size\n"); |
1169 | goto err_bam_channel_exit; | 1180 | goto err_bam_channel_exit; |
@@ -1234,6 +1245,9 @@ static int bam_dma_remove(struct platform_device *pdev) | |||
1234 | bam_dma_terminate_all(&bdev->channels[i].vc.chan); | 1245 | bam_dma_terminate_all(&bdev->channels[i].vc.chan); |
1235 | tasklet_kill(&bdev->channels[i].vc.task); | 1246 | tasklet_kill(&bdev->channels[i].vc.task); |
1236 | 1247 | ||
1248 | if (!bdev->channels[i].fifo_virt) | ||
1249 | continue; | ||
1250 | |||
1237 | dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, | 1251 | dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, |
1238 | bdev->channels[i].fifo_virt, | 1252 | bdev->channels[i].fifo_virt, |
1239 | bdev->channels[i].fifo_phys); | 1253 | bdev->channels[i].fifo_phys); |