d->static_tr.elcnt = elcnt;
 
-       /*
-        * PDMA must to close the packet when the channel is in packet mode.
-        * For TR mode when the channel is not cyclic we also need PDMA to close
-        * the packet otherwise the transfer will stall because PDMA holds on
-        * the data it has received from the peripheral.
-        */
        if (uc->config.pkt_mode || !uc->cyclic) {
+               /*
+                * PDMA must close the packet when the channel is in packet mode.
+                * For TR mode when the channel is not cyclic we also need PDMA
+                * to close the packet otherwise the transfer will stall because
+                * PDMA holds on the data it has received from the peripheral.
+                */
                unsigned int div = dev_width * elcnt;
 
                if (uc->cyclic)
                        d->static_tr.bstcnt = d->residue / d->sglen / div;
                else
                        d->static_tr.bstcnt = d->residue / div;
+       } else if (uc->ud->match_data->type == DMA_TYPE_BCDMA &&
+                  uc->config.dir == DMA_DEV_TO_MEM &&
+                  uc->cyclic) {
+               /*
+                * For cyclic mode with BCDMA we have to set EOP in each TR to
+                * prevent short packet errors seen on channel teardown. So the
+                * PDMA must close the packet after every TR transfer by setting
+                * burst count equal to the number of bytes transferred.
+                */
+               struct cppi5_tr_type1_t *tr_req = d->hwdesc[0].tr_req_base;
 
-               if (uc->config.dir == DMA_DEV_TO_MEM &&
-                   d->static_tr.bstcnt > uc->ud->match_data->statictr_z_mask)
-                       return -EINVAL;
+               d->static_tr.bstcnt =
+                       (tr_req->icnt0 * tr_req->icnt1) / dev_width;
        } else {
                d->static_tr.bstcnt = 0;
        }
 
+       if (uc->config.dir == DMA_DEV_TO_MEM &&
+           d->static_tr.bstcnt > uc->ud->match_data->statictr_z_mask)
+               return -EINVAL;
+
        return 0;
 }
 
        /* static TR for remote PDMA */
        if (udma_configure_statictr(uc, d, dev_width, burst)) {
                dev_err(uc->ud->dev,
-                       "%s: StaticTR Z is limited to maximum 4095 (%u)\n",
-                       __func__, d->static_tr.bstcnt);
+                       "%s: StaticTR Z is limited to maximum %u (%u)\n",
+                       __func__, uc->ud->match_data->statictr_z_mask,
+                       d->static_tr.bstcnt);
 
                udma_free_hwdesc(uc, d);
                kfree(d);
        u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
        unsigned int i;
        int num_tr;
+       u32 period_csf = 0;
 
        num_tr = udma_get_tr_counters(period_len, __ffs(buf_addr), &tr0_cnt0,
                                      &tr0_cnt1, &tr1_cnt0);
                period_addr = buf_addr |
                        ((u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT);
 
+       /*
+        * For BCDMA <-> PDMA transfers, the EOP flag needs to be set on the
+        * last TR of a descriptor, to mark the packet as complete.
+        * This is required for getting the teardown completion message in case
+        * of TX, and to avoid short-packet error in case of RX.
+        *
+        * As we are in cyclic mode, we do not know which period might be the
+        * last one, so set the flag for each period.
+        */
+       if (uc->config.ep_type == PSIL_EP_PDMA_XY &&
+           uc->ud->match_data->type == DMA_TYPE_BCDMA) {
+               period_csf = CPPI5_TR_CSF_EOP;
+       }
+
        for (i = 0; i < periods; i++) {
                int tr_idx = i * num_tr;
 
                }
 
                if (!(flags & DMA_PREP_INTERRUPT))
-                       cppi5_tr_csf_set(&tr_req[tr_idx].flags,
-                                        CPPI5_TR_CSF_SUPR_EVT);
+                       period_csf |= CPPI5_TR_CSF_SUPR_EVT;
+
+               if (period_csf)
+                       cppi5_tr_csf_set(&tr_req[tr_idx].flags, period_csf);
 
                period_addr += period_len;
        }
        /* static TR for remote PDMA */
        if (udma_configure_statictr(uc, d, dev_width, burst)) {
                dev_err(uc->ud->dev,
-                       "%s: StaticTR Z is limited to maximum 4095 (%u)\n",
-                       __func__, d->static_tr.bstcnt);
+                       "%s: StaticTR Z is limited to maximum %u (%u)\n",
+                       __func__, uc->ud->match_data->statictr_z_mask,
+                       d->static_tr.bstcnt);
 
                udma_free_hwdesc(uc, d);
                kfree(d);