linux/drivers/fpga/zynqmp-fpga.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2016 - 2019 Xilinx, Inc.
   4 */
   5
   6#include <linux/clk.h>
   7#include <linux/dma-mapping.h>
   8#include <linux/fpga/fpga-mgr.h>
   9#include <linux/io.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/of_address.h>
  13#include <linux/string.h>
  14#include <linux/seq_file.h>
  15#include <linux/firmware/xlnx-zynqmp.h>
  16
  17/* Constant Definitions */
  18#define IXR_FPGA_DONE_MASK      0X00000008U
  19#define IXR_FPGA_ENCRYPTION_EN  0x00000008U
  20
  21#define READ_DMA_SIZE           0x200
  22#define DUMMY_FRAMES_SIZE       0x64
  23#define PCAP_READ_CLKFREQ       25000000
  24
  25/* Error Register */
  26#define IXR_FPGA_ERR_CRC_ERR            BIT(0)
  27#define IXR_FPGA_ERR_SECURITY_ERR       BIT(16)
  28
  29/* Signal Status Register */
  30#define IXR_FPGA_END_OF_STARTUP         BIT(4)
  31#define IXR_FPGA_GST_CFG_B              BIT(5)
  32#define IXR_FPGA_INIT_B_INTERNAL        BIT(11)
  33#define IXR_FPGA_DONE_INTERNAL_SIGNAL   BIT(13)
  34
  35#define IXR_FPGA_CONFIG_STAT_OFFSET     7U
  36#define IXR_FPGA_READ_CONFIG_TYPE       0U
  37
  38static bool readback_type;
  39module_param(readback_type, bool, 0644);
  40MODULE_PARM_DESC(readback_type,
  41                 "readback_type 0-configuration register read "
  42                 "1- configuration data read (default: 0)");
  43
  44static const struct zynqmp_eemi_ops *eemi_ops;
  45
  46/**
  47 * struct zynqmp_configreg - Configuration register offsets
  48 * @reg:        Name of the configuration register.
  49 * @offset:     Register offset.
  50 */
  51struct zynqmp_configreg {
  52        char *reg;
  53        u32 offset;
  54};
  55
  56static struct zynqmp_configreg cfgreg[] = {
  57        {.reg = "CRC",          .offset = 0},
  58        {.reg = "FAR",          .offset = 1},
  59        {.reg = "FDRI",         .offset = 2},
  60        {.reg = "FDRO",         .offset = 3},
  61        {.reg = "CMD",          .offset = 4},
  62        {.reg = "CTRL0",        .offset = 5},
  63        {.reg = "MASK",         .offset = 6},
  64        {.reg = "STAT",         .offset = 7},
  65        {.reg = "LOUT",         .offset = 8},
  66        {.reg = "COR0",         .offset = 9},
  67        {.reg = "MFWR",         .offset = 10},
  68        {.reg = "CBC",          .offset = 11},
  69        {.reg = "IDCODE",       .offset = 12},
  70        {.reg = "AXSS",         .offset = 13},
  71        {.reg = "COR1",         .offset = 14},
  72        {.reg = "WBSTR",        .offset = 16},
  73        {.reg = "TIMER",        .offset = 17},
  74        {.reg = "BOOTSTS",      .offset = 22},
  75        {.reg = "CTRL1",        .offset = 24},
  76        {}
  77};
  78
  79/**
  80 * struct zynqmp_fpga_priv - Private data structure
  81 * @dev:        Device data structure
  82 * @lock:       Mutex lock for device
  83 * @clk:        Clock resource for pcap controller
  84 * @flags:      flags which is used to identify the bitfile type
  85 * @size:       Size of the Bitstream used for readback
  86 */
  87struct zynqmp_fpga_priv {
  88        struct device *dev;
  89        struct mutex lock;
  90        struct clk *clk;
  91        char *key;
  92        u32 flags;
  93        u32 size;
  94};
  95
  96static int zynqmp_fpga_ops_write_init(struct fpga_manager *mgr,
  97                                      struct fpga_image_info *info,
  98                                      const char *buf, size_t size)
  99{
 100        struct zynqmp_fpga_priv *priv;
 101
 102        priv = mgr->priv;
 103        priv->flags = info->flags;
 104        priv->key = info->key;
 105
 106        return 0;
 107}
 108
 109static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
 110                                        const char *buf, size_t size)
 111{
 112        struct zynqmp_fpga_priv *priv;
 113        char *kbuf;
 114        size_t dma_size;
 115        dma_addr_t dma_addr;
 116        int ret;
 117
 118        if (!eemi_ops->fpga_load)
 119                return -ENXIO;
 120
 121        priv = mgr->priv;
 122        priv->size = size;
 123
 124        if (!mutex_trylock(&priv->lock))
 125                return -EBUSY;
 126
 127        ret = clk_enable(priv->clk);
 128        if (ret)
 129                goto err_unlock;
 130
 131        if (priv->flags & IXR_FPGA_ENCRYPTION_EN)
 132                dma_size = size + ENCRYPTED_KEY_LEN;
 133        else
 134                dma_size = size;
 135
 136        kbuf = dma_alloc_coherent(priv->dev, dma_size, &dma_addr, GFP_KERNEL);
 137        if (!kbuf) {
 138                ret = -ENOMEM;
 139                goto disable_clk;
 140        }
 141
 142        memcpy(kbuf, buf, size);
 143
 144        if (priv->flags & IXR_FPGA_ENCRYPTION_EN)
 145                memcpy(kbuf + size, priv->key, ENCRYPTED_KEY_LEN);
 146
 147        wmb(); /* ensure all writes are done before initiate FW call */
 148
 149        if (priv->flags & IXR_FPGA_ENCRYPTION_EN)
 150                ret = eemi_ops->fpga_load(dma_addr, dma_addr + size,
 151                                          priv->flags);
 152        else
 153                ret = eemi_ops->fpga_load(dma_addr, size, priv->flags);
 154
 155        dma_free_coherent(priv->dev, dma_size, kbuf, dma_addr);
 156disable_clk:
 157        clk_disable(priv->clk);
 158err_unlock:
 159        mutex_unlock(&priv->lock);
 160        return ret;
 161}
 162
 163static int zynqmp_fpga_ops_write_complete(struct fpga_manager *mgr,
 164                                          struct fpga_image_info *info)
 165{
 166        return 0;
 167}
 168
 169static enum fpga_mgr_states zynqmp_fpga_ops_state(struct fpga_manager *mgr)
 170{
 171        u32 status;
 172
 173        if (!eemi_ops->fpga_get_status)
 174                return FPGA_MGR_STATE_UNKNOWN;
 175
 176        eemi_ops->fpga_get_status(&status);
 177        if (status & IXR_FPGA_DONE_MASK)
 178                return FPGA_MGR_STATE_OPERATING;
 179
 180        return FPGA_MGR_STATE_UNKNOWN;
 181}
 182
 183static u64 zynqmp_fpga_ops_status(struct fpga_manager *mgr)
 184{
 185        const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 186        unsigned int *buf, reg_val;
 187        dma_addr_t dma_addr;
 188        u64 status = 0;
 189        int ret;
 190
 191        if (IS_ERR_OR_NULL(eemi_ops) || !eemi_ops->fpga_read)
 192                return FPGA_MGR_STATUS_FIRMWARE_REQ_ERR;
 193
 194        buf = dma_zalloc_coherent(mgr->dev.parent, READ_DMA_SIZE,
 195                                  &dma_addr, GFP_KERNEL);
 196        if (!buf)
 197                return FPGA_MGR_STATUS_FIRMWARE_REQ_ERR;
 198
 199        ret = eemi_ops->fpga_read(IXR_FPGA_CONFIG_STAT_OFFSET, dma_addr,
 200                                  IXR_FPGA_READ_CONFIG_TYPE, &reg_val);
 201        if (ret) {
 202                status = FPGA_MGR_STATUS_FIRMWARE_REQ_ERR;
 203                goto free_dmabuf;
 204        }
 205
 206        if (reg_val & IXR_FPGA_ERR_CRC_ERR)
 207                status |= FPGA_MGR_STATUS_CRC_ERR;
 208        if (reg_val & IXR_FPGA_ERR_SECURITY_ERR)
 209                status |= FPGA_MGR_STATUS_SECURITY_ERR;
 210        if (!(reg_val & IXR_FPGA_INIT_B_INTERNAL))
 211                status |= FPGA_MGR_STATUS_DEVICE_INIT_ERR;
 212        if (!(reg_val & IXR_FPGA_DONE_INTERNAL_SIGNAL))
 213                status |= FPGA_MGR_STATUS_SIGNAL_ERR;
 214        if (!(reg_val & IXR_FPGA_GST_CFG_B))
 215                status |= FPGA_MGR_STATUS_HIGH_Z_STATE_ERR;
 216        if (!(reg_val & IXR_FPGA_END_OF_STARTUP))
 217                status |= FPGA_MGR_STATUS_EOS_ERR;
 218
 219free_dmabuf:
 220        dma_free_coherent(mgr->dev.parent, READ_DMA_SIZE, buf, dma_addr);
 221
 222        return status;
 223}
 224
 225static int zynqmp_fpga_read_cfgreg(struct fpga_manager *mgr,
 226                                   struct seq_file *s)
 227{
 228        struct zynqmp_fpga_priv *priv = mgr->priv;
 229        int ret, val;
 230        unsigned int *buf;
 231        dma_addr_t dma_addr;
 232        struct zynqmp_configreg *p = cfgreg;
 233
 234        ret = clk_enable(priv->clk);
 235        if (ret)
 236                return ret;
 237
 238        buf = dma_zalloc_coherent(mgr->dev.parent, READ_DMA_SIZE,
 239                                  &dma_addr, GFP_KERNEL);
 240        if (!buf) {
 241                ret = -ENOMEM;
 242                goto disable_clk;
 243        }
 244
 245        seq_puts(s, "zynqMP FPGA Configuration register contents are\n");
 246
 247        while (p->reg) {
 248                ret = eemi_ops->fpga_read(p->offset, dma_addr, readback_type,
 249                                          &val);
 250                if (ret)
 251                        goto free_dmabuf;
 252                seq_printf(s, "%s --> \t %x \t\r\n", p->reg, val);
 253                p++;
 254        }
 255
 256free_dmabuf:
 257        dma_free_coherent(mgr->dev.parent, READ_DMA_SIZE, buf,
 258                          dma_addr);
 259disable_clk:
 260        clk_disable(priv->clk);
 261
 262        return ret;
 263}
 264
 265static int zynqmp_fpga_read_cfgdata(struct fpga_manager *mgr,
 266                                    struct seq_file *s)
 267{
 268        struct zynqmp_fpga_priv *priv;
 269        int ret, data_offset;
 270        unsigned int *buf;
 271        dma_addr_t dma_addr;
 272        size_t size;
 273        int clk_rate;
 274
 275        priv = mgr->priv;
 276        size = priv->size + READ_DMA_SIZE + DUMMY_FRAMES_SIZE;
 277
 278        /*
 279         * There is no h/w flow control for pcap read
 280         * to prevent the FIFO from over flowing, reduce
 281         * the PCAP operating frequency.
 282         */
 283        clk_rate = clk_get_rate(priv->clk);
 284        clk_unprepare(priv->clk);
 285        ret = clk_set_rate(priv->clk, PCAP_READ_CLKFREQ);
 286        if (ret) {
 287                dev_err(&mgr->dev, "Unable to reduce the PCAP freq %d\n", ret);
 288                goto prepare_clk;
 289        }
 290        ret = clk_prepare_enable(priv->clk);
 291        if (ret) {
 292                dev_err(&mgr->dev, "Cannot enable clock.\n");
 293                goto restore_pcap_clk;
 294        }
 295
 296        buf = dma_zalloc_coherent(mgr->dev.parent, size, &dma_addr,
 297                                  GFP_KERNEL);
 298        if (!buf) {
 299                ret = -ENOMEM;
 300                goto disable_clk;
 301        }
 302
 303        seq_puts(s, "zynqMP FPGA Configuration data contents are\n");
 304        ret = eemi_ops->fpga_read((priv->size + DUMMY_FRAMES_SIZE) / 4,
 305                                  dma_addr, readback_type, &data_offset);
 306        if (ret)
 307                goto free_dmabuf;
 308
 309        seq_write(s, &buf[data_offset], priv->size);
 310
 311free_dmabuf:
 312        dma_free_coherent(mgr->dev.parent, size, buf, dma_addr);
 313disable_clk:
 314        clk_disable_unprepare(priv->clk);
 315restore_pcap_clk:
 316        clk_set_rate(priv->clk, clk_rate);
 317prepare_clk:
 318        clk_prepare(priv->clk);
 319
 320        return ret;
 321}
 322
 323static int zynqmp_fpga_ops_read(struct fpga_manager *mgr, struct seq_file *s)
 324{
 325        struct zynqmp_fpga_priv *priv = mgr->priv;
 326        int ret;
 327
 328        if (!eemi_ops->fpga_read)
 329                return -ENXIO;
 330
 331        if (!mutex_trylock(&priv->lock))
 332                return -EBUSY;
 333
 334        if (readback_type)
 335                ret = zynqmp_fpga_read_cfgdata(mgr, s);
 336        else
 337                ret = zynqmp_fpga_read_cfgreg(mgr, s);
 338
 339        mutex_unlock(&priv->lock);
 340        return ret;
 341}
 342
 343static const struct fpga_manager_ops zynqmp_fpga_ops = {
 344        .state = zynqmp_fpga_ops_state,
 345        .status = zynqmp_fpga_ops_status,
 346        .write_init = zynqmp_fpga_ops_write_init,
 347        .write = zynqmp_fpga_ops_write,
 348        .write_complete = zynqmp_fpga_ops_write_complete,
 349        .read = zynqmp_fpga_ops_read,
 350};
 351
 352static int zynqmp_fpga_probe(struct platform_device *pdev)
 353{
 354        struct device *dev = &pdev->dev;
 355        struct zynqmp_fpga_priv *priv;
 356        int err, ret;
 357        struct fpga_manager *mgr;
 358
 359        eemi_ops = zynqmp_pm_get_eemi_ops();
 360        if (IS_ERR(eemi_ops))
 361                return PTR_ERR(eemi_ops);
 362
 363        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 364        if (!priv)
 365                return -ENOMEM;
 366
 367        priv->dev = dev;
 368        mutex_init(&priv->lock);
 369        ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
 370        if (ret < 0)
 371                dev_err(dev, "no usable DMA configuration");
 372
 373        mgr = fpga_mgr_create(dev, "Xilinx ZynqMP FPGA Manager",
 374                              &zynqmp_fpga_ops, priv);
 375        if (!mgr)
 376                return -ENOMEM;
 377
 378        platform_set_drvdata(pdev, mgr);
 379
 380        priv->clk = devm_clk_get(dev, "ref_clk");
 381        if (IS_ERR(priv->clk)) {
 382                ret = PTR_ERR(priv->clk);
 383                dev_err(dev, "failed to to get pcp ref_clk (%d)\n", ret);
 384                return ret;
 385        }
 386
 387        ret = clk_prepare(priv->clk);
 388        if (ret) {
 389                dev_err(dev, "Cannot enable clock.\n");
 390                return ret;
 391        }
 392
 393        err = fpga_mgr_register(mgr);
 394        if (err) {
 395                dev_err(dev, "unable to register FPGA manager");
 396                fpga_mgr_free(mgr);
 397                clk_unprepare(priv->clk);
 398                return err;
 399        }
 400
 401        return 0;
 402}
 403
 404static int zynqmp_fpga_remove(struct platform_device *pdev)
 405{
 406        struct zynqmp_fpga_priv *priv;
 407        struct fpga_manager *mgr;
 408
 409        mgr = platform_get_drvdata(pdev);
 410        priv = mgr->priv;
 411
 412        fpga_mgr_unregister(mgr);
 413        clk_unprepare(priv->clk);
 414
 415        return 0;
 416}
 417
 418static const struct of_device_id zynqmp_fpga_of_match[] = {
 419        { .compatible = "xlnx,zynqmp-pcap-fpga", },
 420        {},
 421};
 422
 423MODULE_DEVICE_TABLE(of, zynqmp_fpga_of_match);
 424
 425static struct platform_driver zynqmp_fpga_driver = {
 426        .probe = zynqmp_fpga_probe,
 427        .remove = zynqmp_fpga_remove,
 428        .driver = {
 429                .name = "zynqmp_fpga_manager",
 430                .of_match_table = of_match_ptr(zynqmp_fpga_of_match),
 431        },
 432};
 433
 434module_platform_driver(zynqmp_fpga_driver);
 435
 436MODULE_AUTHOR("Nava kishore Manne <navam@xilinx.com>");
 437MODULE_DESCRIPTION("Xilinx ZynqMp FPGA Manager");
 438MODULE_LICENSE("GPL");
 439