root/drivers/fpga/altera-pr-ip-core.c

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

DEFINITIONS

This source file includes following definitions.
  1. alt_pr_fpga_state
  2. alt_pr_fpga_write_init
  3. alt_pr_fpga_write
  4. alt_pr_fpga_write_complete
  5. alt_pr_register
  6. alt_pr_unregister

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Driver for Altera Partial Reconfiguration IP Core
   4  *
   5  * Copyright (C) 2016-2017 Intel Corporation
   6  *
   7  * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation
   8  *  by Alan Tull <atull@opensource.altera.com>
   9  */
  10 #include <linux/delay.h>
  11 #include <linux/fpga/altera-pr-ip-core.h>
  12 #include <linux/fpga/fpga-mgr.h>
  13 #include <linux/module.h>
  14 
  15 #define ALT_PR_DATA_OFST                0x00
  16 #define ALT_PR_CSR_OFST                 0x04
  17 
  18 #define ALT_PR_CSR_PR_START             BIT(0)
  19 #define ALT_PR_CSR_STATUS_SFT           2
  20 #define ALT_PR_CSR_STATUS_MSK           (7 << ALT_PR_CSR_STATUS_SFT)
  21 #define ALT_PR_CSR_STATUS_NRESET        (0 << ALT_PR_CSR_STATUS_SFT)
  22 #define ALT_PR_CSR_STATUS_PR_ERR        (1 << ALT_PR_CSR_STATUS_SFT)
  23 #define ALT_PR_CSR_STATUS_CRC_ERR       (2 << ALT_PR_CSR_STATUS_SFT)
  24 #define ALT_PR_CSR_STATUS_BAD_BITS      (3 << ALT_PR_CSR_STATUS_SFT)
  25 #define ALT_PR_CSR_STATUS_PR_IN_PROG    (4 << ALT_PR_CSR_STATUS_SFT)
  26 #define ALT_PR_CSR_STATUS_PR_SUCCESS    (5 << ALT_PR_CSR_STATUS_SFT)
  27 
  28 struct alt_pr_priv {
  29         void __iomem *reg_base;
  30 };
  31 
  32 static enum fpga_mgr_states alt_pr_fpga_state(struct fpga_manager *mgr)
  33 {
  34         struct alt_pr_priv *priv = mgr->priv;
  35         const char *err = "unknown";
  36         enum fpga_mgr_states ret = FPGA_MGR_STATE_UNKNOWN;
  37         u32 val;
  38 
  39         val = readl(priv->reg_base + ALT_PR_CSR_OFST);
  40 
  41         val &= ALT_PR_CSR_STATUS_MSK;
  42 
  43         switch (val) {
  44         case ALT_PR_CSR_STATUS_NRESET:
  45                 return FPGA_MGR_STATE_RESET;
  46 
  47         case ALT_PR_CSR_STATUS_PR_ERR:
  48                 err = "pr error";
  49                 ret = FPGA_MGR_STATE_WRITE_ERR;
  50                 break;
  51 
  52         case ALT_PR_CSR_STATUS_CRC_ERR:
  53                 err = "crc error";
  54                 ret = FPGA_MGR_STATE_WRITE_ERR;
  55                 break;
  56 
  57         case ALT_PR_CSR_STATUS_BAD_BITS:
  58                 err = "bad bits";
  59                 ret = FPGA_MGR_STATE_WRITE_ERR;
  60                 break;
  61 
  62         case ALT_PR_CSR_STATUS_PR_IN_PROG:
  63                 return FPGA_MGR_STATE_WRITE;
  64 
  65         case ALT_PR_CSR_STATUS_PR_SUCCESS:
  66                 return FPGA_MGR_STATE_OPERATING;
  67 
  68         default:
  69                 break;
  70         }
  71 
  72         dev_err(&mgr->dev, "encountered error code %d (%s) in %s()\n",
  73                 val, err, __func__);
  74         return ret;
  75 }
  76 
  77 static int alt_pr_fpga_write_init(struct fpga_manager *mgr,
  78                                   struct fpga_image_info *info,
  79                                   const char *buf, size_t count)
  80 {
  81         struct alt_pr_priv *priv = mgr->priv;
  82         u32 val;
  83 
  84         if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
  85                 dev_err(&mgr->dev, "%s Partial Reconfiguration flag not set\n",
  86                         __func__);
  87                 return -EINVAL;
  88         }
  89 
  90         val = readl(priv->reg_base + ALT_PR_CSR_OFST);
  91 
  92         if (val & ALT_PR_CSR_PR_START) {
  93                 dev_err(&mgr->dev,
  94                         "%s Partial Reconfiguration already started\n",
  95                        __func__);
  96                 return -EINVAL;
  97         }
  98 
  99         writel(val | ALT_PR_CSR_PR_START, priv->reg_base + ALT_PR_CSR_OFST);
 100 
 101         return 0;
 102 }
 103 
 104 static int alt_pr_fpga_write(struct fpga_manager *mgr, const char *buf,
 105                              size_t count)
 106 {
 107         struct alt_pr_priv *priv = mgr->priv;
 108         u32 *buffer_32 = (u32 *)buf;
 109         size_t i = 0;
 110 
 111         if (count <= 0)
 112                 return -EINVAL;
 113 
 114         /* Write out the complete 32-bit chunks */
 115         while (count >= sizeof(u32)) {
 116                 writel(buffer_32[i++], priv->reg_base);
 117                 count -= sizeof(u32);
 118         }
 119 
 120         /* Write out remaining non 32-bit chunks */
 121         switch (count) {
 122         case 3:
 123                 writel(buffer_32[i++] & 0x00ffffff, priv->reg_base);
 124                 break;
 125         case 2:
 126                 writel(buffer_32[i++] & 0x0000ffff, priv->reg_base);
 127                 break;
 128         case 1:
 129                 writel(buffer_32[i++] & 0x000000ff, priv->reg_base);
 130                 break;
 131         case 0:
 132                 break;
 133         default:
 134                 /* This will never happen */
 135                 return -EFAULT;
 136         }
 137 
 138         if (alt_pr_fpga_state(mgr) == FPGA_MGR_STATE_WRITE_ERR)
 139                 return -EIO;
 140 
 141         return 0;
 142 }
 143 
 144 static int alt_pr_fpga_write_complete(struct fpga_manager *mgr,
 145                                       struct fpga_image_info *info)
 146 {
 147         u32 i = 0;
 148 
 149         do {
 150                 switch (alt_pr_fpga_state(mgr)) {
 151                 case FPGA_MGR_STATE_WRITE_ERR:
 152                         return -EIO;
 153 
 154                 case FPGA_MGR_STATE_OPERATING:
 155                         dev_info(&mgr->dev,
 156                                  "successful partial reconfiguration\n");
 157                         return 0;
 158 
 159                 default:
 160                         break;
 161                 }
 162                 udelay(1);
 163         } while (info->config_complete_timeout_us > i++);
 164 
 165         dev_err(&mgr->dev, "timed out waiting for write to complete\n");
 166         return -ETIMEDOUT;
 167 }
 168 
 169 static const struct fpga_manager_ops alt_pr_ops = {
 170         .state = alt_pr_fpga_state,
 171         .write_init = alt_pr_fpga_write_init,
 172         .write = alt_pr_fpga_write,
 173         .write_complete = alt_pr_fpga_write_complete,
 174 };
 175 
 176 int alt_pr_register(struct device *dev, void __iomem *reg_base)
 177 {
 178         struct alt_pr_priv *priv;
 179         struct fpga_manager *mgr;
 180         u32 val;
 181 
 182         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 183         if (!priv)
 184                 return -ENOMEM;
 185 
 186         priv->reg_base = reg_base;
 187 
 188         val = readl(priv->reg_base + ALT_PR_CSR_OFST);
 189 
 190         dev_dbg(dev, "%s status=%d start=%d\n", __func__,
 191                 (val & ALT_PR_CSR_STATUS_MSK) >> ALT_PR_CSR_STATUS_SFT,
 192                 (int)(val & ALT_PR_CSR_PR_START));
 193 
 194         mgr = devm_fpga_mgr_create(dev, dev_name(dev), &alt_pr_ops, priv);
 195         if (!mgr)
 196                 return -ENOMEM;
 197 
 198         dev_set_drvdata(dev, mgr);
 199 
 200         return fpga_mgr_register(mgr);
 201 }
 202 EXPORT_SYMBOL_GPL(alt_pr_register);
 203 
 204 void alt_pr_unregister(struct device *dev)
 205 {
 206         struct fpga_manager *mgr = dev_get_drvdata(dev);
 207 
 208         dev_dbg(dev, "%s\n", __func__);
 209 
 210         fpga_mgr_unregister(mgr);
 211 }
 212 EXPORT_SYMBOL_GPL(alt_pr_unregister);
 213 
 214 MODULE_AUTHOR("Matthew Gerlach <matthew.gerlach@linux.intel.com>");
 215 MODULE_DESCRIPTION("Altera Partial Reconfiguration IP Core");
 216 MODULE_LICENSE("GPL v2");

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