aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/fpga/zynq-fpga.c
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2017-02-01 14:48:42 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-02-10 09:20:44 -0500
commit6b45e0f24c7b5316dea7ed5995e1b809a3266b43 (patch)
tree4187f662de96e222040b4c7068d34a15678fac83 /drivers/fpga/zynq-fpga.c
parentcb97fbbcac15982406e0c74cd5512a8b6fcf10b3 (diff)
fpga zynq: Check for errors after completing DMA
The completion did not check the interrupt status to see if any error bits were asserted, check error bits and dump some registers if things went wrong. A few fixes are needed to make this work, the IXR_ERROR_FLAGS_MASK was wrong, it included the done bits, which shows a bug in mask/unmask_irqs which were using the wrong bits, simplify all of this stuff. Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Reviewed-by: Moritz Fischer <moritz.fischer@ettus.com> Acked-by: Alan Tull <atull@opensource.altera.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/fpga/zynq-fpga.c')
-rw-r--r--drivers/fpga/zynq-fpga.c54
1 files changed, 32 insertions, 22 deletions
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index 1812bf7614e1..f674e32832ec 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -89,7 +89,7 @@
89#define IXR_D_P_DONE_MASK BIT(12) 89#define IXR_D_P_DONE_MASK BIT(12)
90 /* FPGA programmed */ 90 /* FPGA programmed */
91#define IXR_PCFG_DONE_MASK BIT(2) 91#define IXR_PCFG_DONE_MASK BIT(2)
92#define IXR_ERROR_FLAGS_MASK 0x00F0F860 92#define IXR_ERROR_FLAGS_MASK 0x00F0C860
93#define IXR_ALL_MASK 0xF8F7F87F 93#define IXR_ALL_MASK 0xF8F7F87F
94 94
95/* Miscellaneous constant values */ 95/* Miscellaneous constant values */
@@ -143,23 +143,10 @@ static inline u32 zynq_fpga_read(const struct zynq_fpga_priv *priv,
143 readl_poll_timeout(priv->io_base + addr, val, cond, sleep_us, \ 143 readl_poll_timeout(priv->io_base + addr, val, cond, sleep_us, \
144 timeout_us) 144 timeout_us)
145 145
146static void zynq_fpga_mask_irqs(struct zynq_fpga_priv *priv) 146/* Cause the specified irq mask bits to generate IRQs */
147static inline void zynq_fpga_set_irq(struct zynq_fpga_priv *priv, u32 enable)
147{ 148{
148 u32 intr_mask; 149 zynq_fpga_write(priv, INT_MASK_OFFSET, ~enable);
149
150 intr_mask = zynq_fpga_read(priv, INT_MASK_OFFSET);
151 zynq_fpga_write(priv, INT_MASK_OFFSET,
152 intr_mask | IXR_DMA_DONE_MASK | IXR_ERROR_FLAGS_MASK);
153}
154
155static void zynq_fpga_unmask_irqs(struct zynq_fpga_priv *priv)
156{
157 u32 intr_mask;
158
159 intr_mask = zynq_fpga_read(priv, INT_MASK_OFFSET);
160 zynq_fpga_write(priv, INT_MASK_OFFSET,
161 intr_mask
162 & ~(IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK));
163} 150}
164 151
165static irqreturn_t zynq_fpga_isr(int irq, void *data) 152static irqreturn_t zynq_fpga_isr(int irq, void *data)
@@ -167,7 +154,7 @@ static irqreturn_t zynq_fpga_isr(int irq, void *data)
167 struct zynq_fpga_priv *priv = data; 154 struct zynq_fpga_priv *priv = data;
168 155
169 /* disable DMA and error IRQs */ 156 /* disable DMA and error IRQs */
170 zynq_fpga_mask_irqs(priv); 157 zynq_fpga_set_irq(priv, 0);
171 158
172 complete(&priv->dma_done); 159 complete(&priv->dma_done);
173 160
@@ -285,6 +272,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
285 const char *buf, size_t count) 272 const char *buf, size_t count)
286{ 273{
287 struct zynq_fpga_priv *priv; 274 struct zynq_fpga_priv *priv;
275 const char *why;
288 int err; 276 int err;
289 char *kbuf; 277 char *kbuf;
290 size_t in_count; 278 size_t in_count;
@@ -312,7 +300,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
312 reinit_completion(&priv->dma_done); 300 reinit_completion(&priv->dma_done);
313 301
314 /* enable DMA and error IRQs */ 302 /* enable DMA and error IRQs */
315 zynq_fpga_unmask_irqs(priv); 303 zynq_fpga_set_irq(priv, IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK);
316 304
317 /* the +1 in the src addr is used to hold off on DMA_DONE IRQ 305 /* the +1 in the src addr is used to hold off on DMA_DONE IRQ
318 * until both AXI and PCAP are done ... 306 * until both AXI and PCAP are done ...
@@ -331,11 +319,33 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
331 intr_status = zynq_fpga_read(priv, INT_STS_OFFSET); 319 intr_status = zynq_fpga_read(priv, INT_STS_OFFSET);
332 zynq_fpga_write(priv, INT_STS_OFFSET, intr_status); 320 zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
333 321
322 if (intr_status & IXR_ERROR_FLAGS_MASK) {
323 why = "DMA reported error";
324 err = -EIO;
325 goto out_report;
326 }
327
334 if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) { 328 if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
335 dev_err(&mgr->dev, "Error configuring FPGA\n"); 329 why = "DMA did not complete";
336 err = -EFAULT; 330 err = -EIO;
331 goto out_report;
337 } 332 }
338 333
334 err = 0;
335 goto out_clk;
336
337out_report:
338 dev_err(&mgr->dev,
339 "%s: INT_STS:0x%x CTRL:0x%x LOCK:0x%x INT_MASK:0x%x STATUS:0x%x MCTRL:0x%x\n",
340 why,
341 intr_status,
342 zynq_fpga_read(priv, CTRL_OFFSET),
343 zynq_fpga_read(priv, LOCK_OFFSET),
344 zynq_fpga_read(priv, INT_MASK_OFFSET),
345 zynq_fpga_read(priv, STATUS_OFFSET),
346 zynq_fpga_read(priv, MCTRL_OFFSET));
347
348out_clk:
339 clk_disable(priv->clk); 349 clk_disable(priv->clk);
340 350
341out_free: 351out_free:
@@ -452,7 +462,7 @@ static int zynq_fpga_probe(struct platform_device *pdev)
452 /* unlock the device */ 462 /* unlock the device */
453 zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK); 463 zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK);
454 464
455 zynq_fpga_write(priv, INT_MASK_OFFSET, 0xFFFFFFFF); 465 zynq_fpga_set_irq(priv, 0);
456 zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK); 466 zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
457 err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0, dev_name(dev), 467 err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0, dev_name(dev),
458 priv); 468 priv);