Преглед на файлове

Merge tag 'fpga-for-greg-20161129' of git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga into char-misc-next

Alan writes:

fpga: Updates for 4.10

These are:
 * Add git url to MAINTAINERS
 * Allow write_init to specify how much buffer it needs
 * Fixes for ISR state in zynq fpga manager driver
 * Other small fixes for zynq
 * Add Altera SoCFPGA drivers for COMPILE_TEST
Greg Kroah-Hartman преди 8 години
родител
ревизия
e073462966
променени са 7 файла, в които са добавени 38 реда и са изтрити 28 реда
  1. 4 1
      Documentation/fpga/fpga-mgr.txt
  2. 1 0
      MAINTAINERS
  3. 3 2
      drivers/fpga/Kconfig
  4. 4 2
      drivers/fpga/fpga-mgr.c
  5. 1 0
      drivers/fpga/socfpga-a10.c
  6. 23 23
      drivers/fpga/zynq-fpga.c
  7. 2 0
      include/linux/fpga/fpga-mgr.h

+ 4 - 1
Documentation/fpga/fpga-mgr.txt

@@ -169,7 +169,10 @@ The programming sequence is:
  2. .write (may be called once or multiple times)
  2. .write (may be called once or multiple times)
  3. .write_complete
  3. .write_complete
 
 
-The .write_init function will prepare the FPGA to receive the image data.
+The .write_init function will prepare the FPGA to receive the image data.  The
+buffer passed into .write_init will be atmost .initial_header_size bytes long,
+if the whole bitstream is not immediately available then the core code will
+buffer up at least this much before starting.
 
 
 The .write function writes a buffer to the FPGA. The buffer may be contain the
 The .write function writes a buffer to the FPGA. The buffer may be contain the
 whole FPGA image or may be a smaller chunk of an FPGA image.  In the latter
 whole FPGA image or may be a smaller chunk of an FPGA image.  In the latter

+ 1 - 0
MAINTAINERS

@@ -4958,6 +4958,7 @@ M:	Alan Tull <atull@opensource.altera.com>
 R:	Moritz Fischer <moritz.fischer@ettus.com>
 R:	Moritz Fischer <moritz.fischer@ettus.com>
 L:	linux-fpga@vger.kernel.org
 L:	linux-fpga@vger.kernel.org
 S:	Maintained
 S:	Maintained
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git
 F:	drivers/fpga/
 F:	drivers/fpga/
 F:	include/linux/fpga/fpga-mgr.h
 F:	include/linux/fpga/fpga-mgr.h
 W:	http://www.rocketboards.org
 W:	http://www.rocketboards.org

+ 3 - 2
drivers/fpga/Kconfig

@@ -22,13 +22,14 @@ config FPGA_REGION
 
 
 config FPGA_MGR_SOCFPGA
 config FPGA_MGR_SOCFPGA
 	tristate "Altera SOCFPGA FPGA Manager"
 	tristate "Altera SOCFPGA FPGA Manager"
-	depends on ARCH_SOCFPGA
+	depends on ARCH_SOCFPGA || COMPILE_TEST
 	help
 	help
 	  FPGA manager driver support for Altera SOCFPGA.
 	  FPGA manager driver support for Altera SOCFPGA.
 
 
 config FPGA_MGR_SOCFPGA_A10
 config FPGA_MGR_SOCFPGA_A10
 	tristate "Altera SoCFPGA Arria10"
 	tristate "Altera SoCFPGA Arria10"
-	depends on ARCH_SOCFPGA
+	depends on ARCH_SOCFPGA || COMPILE_TEST
+	select REGMAP_MMIO
 	help
 	help
 	  FPGA manager driver support for Altera Arria10 SoCFPGA.
 	  FPGA manager driver support for Altera Arria10 SoCFPGA.
 
 

+ 4 - 2
drivers/fpga/fpga-mgr.c

@@ -53,10 +53,12 @@ int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info,
 	/*
 	/*
 	 * Call the low level driver's write_init function.  This will do the
 	 * Call the low level driver's write_init function.  This will do the
 	 * device-specific things to get the FPGA into the state where it is
 	 * device-specific things to get the FPGA into the state where it is
-	 * ready to receive an FPGA image.
+	 * ready to receive an FPGA image. The low level driver only gets to
+	 * see the first initial_header_size bytes in the buffer.
 	 */
 	 */
 	mgr->state = FPGA_MGR_STATE_WRITE_INIT;
 	mgr->state = FPGA_MGR_STATE_WRITE_INIT;
-	ret = mgr->mops->write_init(mgr, info, buf, count);
+	ret = mgr->mops->write_init(mgr, info, buf,
+				    min(mgr->mops->initial_header_size, count));
 	if (ret) {
 	if (ret) {
 		dev_err(dev, "Error preparing FPGA for writing\n");
 		dev_err(dev, "Error preparing FPGA for writing\n");
 		mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
 		mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;

+ 1 - 0
drivers/fpga/socfpga-a10.c

@@ -470,6 +470,7 @@ static enum fpga_mgr_states socfpga_a10_fpga_state(struct fpga_manager *mgr)
 }
 }
 
 
 static const struct fpga_manager_ops socfpga_a10_fpga_mgr_ops = {
 static const struct fpga_manager_ops socfpga_a10_fpga_mgr_ops = {
+	.initial_header_size = (RBF_DECOMPRESS_OFFSET + 1) * 4,
 	.state = socfpga_a10_fpga_state,
 	.state = socfpga_a10_fpga_state,
 	.write_init = socfpga_a10_fpga_write_init,
 	.write_init = socfpga_a10_fpga_write_init,
 	.write = socfpga_a10_fpga_write,
 	.write = socfpga_a10_fpga_write,

+ 23 - 23
drivers/fpga/zynq-fpga.c

@@ -118,7 +118,6 @@
 #define FPGA_RST_NONE_MASK		0x0
 #define FPGA_RST_NONE_MASK		0x0
 
 
 struct zynq_fpga_priv {
 struct zynq_fpga_priv {
-	struct device *dev;
 	int irq;
 	int irq;
 	struct clk *clk;
 	struct clk *clk;
 
 
@@ -218,7 +217,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
 					     INIT_POLL_DELAY,
 					     INIT_POLL_DELAY,
 					     INIT_POLL_TIMEOUT);
 					     INIT_POLL_TIMEOUT);
 		if (err) {
 		if (err) {
-			dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
+			dev_err(&mgr->dev, "Timeout waiting for PCFG_INIT\n");
 			goto out_err;
 			goto out_err;
 		}
 		}
 
 
@@ -232,7 +231,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
 					     INIT_POLL_DELAY,
 					     INIT_POLL_DELAY,
 					     INIT_POLL_TIMEOUT);
 					     INIT_POLL_TIMEOUT);
 		if (err) {
 		if (err) {
-			dev_err(priv->dev, "Timeout waiting for !PCFG_INIT");
+			dev_err(&mgr->dev, "Timeout waiting for !PCFG_INIT\n");
 			goto out_err;
 			goto out_err;
 		}
 		}
 
 
@@ -246,7 +245,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
 					     INIT_POLL_DELAY,
 					     INIT_POLL_DELAY,
 					     INIT_POLL_TIMEOUT);
 					     INIT_POLL_TIMEOUT);
 		if (err) {
 		if (err) {
-			dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
+			dev_err(&mgr->dev, "Timeout waiting for PCFG_INIT\n");
 			goto out_err;
 			goto out_err;
 		}
 		}
 	}
 	}
@@ -263,7 +262,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
 	/* check that we have room in the command queue */
 	/* check that we have room in the command queue */
 	status = zynq_fpga_read(priv, STATUS_OFFSET);
 	status = zynq_fpga_read(priv, STATUS_OFFSET);
 	if (status & STATUS_DMA_Q_F) {
 	if (status & STATUS_DMA_Q_F) {
-		dev_err(priv->dev, "DMA command queue full");
+		dev_err(&mgr->dev, "DMA command queue full\n");
 		err = -EBUSY;
 		err = -EBUSY;
 		goto out_err;
 		goto out_err;
 	}
 	}
@@ -296,7 +295,8 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
 	in_count = count;
 	in_count = count;
 	priv = mgr->priv;
 	priv = mgr->priv;
 
 
-	kbuf = dma_alloc_coherent(priv->dev, count, &dma_addr, GFP_KERNEL);
+	kbuf =
+	    dma_alloc_coherent(mgr->dev.parent, count, &dma_addr, GFP_KERNEL);
 	if (!kbuf)
 	if (!kbuf)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
@@ -332,15 +332,14 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
 	zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
 	zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
 
 
 	if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
 	if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
-		dev_err(priv->dev, "Error configuring FPGA");
+		dev_err(&mgr->dev, "Error configuring FPGA\n");
 		err = -EFAULT;
 		err = -EFAULT;
 	}
 	}
 
 
 	clk_disable(priv->clk);
 	clk_disable(priv->clk);
 
 
 out_free:
 out_free:
-	dma_free_coherent(priv->dev, in_count, kbuf, dma_addr);
-
+	dma_free_coherent(mgr->dev.parent, count, kbuf, dma_addr);
 	return err;
 	return err;
 }
 }
 
 
@@ -418,8 +417,6 @@ static int zynq_fpga_probe(struct platform_device *pdev)
 	if (!priv)
 	if (!priv)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	priv->dev = dev;
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	priv->io_base = devm_ioremap_resource(dev, res);
 	priv->io_base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(priv->io_base))
 	if (IS_ERR(priv->io_base))
@@ -428,7 +425,7 @@ static int zynq_fpga_probe(struct platform_device *pdev)
 	priv->slcr = syscon_regmap_lookup_by_phandle(dev->of_node,
 	priv->slcr = syscon_regmap_lookup_by_phandle(dev->of_node,
 		"syscon");
 		"syscon");
 	if (IS_ERR(priv->slcr)) {
 	if (IS_ERR(priv->slcr)) {
-		dev_err(dev, "unable to get zynq-slcr regmap");
+		dev_err(dev, "unable to get zynq-slcr regmap\n");
 		return PTR_ERR(priv->slcr);
 		return PTR_ERR(priv->slcr);
 	}
 	}
 
 
@@ -436,38 +433,41 @@ static int zynq_fpga_probe(struct platform_device *pdev)
 
 
 	priv->irq = platform_get_irq(pdev, 0);
 	priv->irq = platform_get_irq(pdev, 0);
 	if (priv->irq < 0) {
 	if (priv->irq < 0) {
-		dev_err(dev, "No IRQ available");
+		dev_err(dev, "No IRQ available\n");
 		return priv->irq;
 		return priv->irq;
 	}
 	}
 
 
-	err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0,
-			       dev_name(dev), priv);
-	if (err) {
-		dev_err(dev, "unable to request IRQ");
-		return err;
-	}
-
 	priv->clk = devm_clk_get(dev, "ref_clk");
 	priv->clk = devm_clk_get(dev, "ref_clk");
 	if (IS_ERR(priv->clk)) {
 	if (IS_ERR(priv->clk)) {
-		dev_err(dev, "input clock not found");
+		dev_err(dev, "input clock not found\n");
 		return PTR_ERR(priv->clk);
 		return PTR_ERR(priv->clk);
 	}
 	}
 
 
 	err = clk_prepare_enable(priv->clk);
 	err = clk_prepare_enable(priv->clk);
 	if (err) {
 	if (err) {
-		dev_err(dev, "unable to enable clock");
+		dev_err(dev, "unable to enable clock\n");
 		return err;
 		return err;
 	}
 	}
 
 
 	/* unlock the device */
 	/* unlock the device */
 	zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK);
 	zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK);
 
 
+	zynq_fpga_write(priv, INT_MASK_OFFSET, 0xFFFFFFFF);
+	zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
+	err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0, dev_name(dev),
+			       priv);
+	if (err) {
+		dev_err(dev, "unable to request IRQ\n");
+		clk_disable_unprepare(priv->clk);
+		return err;
+	}
+
 	clk_disable(priv->clk);
 	clk_disable(priv->clk);
 
 
 	err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
 	err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
 				&zynq_fpga_ops, priv);
 				&zynq_fpga_ops, priv);
 	if (err) {
 	if (err) {
-		dev_err(dev, "unable to register FPGA manager");
+		dev_err(dev, "unable to register FPGA manager\n");
 		clk_unprepare(priv->clk);
 		clk_unprepare(priv->clk);
 		return err;
 		return err;
 	}
 	}

+ 2 - 0
include/linux/fpga/fpga-mgr.h

@@ -84,6 +84,7 @@ struct fpga_image_info {
 
 
 /**
 /**
  * struct fpga_manager_ops - ops for low level fpga manager drivers
  * struct fpga_manager_ops - ops for low level fpga manager drivers
+ * @initial_header_size: Maximum number of bytes that should be passed into write_init
  * @state: returns an enum value of the FPGA's state
  * @state: returns an enum value of the FPGA's state
  * @write_init: prepare the FPGA to receive confuration data
  * @write_init: prepare the FPGA to receive confuration data
  * @write: write count bytes of configuration data to the FPGA
  * @write: write count bytes of configuration data to the FPGA
@@ -95,6 +96,7 @@ struct fpga_image_info {
  * called, so leaving them out is fine.
  * called, so leaving them out is fine.
  */
  */
 struct fpga_manager_ops {
 struct fpga_manager_ops {
+	size_t initial_header_size;
 	enum fpga_mgr_states (*state)(struct fpga_manager *mgr);
 	enum fpga_mgr_states (*state)(struct fpga_manager *mgr);
 	int (*write_init)(struct fpga_manager *mgr,
 	int (*write_init)(struct fpga_manager *mgr,
 			  struct fpga_image_info *info,
 			  struct fpga_image_info *info,