linux/drivers/fpga/altera-cvp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * FPGA Manager Driver for Altera Arria/Cyclone/Stratix CvP
   4 *
   5 * Copyright (C) 2017 DENX Software Engineering
   6 *
   7 * Anatolij Gustschin <agust@denx.de>
   8 *
   9 * Manage Altera FPGA firmware using PCIe CvP.
  10 * Firmware must be in binary "rbf" format.
  11 */
  12
  13#include <linux/delay.h>
  14#include <linux/device.h>
  15#include <linux/fpga/fpga-mgr.h>
  16#include <linux/module.h>
  17#include <linux/pci.h>
  18#include <linux/sizes.h>
  19
  20#define CVP_BAR         0       /* BAR used for data transfer in memory mode */
  21#define CVP_DUMMY_WR    244     /* dummy writes to clear CvP state machine */
  22#define TIMEOUT_US      2000    /* CVP STATUS timeout for USERMODE polling */
  23
  24/* Vendor Specific Extended Capability Registers */
  25#define VSE_PCIE_EXT_CAP_ID             0x0
  26#define VSE_PCIE_EXT_CAP_ID_VAL         0x000b  /* 16bit */
  27
  28#define VSE_CVP_STATUS                  0x1c    /* 32bit */
  29#define VSE_CVP_STATUS_CFG_RDY          BIT(18) /* CVP_CONFIG_READY */
  30#define VSE_CVP_STATUS_CFG_ERR          BIT(19) /* CVP_CONFIG_ERROR */
  31#define VSE_CVP_STATUS_CVP_EN           BIT(20) /* ctrl block is enabling CVP */
  32#define VSE_CVP_STATUS_USERMODE         BIT(21) /* USERMODE */
  33#define VSE_CVP_STATUS_CFG_DONE         BIT(23) /* CVP_CONFIG_DONE */
  34#define VSE_CVP_STATUS_PLD_CLK_IN_USE   BIT(24) /* PLD_CLK_IN_USE */
  35
  36#define VSE_CVP_MODE_CTRL               0x20    /* 32bit */
  37#define VSE_CVP_MODE_CTRL_CVP_MODE      BIT(0)  /* CVP (1) or normal mode (0) */
  38#define VSE_CVP_MODE_CTRL_HIP_CLK_SEL   BIT(1) /* PMA (1) or fabric clock (0) */
  39#define VSE_CVP_MODE_CTRL_NUMCLKS_OFF   8       /* NUMCLKS bits offset */
  40#define VSE_CVP_MODE_CTRL_NUMCLKS_MASK  GENMASK(15, 8)
  41
  42#define VSE_CVP_DATA                    0x28    /* 32bit */
  43#define VSE_CVP_PROG_CTRL               0x2c    /* 32bit */
  44#define VSE_CVP_PROG_CTRL_CONFIG        BIT(0)
  45#define VSE_CVP_PROG_CTRL_START_XFER    BIT(1)
  46#define VSE_CVP_PROG_CTRL_MASK          GENMASK(1, 0)
  47
  48#define VSE_UNCOR_ERR_STATUS            0x34    /* 32bit */
  49#define VSE_UNCOR_ERR_CVP_CFG_ERR       BIT(5)  /* CVP_CONFIG_ERROR_LATCHED */
  50
  51#define V1_VSEC_OFFSET                  0x200   /* Vendor Specific Offset V1 */
  52/* V2 Defines */
  53#define VSE_CVP_TX_CREDITS              0x49    /* 8bit */
  54
  55#define V2_CREDIT_TIMEOUT_US            20000
  56#define V2_CHECK_CREDIT_US              10
  57#define V2_POLL_TIMEOUT_US              1000000
  58#define V2_USER_TIMEOUT_US              500000
  59
  60#define V1_POLL_TIMEOUT_US              10
  61
  62#define DRV_NAME                "altera-cvp"
  63#define ALTERA_CVP_MGR_NAME     "Altera CvP FPGA Manager"
  64
  65/* Write block sizes */
  66#define ALTERA_CVP_V1_SIZE      4
  67#define ALTERA_CVP_V2_SIZE      4096
  68
  69/* Optional CvP config error status check for debugging */
  70static bool altera_cvp_chkcfg;
  71
  72struct cvp_priv;
  73
  74struct altera_cvp_conf {
  75        struct fpga_manager     *mgr;
  76        struct pci_dev          *pci_dev;
  77        void __iomem            *map;
  78        void                    (*write_data)(struct altera_cvp_conf *conf,
  79                                              u32 data);
  80        char                    mgr_name[64];
  81        u8                      numclks;
  82        u32                     sent_packets;
  83        u32                     vsec_offset;
  84        const struct cvp_priv   *priv;
  85};
  86
  87struct cvp_priv {
  88        void    (*switch_clk)(struct altera_cvp_conf *conf);
  89        int     (*clear_state)(struct altera_cvp_conf *conf);
  90        int     (*wait_credit)(struct fpga_manager *mgr, u32 blocks);
  91        size_t  block_size;
  92        int     poll_time_us;
  93        int     user_time_us;
  94};
  95
  96static int altera_read_config_byte(struct altera_cvp_conf *conf,
  97                                   int where, u8 *val)
  98{
  99        return pci_read_config_byte(conf->pci_dev, conf->vsec_offset + where,
 100                                    val);
 101}
 102
 103static int altera_read_config_dword(struct altera_cvp_conf *conf,
 104                                    int where, u32 *val)
 105{
 106        return pci_read_config_dword(conf->pci_dev, conf->vsec_offset + where,
 107                                     val);
 108}
 109
 110static int altera_write_config_dword(struct altera_cvp_conf *conf,
 111                                     int where, u32 val)
 112{
 113        return pci_write_config_dword(conf->pci_dev, conf->vsec_offset + where,
 114                                      val);
 115}
 116
 117static enum fpga_mgr_states altera_cvp_state(struct fpga_manager *mgr)
 118{
 119        struct altera_cvp_conf *conf = mgr->priv;
 120        u32 status;
 121
 122        altera_read_config_dword(conf, VSE_CVP_STATUS, &status);
 123
 124        if (status & VSE_CVP_STATUS_CFG_DONE)
 125                return FPGA_MGR_STATE_OPERATING;
 126
 127        if (status & VSE_CVP_STATUS_CVP_EN)
 128                return FPGA_MGR_STATE_POWER_UP;
 129
 130        return FPGA_MGR_STATE_UNKNOWN;
 131}
 132
 133static void altera_cvp_write_data_iomem(struct altera_cvp_conf *conf, u32 val)
 134{
 135        writel(val, conf->map);
 136}
 137
 138static void altera_cvp_write_data_config(struct altera_cvp_conf *conf, u32 val)
 139{
 140        pci_write_config_dword(conf->pci_dev, conf->vsec_offset + VSE_CVP_DATA,
 141                               val);
 142}
 143
 144/* switches between CvP clock and internal clock */
 145static void altera_cvp_dummy_write(struct altera_cvp_conf *conf)
 146{
 147        unsigned int i;
 148        u32 val;
 149
 150        /* set 1 CVP clock cycle for every CVP Data Register Write */
 151        altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);
 152        val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK;
 153        val |= 1 << VSE_CVP_MODE_CTRL_NUMCLKS_OFF;
 154        altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);
 155
 156        for (i = 0; i < CVP_DUMMY_WR; i++)
 157                conf->write_data(conf, 0); /* dummy data, could be any value */
 158}
 159
 160static int altera_cvp_wait_status(struct altera_cvp_conf *conf, u32 status_mask,
 161                                  u32 status_val, int timeout_us)
 162{
 163        unsigned int retries;
 164        u32 val;
 165
 166        retries = timeout_us / 10;
 167        if (timeout_us % 10)
 168                retries++;
 169
 170        do {
 171                altera_read_config_dword(conf, VSE_CVP_STATUS, &val);
 172                if ((val & status_mask) == status_val)
 173                        return 0;
 174
 175                /* use small usleep value to re-check and break early */
 176                usleep_range(10, 11);
 177        } while (--retries);
 178
 179        return -ETIMEDOUT;
 180}
 181
 182static int altera_cvp_chk_error(struct fpga_manager *mgr, size_t bytes)
 183{
 184        struct altera_cvp_conf *conf = mgr->priv;
 185        u32 val;
 186        int ret;
 187
 188        /* STEP 10 (optional) - check CVP_CONFIG_ERROR flag */
 189        ret = altera_read_config_dword(conf, VSE_CVP_STATUS, &val);
 190        if (ret || (val & VSE_CVP_STATUS_CFG_ERR)) {
 191                dev_err(&mgr->dev, "CVP_CONFIG_ERROR after %zu bytes!\n",
 192                        bytes);
 193                return -EPROTO;
 194        }
 195        return 0;
 196}
 197
 198/*
 199 * CvP Version2 Functions
 200 * Recent Intel FPGAs use a credit mechanism to throttle incoming
 201 * bitstreams and a different method of clearing the state.
 202 */
 203
 204static int altera_cvp_v2_clear_state(struct altera_cvp_conf *conf)
 205{
 206        u32 val;
 207        int ret;
 208
 209        /* Clear the START_XFER and CVP_CONFIG bits */
 210        ret = altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);
 211        if (ret) {
 212                dev_err(&conf->pci_dev->dev,
 213                        "Error reading CVP Program Control Register\n");
 214                return ret;
 215        }
 216
 217        val &= ~VSE_CVP_PROG_CTRL_MASK;
 218        ret = altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);
 219        if (ret) {
 220                dev_err(&conf->pci_dev->dev,
 221                        "Error writing CVP Program Control Register\n");
 222                return ret;
 223        }
 224
 225        return altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0,
 226                                      conf->priv->poll_time_us);
 227}
 228
 229static int altera_cvp_v2_wait_for_credit(struct fpga_manager *mgr,
 230                                         u32 blocks)
 231{
 232        u32 timeout = V2_CREDIT_TIMEOUT_US / V2_CHECK_CREDIT_US;
 233        struct altera_cvp_conf *conf = mgr->priv;
 234        int ret;
 235        u8 val;
 236
 237        do {
 238                ret = altera_read_config_byte(conf, VSE_CVP_TX_CREDITS, &val);
 239                if (ret) {
 240                        dev_err(&conf->pci_dev->dev,
 241                                "Error reading CVP Credit Register\n");
 242                        return ret;
 243                }
 244
 245                /* Return if there is space in FIFO */
 246                if (val - (u8)conf->sent_packets)
 247                        return 0;
 248
 249                ret = altera_cvp_chk_error(mgr, blocks * ALTERA_CVP_V2_SIZE);
 250                if (ret) {
 251                        dev_err(&conf->pci_dev->dev,
 252                                "CE Bit error credit reg[0x%x]:sent[0x%x]\n",
 253                                val, conf->sent_packets);
 254                        return -EAGAIN;
 255                }
 256
 257                /* Limit the check credit byte traffic */
 258                usleep_range(V2_CHECK_CREDIT_US, V2_CHECK_CREDIT_US + 1);
 259        } while (timeout--);
 260
 261        dev_err(&conf->pci_dev->dev, "Timeout waiting for credit\n");
 262        return -ETIMEDOUT;
 263}
 264
 265static int altera_cvp_send_block(struct altera_cvp_conf *conf,
 266                                 const u32 *data, size_t len)
 267{
 268        u32 mask, words = len / sizeof(u32);
 269        int i, remainder;
 270
 271        for (i = 0; i < words; i++)
 272                conf->write_data(conf, *data++);
 273
 274        /* write up to 3 trailing bytes, if any */
 275        remainder = len % sizeof(u32);
 276        if (remainder) {
 277                mask = BIT(remainder * 8) - 1;
 278                if (mask)
 279                        conf->write_data(conf, *data & mask);
 280        }
 281
 282        return 0;
 283}
 284
 285static int altera_cvp_teardown(struct fpga_manager *mgr,
 286                               struct fpga_image_info *info)
 287{
 288        struct altera_cvp_conf *conf = mgr->priv;
 289        int ret;
 290        u32 val;
 291
 292        /* STEP 12 - reset START_XFER bit */
 293        altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);
 294        val &= ~VSE_CVP_PROG_CTRL_START_XFER;
 295        altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);
 296
 297        /* STEP 13 - reset CVP_CONFIG bit */
 298        val &= ~VSE_CVP_PROG_CTRL_CONFIG;
 299        altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);
 300
 301        /*
 302         * STEP 14
 303         * - set CVP_NUMCLKS to 1 and then issue CVP_DUMMY_WR dummy
 304         *   writes to the HIP
 305         */
 306        if (conf->priv->switch_clk)
 307                conf->priv->switch_clk(conf);
 308
 309        /* STEP 15 - poll CVP_CONFIG_READY bit for 0 with 10us timeout */
 310        ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0,
 311                                     conf->priv->poll_time_us);
 312        if (ret)
 313                dev_err(&mgr->dev, "CFG_RDY == 0 timeout\n");
 314
 315        return ret;
 316}
 317
 318static int altera_cvp_write_init(struct fpga_manager *mgr,
 319                                 struct fpga_image_info *info,
 320                                 const char *buf, size_t count)
 321{
 322        struct altera_cvp_conf *conf = mgr->priv;
 323        u32 iflags, val;
 324        int ret;
 325
 326        iflags = info ? info->flags : 0;
 327
 328        if (iflags & FPGA_MGR_PARTIAL_RECONFIG) {
 329                dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
 330                return -EINVAL;
 331        }
 332
 333        /* Determine allowed clock to data ratio */
 334        if (iflags & FPGA_MGR_COMPRESSED_BITSTREAM)
 335                conf->numclks = 8; /* ratio for all compressed images */
 336        else if (iflags & FPGA_MGR_ENCRYPTED_BITSTREAM)
 337                conf->numclks = 4; /* for uncompressed and encrypted images */
 338        else
 339                conf->numclks = 1; /* for uncompressed and unencrypted images */
 340
 341        /* STEP 1 - read CVP status and check CVP_EN flag */
 342        altera_read_config_dword(conf, VSE_CVP_STATUS, &val);
 343        if (!(val & VSE_CVP_STATUS_CVP_EN)) {
 344                dev_err(&mgr->dev, "CVP mode off: 0x%04x\n", val);
 345                return -ENODEV;
 346        }
 347
 348        if (val & VSE_CVP_STATUS_CFG_RDY) {
 349                dev_warn(&mgr->dev, "CvP already started, tear down first\n");
 350                ret = altera_cvp_teardown(mgr, info);
 351                if (ret)
 352                        return ret;
 353        }
 354
 355        /*
 356         * STEP 2
 357         * - set HIP_CLK_SEL and CVP_MODE (must be set in the order mentioned)
 358         */
 359        /* switch from fabric to PMA clock */
 360        altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);
 361        val |= VSE_CVP_MODE_CTRL_HIP_CLK_SEL;
 362        altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);
 363
 364        /* set CVP mode */
 365        altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);
 366        val |= VSE_CVP_MODE_CTRL_CVP_MODE;
 367        altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);
 368
 369        /*
 370         * STEP 3
 371         * - set CVP_NUMCLKS to 1 and issue CVP_DUMMY_WR dummy writes to the HIP
 372         */
 373        if (conf->priv->switch_clk)
 374                conf->priv->switch_clk(conf);
 375
 376        if (conf->priv->clear_state) {
 377                ret = conf->priv->clear_state(conf);
 378                if (ret) {
 379                        dev_err(&mgr->dev, "Problem clearing out state\n");
 380                        return ret;
 381                }
 382        }
 383
 384        conf->sent_packets = 0;
 385
 386        /* STEP 4 - set CVP_CONFIG bit */
 387        altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);
 388        /* request control block to begin transfer using CVP */
 389        val |= VSE_CVP_PROG_CTRL_CONFIG;
 390        altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);
 391
 392        /* STEP 5 - poll CVP_CONFIG READY for 1 with timeout */
 393        ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY,
 394                                     VSE_CVP_STATUS_CFG_RDY,
 395                                     conf->priv->poll_time_us);
 396        if (ret) {
 397                dev_warn(&mgr->dev, "CFG_RDY == 1 timeout\n");
 398                return ret;
 399        }
 400
 401        /*
 402         * STEP 6
 403         * - set CVP_NUMCLKS to 1 and issue CVP_DUMMY_WR dummy writes to the HIP
 404         */
 405        if (conf->priv->switch_clk)
 406                conf->priv->switch_clk(conf);
 407
 408        if (altera_cvp_chkcfg) {
 409                ret = altera_cvp_chk_error(mgr, 0);
 410                if (ret) {
 411                        dev_warn(&mgr->dev, "CFG_RDY == 1 timeout\n");
 412                        return ret;
 413                }
 414        }
 415
 416        /* STEP 7 - set START_XFER */
 417        altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);
 418        val |= VSE_CVP_PROG_CTRL_START_XFER;
 419        altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);
 420
 421        /* STEP 8 - start transfer (set CVP_NUMCLKS for bitstream) */
 422        if (conf->priv->switch_clk) {
 423                altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);
 424                val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK;
 425                val |= conf->numclks << VSE_CVP_MODE_CTRL_NUMCLKS_OFF;
 426                altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);
 427        }
 428        return 0;
 429}
 430
 431static int altera_cvp_write(struct fpga_manager *mgr, const char *buf,
 432                            size_t count)
 433{
 434        struct altera_cvp_conf *conf = mgr->priv;
 435        size_t done, remaining, len;
 436        const u32 *data;
 437        int status = 0;
 438
 439        /* STEP 9 - write 32-bit data from RBF file to CVP data register */
 440        data = (u32 *)buf;
 441        remaining = count;
 442        done = 0;
 443
 444        while (remaining) {
 445                /* Use credit throttling if available */
 446                if (conf->priv->wait_credit) {
 447                        status = conf->priv->wait_credit(mgr, done);
 448                        if (status) {
 449                                dev_err(&conf->pci_dev->dev,
 450                                        "Wait Credit ERR: 0x%x\n", status);
 451                                return status;
 452                        }
 453                }
 454
 455                len = min(conf->priv->block_size, remaining);
 456                altera_cvp_send_block(conf, data, len);
 457                data += len / sizeof(u32);
 458                done += len;
 459                remaining -= len;
 460                conf->sent_packets++;
 461
 462                /*
 463                 * STEP 10 (optional) and STEP 11
 464                 * - check error flag
 465                 * - loop until data transfer completed
 466                 * Config images can be huge (more than 40 MiB), so
 467                 * only check after a new 4k data block has been written.
 468                 * This reduces the number of checks and speeds up the
 469                 * configuration process.
 470                 */
 471                if (altera_cvp_chkcfg && !(done % SZ_4K)) {
 472                        status = altera_cvp_chk_error(mgr, done);
 473                        if (status < 0)
 474                                return status;
 475                }
 476        }
 477
 478        if (altera_cvp_chkcfg)
 479                status = altera_cvp_chk_error(mgr, count);
 480
 481        return status;
 482}
 483
 484static int altera_cvp_write_complete(struct fpga_manager *mgr,
 485                                     struct fpga_image_info *info)
 486{
 487        struct altera_cvp_conf *conf = mgr->priv;
 488        u32 mask, val;
 489        int ret;
 490
 491        ret = altera_cvp_teardown(mgr, info);
 492        if (ret)
 493                return ret;
 494
 495        /* STEP 16 - check CVP_CONFIG_ERROR_LATCHED bit */
 496        altera_read_config_dword(conf, VSE_UNCOR_ERR_STATUS, &val);
 497        if (val & VSE_UNCOR_ERR_CVP_CFG_ERR) {
 498                dev_err(&mgr->dev, "detected CVP_CONFIG_ERROR_LATCHED!\n");
 499                return -EPROTO;
 500        }
 501
 502        /* STEP 17 - reset CVP_MODE and HIP_CLK_SEL bit */
 503        altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);
 504        val &= ~VSE_CVP_MODE_CTRL_HIP_CLK_SEL;
 505        val &= ~VSE_CVP_MODE_CTRL_CVP_MODE;
 506        altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);
 507
 508        /* STEP 18 - poll PLD_CLK_IN_USE and USER_MODE bits */
 509        mask = VSE_CVP_STATUS_PLD_CLK_IN_USE | VSE_CVP_STATUS_USERMODE;
 510        ret = altera_cvp_wait_status(conf, mask, mask,
 511                                     conf->priv->user_time_us);
 512        if (ret)
 513                dev_err(&mgr->dev, "PLD_CLK_IN_USE|USERMODE timeout\n");
 514
 515        return ret;
 516}
 517
 518static const struct fpga_manager_ops altera_cvp_ops = {
 519        .state          = altera_cvp_state,
 520        .write_init     = altera_cvp_write_init,
 521        .write          = altera_cvp_write,
 522        .write_complete = altera_cvp_write_complete,
 523};
 524
 525static const struct cvp_priv cvp_priv_v1 = {
 526        .switch_clk     = altera_cvp_dummy_write,
 527        .block_size     = ALTERA_CVP_V1_SIZE,
 528        .poll_time_us   = V1_POLL_TIMEOUT_US,
 529        .user_time_us   = TIMEOUT_US,
 530};
 531
 532static const struct cvp_priv cvp_priv_v2 = {
 533        .clear_state    = altera_cvp_v2_clear_state,
 534        .wait_credit    = altera_cvp_v2_wait_for_credit,
 535        .block_size     = ALTERA_CVP_V2_SIZE,
 536        .poll_time_us   = V2_POLL_TIMEOUT_US,
 537        .user_time_us   = V2_USER_TIMEOUT_US,
 538};
 539
 540static ssize_t chkcfg_show(struct device_driver *dev, char *buf)
 541{
 542        return snprintf(buf, 3, "%d\n", altera_cvp_chkcfg);
 543}
 544
 545static ssize_t chkcfg_store(struct device_driver *drv, const char *buf,
 546                            size_t count)
 547{
 548        int ret;
 549
 550        ret = kstrtobool(buf, &altera_cvp_chkcfg);
 551        if (ret)
 552                return ret;
 553
 554        return count;
 555}
 556
 557static DRIVER_ATTR_RW(chkcfg);
 558
 559static int altera_cvp_probe(struct pci_dev *pdev,
 560                            const struct pci_device_id *dev_id);
 561static void altera_cvp_remove(struct pci_dev *pdev);
 562
 563static struct pci_device_id altera_cvp_id_tbl[] = {
 564        { PCI_VDEVICE(ALTERA, PCI_ANY_ID) },
 565        { }
 566};
 567MODULE_DEVICE_TABLE(pci, altera_cvp_id_tbl);
 568
 569static struct pci_driver altera_cvp_driver = {
 570        .name   = DRV_NAME,
 571        .id_table = altera_cvp_id_tbl,
 572        .probe  = altera_cvp_probe,
 573        .remove = altera_cvp_remove,
 574};
 575
 576static int altera_cvp_probe(struct pci_dev *pdev,
 577                            const struct pci_device_id *dev_id)
 578{
 579        struct altera_cvp_conf *conf;
 580        struct fpga_manager *mgr;
 581        int ret, offset;
 582        u16 cmd, val;
 583        u32 regval;
 584
 585        /* Discover the Vendor Specific Offset for this device */
 586        offset = pci_find_next_ext_capability(pdev, 0, PCI_EXT_CAP_ID_VNDR);
 587        if (!offset) {
 588                dev_err(&pdev->dev, "No Vendor Specific Offset.\n");
 589                return -ENODEV;
 590        }
 591
 592        /*
 593         * First check if this is the expected FPGA device. PCI config
 594         * space access works without enabling the PCI device, memory
 595         * space access is enabled further down.
 596         */
 597        pci_read_config_word(pdev, offset + VSE_PCIE_EXT_CAP_ID, &val);
 598        if (val != VSE_PCIE_EXT_CAP_ID_VAL) {
 599                dev_err(&pdev->dev, "Wrong EXT_CAP_ID value 0x%x\n", val);
 600                return -ENODEV;
 601        }
 602
 603        pci_read_config_dword(pdev, offset + VSE_CVP_STATUS, &regval);
 604        if (!(regval & VSE_CVP_STATUS_CVP_EN)) {
 605                dev_err(&pdev->dev,
 606                        "CVP is disabled for this device: CVP_STATUS Reg 0x%x\n",
 607                        regval);
 608                return -ENODEV;
 609        }
 610
 611        conf = devm_kzalloc(&pdev->dev, sizeof(*conf), GFP_KERNEL);
 612        if (!conf)
 613                return -ENOMEM;
 614
 615        conf->vsec_offset = offset;
 616
 617        /*
 618         * Enable memory BAR access. We cannot use pci_enable_device() here
 619         * because it will make the driver unusable with FPGA devices that
 620         * have additional big IOMEM resources (e.g. 4GiB BARs) on 32-bit
 621         * platform. Such BARs will not have an assigned address range and
 622         * pci_enable_device() will fail, complaining about not claimed BAR,
 623         * even if the concerned BAR is not needed for FPGA configuration
 624         * at all. Thus, enable the device via PCI config space command.
 625         */
 626        pci_read_config_word(pdev, PCI_COMMAND, &cmd);
 627        if (!(cmd & PCI_COMMAND_MEMORY)) {
 628                cmd |= PCI_COMMAND_MEMORY;
 629                pci_write_config_word(pdev, PCI_COMMAND, cmd);
 630        }
 631
 632        ret = pci_request_region(pdev, CVP_BAR, "CVP");
 633        if (ret) {
 634                dev_err(&pdev->dev, "Requesting CVP BAR region failed\n");
 635                goto err_disable;
 636        }
 637
 638        conf->pci_dev = pdev;
 639        conf->write_data = altera_cvp_write_data_iomem;
 640
 641        if (conf->vsec_offset == V1_VSEC_OFFSET)
 642                conf->priv = &cvp_priv_v1;
 643        else
 644                conf->priv = &cvp_priv_v2;
 645
 646        conf->map = pci_iomap(pdev, CVP_BAR, 0);
 647        if (!conf->map) {
 648                dev_warn(&pdev->dev, "Mapping CVP BAR failed\n");
 649                conf->write_data = altera_cvp_write_data_config;
 650        }
 651
 652        snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s @%s",
 653                 ALTERA_CVP_MGR_NAME, pci_name(pdev));
 654
 655        mgr = devm_fpga_mgr_create(&pdev->dev, conf->mgr_name,
 656                                   &altera_cvp_ops, conf);
 657        if (!mgr) {
 658                ret = -ENOMEM;
 659                goto err_unmap;
 660        }
 661
 662        pci_set_drvdata(pdev, mgr);
 663
 664        ret = fpga_mgr_register(mgr);
 665        if (ret)
 666                goto err_unmap;
 667
 668        return 0;
 669
 670err_unmap:
 671        if (conf->map)
 672                pci_iounmap(pdev, conf->map);
 673        pci_release_region(pdev, CVP_BAR);
 674err_disable:
 675        cmd &= ~PCI_COMMAND_MEMORY;
 676        pci_write_config_word(pdev, PCI_COMMAND, cmd);
 677        return ret;
 678}
 679
 680static void altera_cvp_remove(struct pci_dev *pdev)
 681{
 682        struct fpga_manager *mgr = pci_get_drvdata(pdev);
 683        struct altera_cvp_conf *conf = mgr->priv;
 684        u16 cmd;
 685
 686        fpga_mgr_unregister(mgr);
 687        if (conf->map)
 688                pci_iounmap(pdev, conf->map);
 689        pci_release_region(pdev, CVP_BAR);
 690        pci_read_config_word(pdev, PCI_COMMAND, &cmd);
 691        cmd &= ~PCI_COMMAND_MEMORY;
 692        pci_write_config_word(pdev, PCI_COMMAND, cmd);
 693}
 694
 695static int __init altera_cvp_init(void)
 696{
 697        int ret;
 698
 699        ret = pci_register_driver(&altera_cvp_driver);
 700        if (ret)
 701                return ret;
 702
 703        ret = driver_create_file(&altera_cvp_driver.driver,
 704                                 &driver_attr_chkcfg);
 705        if (ret)
 706                pr_warn("Can't create sysfs chkcfg file\n");
 707
 708        return 0;
 709}
 710
 711static void __exit altera_cvp_exit(void)
 712{
 713        driver_remove_file(&altera_cvp_driver.driver, &driver_attr_chkcfg);
 714        pci_unregister_driver(&altera_cvp_driver);
 715}
 716
 717module_init(altera_cvp_init);
 718module_exit(altera_cvp_exit);
 719
 720MODULE_LICENSE("GPL v2");
 721MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
 722MODULE_DESCRIPTION("Module to load Altera FPGA over CvP");
 723