aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/fpga/zynq-fpga.c
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2017-02-01 14:48:43 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-02-10 09:20:44 -0500
commitb496df86ac1bbe393a55ddbfed35d46e74ef9767 (patch)
tree0f87f727e68acab692280c556f6376237a68c64a /drivers/fpga/zynq-fpga.c
parent6b45e0f24c7b5316dea7ed5995e1b809a3266b43 (diff)
fpga zynq: Check the bitstream for validity
There is no sense in sending a bitstream we know will not work, and with the variety of options for bitstream generation in Xilinx tools it is not terribly clear what the correct input should be. This is particularly important for Zynq since auto-correction was removed from the driver and the Zynq hardware only accepts a bitstream format that is different from what the Xilinx tools typically produce. Worse, the hardware provides no indication why the bitstream fails, it simply times out if the input is wrong. The best option here is to have the kernel print a message informing the user they are using a malformed bistream and programming failure isn't for any of the myriad of other reasons. Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Acked-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.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index f674e32832ec..c3fc2a231e28 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -161,6 +161,19 @@ static irqreturn_t zynq_fpga_isr(int irq, void *data)
161 return IRQ_HANDLED; 161 return IRQ_HANDLED;
162} 162}
163 163
164/* Sanity check the proposed bitstream. It must start with the sync word in
165 * the correct byte order, and be dword aligned. The input is a Xilinx .bin
166 * file with every 32 bit quantity swapped.
167 */
168static bool zynq_fpga_has_sync(const u8 *buf, size_t count)
169{
170 for (; count >= 4; buf += 4, count -= 4)
171 if (buf[0] == 0x66 && buf[1] == 0x55 && buf[2] == 0x99 &&
172 buf[3] == 0xaa)
173 return true;
174 return false;
175}
176
164static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, 177static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
165 struct fpga_image_info *info, 178 struct fpga_image_info *info,
166 const char *buf, size_t count) 179 const char *buf, size_t count)
@@ -177,6 +190,13 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
177 190
178 /* don't globally reset PL if we're doing partial reconfig */ 191 /* don't globally reset PL if we're doing partial reconfig */
179 if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) { 192 if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
193 if (!zynq_fpga_has_sync(buf, count)) {
194 dev_err(&mgr->dev,
195 "Invalid bitstream, could not find a sync word. Bitstream must be a byte swapped .bin file\n");
196 err = -EINVAL;
197 goto out_err;
198 }
199
180 /* assert AXI interface resets */ 200 /* assert AXI interface resets */
181 regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET, 201 regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET,
182 FPGA_RST_ALL_MASK); 202 FPGA_RST_ALL_MASK);
@@ -410,6 +430,7 @@ static enum fpga_mgr_states zynq_fpga_ops_state(struct fpga_manager *mgr)
410} 430}
411 431
412static const struct fpga_manager_ops zynq_fpga_ops = { 432static const struct fpga_manager_ops zynq_fpga_ops = {
433 .initial_header_size = 128,
413 .state = zynq_fpga_ops_state, 434 .state = zynq_fpga_ops_state,
414 .write_init = zynq_fpga_ops_write_init, 435 .write_init = zynq_fpga_ops_write_init,
415 .write = zynq_fpga_ops_write, 436 .write = zynq_fpga_ops_write,