/* Invalid DMA addr */ #define DMA_INVALID_ADDRESS GENMASK(31, 0) /* Used to unlock the dev */ #define UNLOCK_MASK 0x757bdf0d /* Timeout for polling reset bits */ #define INIT_POLL_TIMEOUT 2500000 /* Delay for polling reset bits */ #define INIT_POLL_DELAY 20 /* Signal this is the last DMA transfer, wait for the AXI and PCAP before *interrupting
*/ #define DMA_SRC_LAST_TRANSFER 1 /* Timeout for DMA completion */ #define DMA_TIMEOUT_MS 5000
/* Masks for controlling stuff in SLCR */ /* Disable all Level shifters */ #define LVL_SHFTR_DISABLE_ALL_MASK 0x0 /* Enable Level shifters from PS to PL */ #define LVL_SHFTR_ENABLE_PS_TO_PL 0xa /* Enable Level shifters from PL to PS */ #define LVL_SHFTR_ENABLE_PL_TO_PS 0xf /* Enable global resets */ #define FPGA_RST_ALL_MASK 0xf /* Disable global resets */ #define FPGA_RST_NONE_MASK 0x0
/* Cause the specified irq mask bits to generate IRQs */ staticinlinevoid zynq_fpga_set_irq(struct zynq_fpga_priv *priv, u32 enable)
{
zynq_fpga_write(priv, INT_MASK_OFFSET, ~enable);
}
/* Must be called with dma_lock held */ staticvoid zynq_step_dma(struct zynq_fpga_priv *priv)
{
u32 addr;
u32 len; bool first;
first = priv->dma_elm == 0; while (priv->cur_sg) { /* Feed the DMA queue until it is full. */ if (zynq_fpga_read(priv, STATUS_OFFSET) & STATUS_DMA_Q_F) break;
addr = sg_dma_address(priv->cur_sg);
len = sg_dma_len(priv->cur_sg); if (priv->dma_elm + 1 == priv->dma_nelms) { /* The last transfer waits for the PCAP to finish too, *noticethisalsochangestheirq_masktoignore *IXR_DMA_DONE_MASKwhichensureswedonottrigger *thecompletiontooearly.
*/
addr |= DMA_SRC_LAST_TRANSFER;
priv->cur_sg = NULL;
} else {
priv->cur_sg = sg_next(priv->cur_sg);
priv->dma_elm++;
}
/* Once the first transfer is queued we can turn on the ISR, future *callstozynq_step_dmawillhappenfromtheISRcontext.The *dma_lockspinlockguaranteesthishandoverisdonecoherently,the *ISRenableisputattheendtoavoidanotherCPUspinninginthe *ISRonthislock.
*/ if (first && priv->cur_sg) {
zynq_fpga_set_irq(priv,
IXR_DMA_DONE_MASK | IXR_ERROR_FLAGS_MASK);
} elseif (!priv->cur_sg) { /* The last transfer changes to DMA & PCAP mode since we do *notwanttocontinueuntileverythinghasbeenflushedinto *thePCAP.
*/
zynq_fpga_set_irq(priv,
IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK);
}
}
/* check if bitstream is encrypted & and system's still secure */ if (info->flags & FPGA_MGR_ENCRYPTED_BITSTREAM) {
ctrl = zynq_fpga_read(priv, CTRL_OFFSET); if (!(ctrl & CTRL_SEC_EN_MASK)) {
dev_err(&mgr->dev, "System not secure, can't use encrypted bitstreams\n");
err = -EINVAL; goto out_err;
}
}
/* don't globally reset PL if we're doing partial reconfig */ if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) { if (!zynq_fpga_has_sync(buf, count)) {
dev_err(&mgr->dev, "Invalid bitstream, could not find a sync word. Bitstream must be a byte swapped .bin file\n");
err = -EINVAL; goto out_err;
}
err = zynq_fpga_poll_timeout(priv, STATUS_OFFSET, status,
status & STATUS_PCFG_INIT_MASK,
INIT_POLL_DELAY,
INIT_POLL_TIMEOUT); if (err) {
dev_err(&mgr->dev, "Timeout waiting for PCFG_INIT\n"); goto out_err;
}
}
/* set configuration register with following options: *-enablePCAPinterface *-setthroughputformaximumspeed(ifbistreamnotencrypted) *-setCPUinusermode
*/
ctrl = zynq_fpga_read(priv, CTRL_OFFSET); if (info->flags & FPGA_MGR_ENCRYPTED_BITSTREAM)
zynq_fpga_write(priv, CTRL_OFFSET,
(CTRL_PCAP_PR_MASK | CTRL_PCAP_MODE_MASK
| CTRL_PCAP_RATE_EN_MASK | ctrl)); else
zynq_fpga_write(priv, CTRL_OFFSET,
(CTRL_PCAP_PR_MASK | CTRL_PCAP_MODE_MASK
| ctrl));
/* We expect that the command queue is empty right now. */
status = zynq_fpga_read(priv, STATUS_OFFSET); if ((status & STATUS_DMA_Q_F) ||
(status & STATUS_DMA_Q_E) != STATUS_DMA_Q_E) {
dev_err(&mgr->dev, "DMA command queue not right\n");
err = -EBUSY; goto out_err;
}
/* The hardware can only DMA multiples of 4 bytes, and it requires the *startingaddressestobealignedto64bits(UG585pg212).
*/
for_each_sg(sgt->sgl, sg, sgt->nents, i) { if ((sg->offset % 8) || (sg->length % 4)) {
dev_err(&mgr->dev, "Invalid bitstream, chunks must be aligned\n"); return -EINVAL;
}
}
/* There doesn't seem to be a way to force cancel any DMA, so if *somethingwentwrongwearerelyingonthehardwaretohavehalted *theDMAbeforewegethere,iftherewaswecoulduse *wait_for_completion_interruptibletoo.
*/
/* Release 'PR' control back to the ICAP */
zynq_fpga_write(priv, CTRL_OFFSET,
zynq_fpga_read(priv, CTRL_OFFSET) & ~CTRL_PCAP_PR_MASK);
clk_disable(priv->clk);
if (err) return err;
/* for the partial reconfig case we didn't touch the level shifters */ if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) { /* enable level shifters from PL to PS */
regmap_write(priv->slcr, SLCR_LVL_SHFTR_EN_OFFSET,
LVL_SHFTR_ENABLE_PL_TO_PS);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.