root/drivers/fpga/zynqmp-fpga.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zynqmp_fpga_ops_write_init
  2. zynqmp_fpga_ops_write
  3. zynqmp_fpga_ops_write_complete
  4. zynqmp_fpga_ops_state
  5. zynqmp_fpga_probe
  6. zynqmp_fpga_remove

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Copyright (C) 2019 Xilinx, Inc.
   4  */
   5 
   6 #include <linux/dma-mapping.h>
   7 #include <linux/fpga/fpga-mgr.h>
   8 #include <linux/io.h>
   9 #include <linux/kernel.h>
  10 #include <linux/module.h>
  11 #include <linux/of_address.h>
  12 #include <linux/string.h>
  13 #include <linux/firmware/xlnx-zynqmp.h>
  14 
  15 /* Constant Definitions */
  16 #define IXR_FPGA_DONE_MASK      BIT(3)
  17 
  18 /**
  19  * struct zynqmp_fpga_priv - Private data structure
  20  * @dev:        Device data structure
  21  * @flags:      flags which is used to identify the bitfile type
  22  */
  23 struct zynqmp_fpga_priv {
  24         struct device *dev;
  25         u32 flags;
  26 };
  27 
  28 static int zynqmp_fpga_ops_write_init(struct fpga_manager *mgr,
  29                                       struct fpga_image_info *info,
  30                                       const char *buf, size_t size)
  31 {
  32         struct zynqmp_fpga_priv *priv;
  33 
  34         priv = mgr->priv;
  35         priv->flags = info->flags;
  36 
  37         return 0;
  38 }
  39 
  40 static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
  41                                  const char *buf, size_t size)
  42 {
  43         const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
  44         struct zynqmp_fpga_priv *priv;
  45         dma_addr_t dma_addr;
  46         u32 eemi_flags = 0;
  47         char *kbuf;
  48         int ret;
  49 
  50         if (IS_ERR_OR_NULL(eemi_ops) || !eemi_ops->fpga_load)
  51                 return -ENXIO;
  52 
  53         priv = mgr->priv;
  54 
  55         kbuf = dma_alloc_coherent(priv->dev, size, &dma_addr, GFP_KERNEL);
  56         if (!kbuf)
  57                 return -ENOMEM;
  58 
  59         memcpy(kbuf, buf, size);
  60 
  61         wmb(); /* ensure all writes are done before initiate FW call */
  62 
  63         if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG)
  64                 eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL;
  65 
  66         ret = eemi_ops->fpga_load(dma_addr, size, eemi_flags);
  67 
  68         dma_free_coherent(priv->dev, size, kbuf, dma_addr);
  69 
  70         return ret;
  71 }
  72 
  73 static int zynqmp_fpga_ops_write_complete(struct fpga_manager *mgr,
  74                                           struct fpga_image_info *info)
  75 {
  76         return 0;
  77 }
  78 
  79 static enum fpga_mgr_states zynqmp_fpga_ops_state(struct fpga_manager *mgr)
  80 {
  81         const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
  82         u32 status;
  83 
  84         if (IS_ERR_OR_NULL(eemi_ops) || !eemi_ops->fpga_get_status)
  85                 return FPGA_MGR_STATE_UNKNOWN;
  86 
  87         eemi_ops->fpga_get_status(&status);
  88         if (status & IXR_FPGA_DONE_MASK)
  89                 return FPGA_MGR_STATE_OPERATING;
  90 
  91         return FPGA_MGR_STATE_UNKNOWN;
  92 }
  93 
  94 static const struct fpga_manager_ops zynqmp_fpga_ops = {
  95         .state = zynqmp_fpga_ops_state,
  96         .write_init = zynqmp_fpga_ops_write_init,
  97         .write = zynqmp_fpga_ops_write,
  98         .write_complete = zynqmp_fpga_ops_write_complete,
  99 };
 100 
 101 static int zynqmp_fpga_probe(struct platform_device *pdev)
 102 {
 103         struct device *dev = &pdev->dev;
 104         struct zynqmp_fpga_priv *priv;
 105         struct fpga_manager *mgr;
 106         int ret;
 107 
 108         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 109         if (!priv)
 110                 return -ENOMEM;
 111 
 112         priv->dev = dev;
 113 
 114         mgr = devm_fpga_mgr_create(dev, "Xilinx ZynqMP FPGA Manager",
 115                                    &zynqmp_fpga_ops, priv);
 116         if (!mgr)
 117                 return -ENOMEM;
 118 
 119         platform_set_drvdata(pdev, mgr);
 120 
 121         ret = fpga_mgr_register(mgr);
 122         if (ret) {
 123                 dev_err(dev, "unable to register FPGA manager");
 124                 return ret;
 125         }
 126 
 127         return 0;
 128 }
 129 
 130 static int zynqmp_fpga_remove(struct platform_device *pdev)
 131 {
 132         struct fpga_manager *mgr = platform_get_drvdata(pdev);
 133 
 134         fpga_mgr_unregister(mgr);
 135 
 136         return 0;
 137 }
 138 
 139 static const struct of_device_id zynqmp_fpga_of_match[] = {
 140         { .compatible = "xlnx,zynqmp-pcap-fpga", },
 141         {},
 142 };
 143 
 144 MODULE_DEVICE_TABLE(of, zynqmp_fpga_of_match);
 145 
 146 static struct platform_driver zynqmp_fpga_driver = {
 147         .probe = zynqmp_fpga_probe,
 148         .remove = zynqmp_fpga_remove,
 149         .driver = {
 150                 .name = "zynqmp_fpga_manager",
 151                 .of_match_table = of_match_ptr(zynqmp_fpga_of_match),
 152         },
 153 };
 154 
 155 module_platform_driver(zynqmp_fpga_driver);
 156 
 157 MODULE_AUTHOR("Nava kishore Manne <navam@xilinx.com>");
 158 MODULE_DESCRIPTION("Xilinx ZynqMp FPGA Manager");
 159 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */