/* 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, * notice this also changes the irq_mask to ignore * IXR_DMA_DONE_MASK which ensures we do not trigger * the completion too early.
*/
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 * calls to zynq_step_dma will happen from the ISR context. The * dma_lock spinlock guarantees this handover is done coherently, the * ISR enable is put at the end to avoid another CPU spinning in the * ISR on this lock.
*/ 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 * not want to continue until everything has been flushed into * the PCAP.
*/
zynq_fpga_set_irq(priv,
IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK);
}
}
/* If anything other than DMA completion is reported stop and hand * control back to zynq_fpga_ops_write, something went wrong, * otherwise progress the DMA.
*/
spin_lock(&priv->dma_lock);
intr_status = zynq_fpga_read(priv, INT_STS_OFFSET); if (!(intr_status & IXR_ERROR_FLAGS_MASK) &&
(intr_status & IXR_DMA_DONE_MASK) && priv->cur_sg) {
zynq_fpga_write(priv, INT_STS_OFFSET, IXR_DMA_DONE_MASK);
zynq_step_dma(priv);
spin_unlock(&priv->dma_lock); return IRQ_HANDLED;
}
spin_unlock(&priv->dma_lock);
/* Sanity check the proposed bitstream. It must start with the sync word in * the correct byte order, and be dword aligned. The input is a Xilinx .bin * file with every 32 bit quantity swapped.
*/ staticbool zynq_fpga_has_sync(const u8 *buf, size_t count)
{ for (; count >= 4; buf += 4, count -= 4) if (buf[0] == 0x66 && buf[1] == 0x55 && buf[2] == 0x99 &&
buf[3] == 0xaa) returntrue; returnfalse;
}
/* 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;
}
/* disable all level shifters */
regmap_write(priv->slcr, SLCR_LVL_SHFTR_EN_OFFSET,
LVL_SHFTR_DISABLE_ALL_MASK); /* enable level shifters from PS to PL */
regmap_write(priv->slcr, SLCR_LVL_SHFTR_EN_OFFSET,
LVL_SHFTR_ENABLE_PS_TO_PL);
/* create a rising edge on PCFG_INIT. PCFG_INIT follows * PCFG_PROG_B, so we need to poll it after setting PCFG_PROG_B * to make sure the rising edge actually happens. * Note: PCFG_PROG_B is low active, sequence as described in * UG585 v1.10 page 211
*/
ctrl = zynq_fpga_read(priv, CTRL_OFFSET);
ctrl |= CTRL_PCFG_PROG_B_MASK;
zynq_fpga_write(priv, CTRL_OFFSET, ctrl);
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;
}
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: * - enable PCAP interface * - set throughput for maximum speed (if bistream not encrypted) * - set CPU in user mode
*/
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 * starting addresses to be aligned to 64 bits (UG585 pg 212).
*/
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 * something went wrong we are relying on the hardware to have halted * the DMA before we get here, if there was we could use * wait_for_completion_interruptible too.
*/
/* 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.