Merge tag 'io_uring-5.15-2021-09-11' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / dma / dw-axi-dmac / dw-axi-dmac-platform.c
index d9e4ac3..35993ab 100644 (file)
@@ -363,12 +363,16 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
                        DWAXIDMAC_TT_FC_MEM_TO_PER_DST :
                        DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC)
                        << CH_CFG_H_TT_FC_POS;
+               if (chan->chip->apb_regs)
+                       reg |= (chan->id << CH_CFG_H_DST_PER_POS);
                break;
        case DMA_DEV_TO_MEM:
                reg |= (chan->config.device_fc ?
                        DWAXIDMAC_TT_FC_PER_TO_MEM_SRC :
                        DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC)
                        << CH_CFG_H_TT_FC_POS;
+               if (chan->chip->apb_regs)
+                       reg |= (chan->id << CH_CFG_H_SRC_PER_POS);
                break;
        default:
                break;
@@ -470,18 +474,13 @@ static void dma_chan_free_chan_resources(struct dma_chan *dchan)
        pm_runtime_put(chan->chip->dev);
 }
 
-static void dw_axi_dma_set_hw_channel(struct axi_dma_chip *chip,
-                                     u32 handshake_num, bool set)
+static void dw_axi_dma_set_hw_channel(struct axi_dma_chan *chan, bool set)
 {
-       unsigned long start = 0;
-       unsigned long reg_value;
-       unsigned long reg_mask;
-       unsigned long reg_set;
-       unsigned long mask;
-       unsigned long val;
+       struct axi_dma_chip *chip = chan->chip;
+       unsigned long reg_value, val;
 
        if (!chip->apb_regs) {
-               dev_dbg(chip->dev, "apb_regs not initialized\n");
+               dev_err(chip->dev, "apb_regs not initialized\n");
                return;
        }
 
@@ -490,26 +489,22 @@ static void dw_axi_dma_set_hw_channel(struct axi_dma_chip *chip,
         * Lock the DMA channel by assign a handshake number to the channel.
         * Unlock the DMA channel by assign 0x3F to the channel.
         */
-       if (set) {
-               reg_set = UNUSED_CHANNEL;
-               val = handshake_num;
-       } else {
-               reg_set = handshake_num;
+       if (set)
+               val = chan->hw_handshake_num;
+       else
                val = UNUSED_CHANNEL;
-       }
 
        reg_value = lo_hi_readq(chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
 
-       for_each_set_clump8(start, reg_mask, &reg_value, 64) {
-               if (reg_mask == reg_set) {
-                       mask = GENMASK_ULL(start + 7, start);
-                       reg_value &= ~mask;
-                       reg_value |= rol64(val, start);
-                       lo_hi_writeq(reg_value,
-                                    chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
-                       break;
-               }
-       }
+       /* Channel is already allocated, set handshake as per channel ID */
+       /* 64 bit write should handle for 8 channels */
+
+       reg_value &= ~(DMA_APB_HS_SEL_MASK <<
+                       (chan->id * DMA_APB_HS_SEL_BIT_SIZE));
+       reg_value |= (val << (chan->id * DMA_APB_HS_SEL_BIT_SIZE));
+       lo_hi_writeq(reg_value, chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
+
+       return;
 }
 
 /*
@@ -742,7 +737,7 @@ dw_axi_dma_chan_prep_cyclic(struct dma_chan *dchan, dma_addr_t dma_addr,
                llp = hw_desc->llp;
        } while (total_segments);
 
-       dw_axi_dma_set_hw_channel(chan->chip, chan->hw_handshake_num, true);
+       dw_axi_dma_set_hw_channel(chan, true);
 
        return vchan_tx_prep(&chan->vc, &desc->vd, flags);
 
@@ -822,7 +817,7 @@ dw_axi_dma_chan_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
                llp = hw_desc->llp;
        } while (num_sgs);
 
-       dw_axi_dma_set_hw_channel(chan->chip, chan->hw_handshake_num, true);
+       dw_axi_dma_set_hw_channel(chan, true);
 
        return vchan_tx_prep(&chan->vc, &desc->vd, flags);
 
@@ -1098,8 +1093,7 @@ static int dma_chan_terminate_all(struct dma_chan *dchan)
                         "%s failed to stop\n", axi_chan_name(chan));
 
        if (chan->direction != DMA_MEM_TO_MEM)
-               dw_axi_dma_set_hw_channel(chan->chip,
-                                         chan->hw_handshake_num, false);
+               dw_axi_dma_set_hw_channel(chan, false);
        if (chan->direction == DMA_MEM_TO_DEV)
                dw_axi_dma_set_byte_halfword(chan, false);
 
@@ -1296,7 +1290,7 @@ static int parse_device_properties(struct axi_dma_chip *chip)
                        return -EINVAL;
 
                chip->dw->hdata->restrict_axi_burst_len = true;
-               chip->dw->hdata->axi_rw_burst_len = tmp - 1;
+               chip->dw->hdata->axi_rw_burst_len = tmp;
        }
 
        return 0;
@@ -1365,7 +1359,6 @@ static int dw_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-
        INIT_LIST_HEAD(&dw->dma.channels);
        for (i = 0; i < hdata->nr_channels; i++) {
                struct axi_dma_chan *chan = &dw->chan[i];
@@ -1386,6 +1379,7 @@ static int dw_probe(struct platform_device *pdev)
 
        /* DMA capabilities */
        dw->dma.chancnt = hdata->nr_channels;
+       dw->dma.max_burst = hdata->axi_rw_burst_len;
        dw->dma.src_addr_widths = AXI_DMA_BUSWIDTHS;
        dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS;
        dw->dma.directions = BIT(DMA_MEM_TO_MEM);