0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/delay.h>
0014 #include <linux/device.h>
0015 #include <linux/fpga/fpga-mgr.h>
0016 #include <linux/module.h>
0017 #include <linux/pci.h>
0018 #include <linux/sizes.h>
0019
0020 #define CVP_BAR 0
0021 #define CVP_DUMMY_WR 244
0022 #define TIMEOUT_US 2000
0023
0024
0025 #define VSE_PCIE_EXT_CAP_ID 0x0
0026 #define VSE_PCIE_EXT_CAP_ID_VAL 0x000b
0027
0028 #define VSE_CVP_STATUS 0x1c
0029 #define VSE_CVP_STATUS_CFG_RDY BIT(18)
0030 #define VSE_CVP_STATUS_CFG_ERR BIT(19)
0031 #define VSE_CVP_STATUS_CVP_EN BIT(20)
0032 #define VSE_CVP_STATUS_USERMODE BIT(21)
0033 #define VSE_CVP_STATUS_CFG_DONE BIT(23)
0034 #define VSE_CVP_STATUS_PLD_CLK_IN_USE BIT(24)
0035
0036 #define VSE_CVP_MODE_CTRL 0x20
0037 #define VSE_CVP_MODE_CTRL_CVP_MODE BIT(0)
0038 #define VSE_CVP_MODE_CTRL_HIP_CLK_SEL BIT(1)
0039 #define VSE_CVP_MODE_CTRL_NUMCLKS_OFF 8
0040 #define VSE_CVP_MODE_CTRL_NUMCLKS_MASK GENMASK(15, 8)
0041
0042 #define VSE_CVP_DATA 0x28
0043 #define VSE_CVP_PROG_CTRL 0x2c
0044 #define VSE_CVP_PROG_CTRL_CONFIG BIT(0)
0045 #define VSE_CVP_PROG_CTRL_START_XFER BIT(1)
0046 #define VSE_CVP_PROG_CTRL_MASK GENMASK(1, 0)
0047
0048 #define VSE_UNCOR_ERR_STATUS 0x34
0049 #define VSE_UNCOR_ERR_CVP_CFG_ERR BIT(5)
0050
0051 #define V1_VSEC_OFFSET 0x200
0052
0053 #define VSE_CVP_TX_CREDITS 0x49
0054
0055 #define V2_CREDIT_TIMEOUT_US 20000
0056 #define V2_CHECK_CREDIT_US 10
0057 #define V2_POLL_TIMEOUT_US 1000000
0058 #define V2_USER_TIMEOUT_US 500000
0059
0060 #define V1_POLL_TIMEOUT_US 10
0061
0062 #define DRV_NAME "altera-cvp"
0063 #define ALTERA_CVP_MGR_NAME "Altera CvP FPGA Manager"
0064
0065
0066 #define ALTERA_CVP_V1_SIZE 4
0067 #define ALTERA_CVP_V2_SIZE 4096
0068
0069
0070 static bool altera_cvp_chkcfg;
0071
0072 struct cvp_priv;
0073
0074 struct altera_cvp_conf {
0075 struct fpga_manager *mgr;
0076 struct pci_dev *pci_dev;
0077 void __iomem *map;
0078 void (*write_data)(struct altera_cvp_conf *conf,
0079 u32 data);
0080 char mgr_name[64];
0081 u8 numclks;
0082 u32 sent_packets;
0083 u32 vsec_offset;
0084 const struct cvp_priv *priv;
0085 };
0086
0087 struct cvp_priv {
0088 void (*switch_clk)(struct altera_cvp_conf *conf);
0089 int (*clear_state)(struct altera_cvp_conf *conf);
0090 int (*wait_credit)(struct fpga_manager *mgr, u32 blocks);
0091 size_t block_size;
0092 int poll_time_us;
0093 int user_time_us;
0094 };
0095
0096 static int altera_read_config_byte(struct altera_cvp_conf *conf,
0097 int where, u8 *val)
0098 {
0099 return pci_read_config_byte(conf->pci_dev, conf->vsec_offset + where,
0100 val);
0101 }
0102
0103 static int altera_read_config_dword(struct altera_cvp_conf *conf,
0104 int where, u32 *val)
0105 {
0106 return pci_read_config_dword(conf->pci_dev, conf->vsec_offset + where,
0107 val);
0108 }
0109
0110 static int altera_write_config_dword(struct altera_cvp_conf *conf,
0111 int where, u32 val)
0112 {
0113 return pci_write_config_dword(conf->pci_dev, conf->vsec_offset + where,
0114 val);
0115 }
0116
0117 static enum fpga_mgr_states altera_cvp_state(struct fpga_manager *mgr)
0118 {
0119 struct altera_cvp_conf *conf = mgr->priv;
0120 u32 status;
0121
0122 altera_read_config_dword(conf, VSE_CVP_STATUS, &status);
0123
0124 if (status & VSE_CVP_STATUS_CFG_DONE)
0125 return FPGA_MGR_STATE_OPERATING;
0126
0127 if (status & VSE_CVP_STATUS_CVP_EN)
0128 return FPGA_MGR_STATE_POWER_UP;
0129
0130 return FPGA_MGR_STATE_UNKNOWN;
0131 }
0132
0133 static void altera_cvp_write_data_iomem(struct altera_cvp_conf *conf, u32 val)
0134 {
0135 writel(val, conf->map);
0136 }
0137
0138 static void altera_cvp_write_data_config(struct altera_cvp_conf *conf, u32 val)
0139 {
0140 pci_write_config_dword(conf->pci_dev, conf->vsec_offset + VSE_CVP_DATA,
0141 val);
0142 }
0143
0144
0145 static void altera_cvp_dummy_write(struct altera_cvp_conf *conf)
0146 {
0147 unsigned int i;
0148 u32 val;
0149
0150
0151 altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);
0152 val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK;
0153 val |= 1 << VSE_CVP_MODE_CTRL_NUMCLKS_OFF;
0154 altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);
0155
0156 for (i = 0; i < CVP_DUMMY_WR; i++)
0157 conf->write_data(conf, 0);
0158 }
0159
0160 static int altera_cvp_wait_status(struct altera_cvp_conf *conf, u32 status_mask,
0161 u32 status_val, int timeout_us)
0162 {
0163 unsigned int retries;
0164 u32 val;
0165
0166 retries = timeout_us / 10;
0167 if (timeout_us % 10)
0168 retries++;
0169
0170 do {
0171 altera_read_config_dword(conf, VSE_CVP_STATUS, &val);
0172 if ((val & status_mask) == status_val)
0173 return 0;
0174
0175
0176 usleep_range(10, 11);
0177 } while (--retries);
0178
0179 return -ETIMEDOUT;
0180 }
0181
0182 static int altera_cvp_chk_error(struct fpga_manager *mgr, size_t bytes)
0183 {
0184 struct altera_cvp_conf *conf = mgr->priv;
0185 u32 val;
0186 int ret;
0187
0188
0189 ret = altera_read_config_dword(conf, VSE_CVP_STATUS, &val);
0190 if (ret || (val & VSE_CVP_STATUS_CFG_ERR)) {
0191 dev_err(&mgr->dev, "CVP_CONFIG_ERROR after %zu bytes!\n",
0192 bytes);
0193 return -EPROTO;
0194 }
0195 return 0;
0196 }
0197
0198
0199
0200
0201
0202
0203
0204 static int altera_cvp_v2_clear_state(struct altera_cvp_conf *conf)
0205 {
0206 u32 val;
0207 int ret;
0208
0209
0210 ret = altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);
0211 if (ret) {
0212 dev_err(&conf->pci_dev->dev,
0213 "Error reading CVP Program Control Register\n");
0214 return ret;
0215 }
0216
0217 val &= ~VSE_CVP_PROG_CTRL_MASK;
0218 ret = altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);
0219 if (ret) {
0220 dev_err(&conf->pci_dev->dev,
0221 "Error writing CVP Program Control Register\n");
0222 return ret;
0223 }
0224
0225 return altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0,
0226 conf->priv->poll_time_us);
0227 }
0228
0229 static int altera_cvp_v2_wait_for_credit(struct fpga_manager *mgr,
0230 u32 blocks)
0231 {
0232 u32 timeout = V2_CREDIT_TIMEOUT_US / V2_CHECK_CREDIT_US;
0233 struct altera_cvp_conf *conf = mgr->priv;
0234 int ret;
0235 u8 val;
0236
0237 do {
0238 ret = altera_read_config_byte(conf, VSE_CVP_TX_CREDITS, &val);
0239 if (ret) {
0240 dev_err(&conf->pci_dev->dev,
0241 "Error reading CVP Credit Register\n");
0242 return ret;
0243 }
0244
0245
0246 if (val - (u8)conf->sent_packets)
0247 return 0;
0248
0249 ret = altera_cvp_chk_error(mgr, blocks * ALTERA_CVP_V2_SIZE);
0250 if (ret) {
0251 dev_err(&conf->pci_dev->dev,
0252 "CE Bit error credit reg[0x%x]:sent[0x%x]\n",
0253 val, conf->sent_packets);
0254 return -EAGAIN;
0255 }
0256
0257
0258 usleep_range(V2_CHECK_CREDIT_US, V2_CHECK_CREDIT_US + 1);
0259 } while (timeout--);
0260
0261 dev_err(&conf->pci_dev->dev, "Timeout waiting for credit\n");
0262 return -ETIMEDOUT;
0263 }
0264
0265 static int altera_cvp_send_block(struct altera_cvp_conf *conf,
0266 const u32 *data, size_t len)
0267 {
0268 u32 mask, words = len / sizeof(u32);
0269 int i, remainder;
0270
0271 for (i = 0; i < words; i++)
0272 conf->write_data(conf, *data++);
0273
0274
0275 remainder = len % sizeof(u32);
0276 if (remainder) {
0277 mask = BIT(remainder * 8) - 1;
0278 if (mask)
0279 conf->write_data(conf, *data & mask);
0280 }
0281
0282 return 0;
0283 }
0284
0285 static int altera_cvp_teardown(struct fpga_manager *mgr,
0286 struct fpga_image_info *info)
0287 {
0288 struct altera_cvp_conf *conf = mgr->priv;
0289 int ret;
0290 u32 val;
0291
0292
0293 altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);
0294 val &= ~VSE_CVP_PROG_CTRL_START_XFER;
0295 altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);
0296
0297
0298 val &= ~VSE_CVP_PROG_CTRL_CONFIG;
0299 altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);
0300
0301
0302
0303
0304
0305
0306 if (conf->priv->switch_clk)
0307 conf->priv->switch_clk(conf);
0308
0309
0310 ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0,
0311 conf->priv->poll_time_us);
0312 if (ret)
0313 dev_err(&mgr->dev, "CFG_RDY == 0 timeout\n");
0314
0315 return ret;
0316 }
0317
0318 static int altera_cvp_write_init(struct fpga_manager *mgr,
0319 struct fpga_image_info *info,
0320 const char *buf, size_t count)
0321 {
0322 struct altera_cvp_conf *conf = mgr->priv;
0323 u32 iflags, val;
0324 int ret;
0325
0326 iflags = info ? info->flags : 0;
0327
0328 if (iflags & FPGA_MGR_PARTIAL_RECONFIG) {
0329 dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
0330 return -EINVAL;
0331 }
0332
0333
0334 if (iflags & FPGA_MGR_COMPRESSED_BITSTREAM)
0335 conf->numclks = 8;
0336 else if (iflags & FPGA_MGR_ENCRYPTED_BITSTREAM)
0337 conf->numclks = 4;
0338 else
0339 conf->numclks = 1;
0340
0341
0342 altera_read_config_dword(conf, VSE_CVP_STATUS, &val);
0343 if (!(val & VSE_CVP_STATUS_CVP_EN)) {
0344 dev_err(&mgr->dev, "CVP mode off: 0x%04x\n", val);
0345 return -ENODEV;
0346 }
0347
0348 if (val & VSE_CVP_STATUS_CFG_RDY) {
0349 dev_warn(&mgr->dev, "CvP already started, tear down first\n");
0350 ret = altera_cvp_teardown(mgr, info);
0351 if (ret)
0352 return ret;
0353 }
0354
0355
0356
0357
0358
0359
0360 altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);
0361 val |= VSE_CVP_MODE_CTRL_HIP_CLK_SEL;
0362 altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);
0363
0364
0365 altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);
0366 val |= VSE_CVP_MODE_CTRL_CVP_MODE;
0367 altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);
0368
0369
0370
0371
0372
0373 if (conf->priv->switch_clk)
0374 conf->priv->switch_clk(conf);
0375
0376 if (conf->priv->clear_state) {
0377 ret = conf->priv->clear_state(conf);
0378 if (ret) {
0379 dev_err(&mgr->dev, "Problem clearing out state\n");
0380 return ret;
0381 }
0382 }
0383
0384 conf->sent_packets = 0;
0385
0386
0387 altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);
0388
0389 val |= VSE_CVP_PROG_CTRL_CONFIG;
0390 altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);
0391
0392
0393 ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY,
0394 VSE_CVP_STATUS_CFG_RDY,
0395 conf->priv->poll_time_us);
0396 if (ret) {
0397 dev_warn(&mgr->dev, "CFG_RDY == 1 timeout\n");
0398 return ret;
0399 }
0400
0401
0402
0403
0404
0405 if (conf->priv->switch_clk)
0406 conf->priv->switch_clk(conf);
0407
0408 if (altera_cvp_chkcfg) {
0409 ret = altera_cvp_chk_error(mgr, 0);
0410 if (ret) {
0411 dev_warn(&mgr->dev, "CFG_RDY == 1 timeout\n");
0412 return ret;
0413 }
0414 }
0415
0416
0417 altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);
0418 val |= VSE_CVP_PROG_CTRL_START_XFER;
0419 altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);
0420
0421
0422 if (conf->priv->switch_clk) {
0423 altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);
0424 val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK;
0425 val |= conf->numclks << VSE_CVP_MODE_CTRL_NUMCLKS_OFF;
0426 altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);
0427 }
0428 return 0;
0429 }
0430
0431 static int altera_cvp_write(struct fpga_manager *mgr, const char *buf,
0432 size_t count)
0433 {
0434 struct altera_cvp_conf *conf = mgr->priv;
0435 size_t done, remaining, len;
0436 const u32 *data;
0437 int status = 0;
0438
0439
0440 data = (u32 *)buf;
0441 remaining = count;
0442 done = 0;
0443
0444 while (remaining) {
0445
0446 if (conf->priv->wait_credit) {
0447 status = conf->priv->wait_credit(mgr, done);
0448 if (status) {
0449 dev_err(&conf->pci_dev->dev,
0450 "Wait Credit ERR: 0x%x\n", status);
0451 return status;
0452 }
0453 }
0454
0455 len = min(conf->priv->block_size, remaining);
0456 altera_cvp_send_block(conf, data, len);
0457 data += len / sizeof(u32);
0458 done += len;
0459 remaining -= len;
0460 conf->sent_packets++;
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471 if (altera_cvp_chkcfg && !(done % SZ_4K)) {
0472 status = altera_cvp_chk_error(mgr, done);
0473 if (status < 0)
0474 return status;
0475 }
0476 }
0477
0478 if (altera_cvp_chkcfg)
0479 status = altera_cvp_chk_error(mgr, count);
0480
0481 return status;
0482 }
0483
0484 static int altera_cvp_write_complete(struct fpga_manager *mgr,
0485 struct fpga_image_info *info)
0486 {
0487 struct altera_cvp_conf *conf = mgr->priv;
0488 u32 mask, val;
0489 int ret;
0490
0491 ret = altera_cvp_teardown(mgr, info);
0492 if (ret)
0493 return ret;
0494
0495
0496 altera_read_config_dword(conf, VSE_UNCOR_ERR_STATUS, &val);
0497 if (val & VSE_UNCOR_ERR_CVP_CFG_ERR) {
0498 dev_err(&mgr->dev, "detected CVP_CONFIG_ERROR_LATCHED!\n");
0499 return -EPROTO;
0500 }
0501
0502
0503 altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);
0504 val &= ~VSE_CVP_MODE_CTRL_HIP_CLK_SEL;
0505 val &= ~VSE_CVP_MODE_CTRL_CVP_MODE;
0506 altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);
0507
0508
0509 mask = VSE_CVP_STATUS_PLD_CLK_IN_USE | VSE_CVP_STATUS_USERMODE;
0510 ret = altera_cvp_wait_status(conf, mask, mask,
0511 conf->priv->user_time_us);
0512 if (ret)
0513 dev_err(&mgr->dev, "PLD_CLK_IN_USE|USERMODE timeout\n");
0514
0515 return ret;
0516 }
0517
0518 static const struct fpga_manager_ops altera_cvp_ops = {
0519 .state = altera_cvp_state,
0520 .write_init = altera_cvp_write_init,
0521 .write = altera_cvp_write,
0522 .write_complete = altera_cvp_write_complete,
0523 };
0524
0525 static const struct cvp_priv cvp_priv_v1 = {
0526 .switch_clk = altera_cvp_dummy_write,
0527 .block_size = ALTERA_CVP_V1_SIZE,
0528 .poll_time_us = V1_POLL_TIMEOUT_US,
0529 .user_time_us = TIMEOUT_US,
0530 };
0531
0532 static const struct cvp_priv cvp_priv_v2 = {
0533 .clear_state = altera_cvp_v2_clear_state,
0534 .wait_credit = altera_cvp_v2_wait_for_credit,
0535 .block_size = ALTERA_CVP_V2_SIZE,
0536 .poll_time_us = V2_POLL_TIMEOUT_US,
0537 .user_time_us = V2_USER_TIMEOUT_US,
0538 };
0539
0540 static ssize_t chkcfg_show(struct device_driver *dev, char *buf)
0541 {
0542 return snprintf(buf, 3, "%d\n", altera_cvp_chkcfg);
0543 }
0544
0545 static ssize_t chkcfg_store(struct device_driver *drv, const char *buf,
0546 size_t count)
0547 {
0548 int ret;
0549
0550 ret = kstrtobool(buf, &altera_cvp_chkcfg);
0551 if (ret)
0552 return ret;
0553
0554 return count;
0555 }
0556
0557 static DRIVER_ATTR_RW(chkcfg);
0558
0559 static int altera_cvp_probe(struct pci_dev *pdev,
0560 const struct pci_device_id *dev_id);
0561 static void altera_cvp_remove(struct pci_dev *pdev);
0562
0563 static struct pci_device_id altera_cvp_id_tbl[] = {
0564 { PCI_VDEVICE(ALTERA, PCI_ANY_ID) },
0565 { }
0566 };
0567 MODULE_DEVICE_TABLE(pci, altera_cvp_id_tbl);
0568
0569 static struct pci_driver altera_cvp_driver = {
0570 .name = DRV_NAME,
0571 .id_table = altera_cvp_id_tbl,
0572 .probe = altera_cvp_probe,
0573 .remove = altera_cvp_remove,
0574 };
0575
0576 static int altera_cvp_probe(struct pci_dev *pdev,
0577 const struct pci_device_id *dev_id)
0578 {
0579 struct altera_cvp_conf *conf;
0580 struct fpga_manager *mgr;
0581 int ret, offset;
0582 u16 cmd, val;
0583 u32 regval;
0584
0585
0586 offset = pci_find_next_ext_capability(pdev, 0, PCI_EXT_CAP_ID_VNDR);
0587 if (!offset) {
0588 dev_err(&pdev->dev, "No Vendor Specific Offset.\n");
0589 return -ENODEV;
0590 }
0591
0592
0593
0594
0595
0596
0597 pci_read_config_word(pdev, offset + VSE_PCIE_EXT_CAP_ID, &val);
0598 if (val != VSE_PCIE_EXT_CAP_ID_VAL) {
0599 dev_err(&pdev->dev, "Wrong EXT_CAP_ID value 0x%x\n", val);
0600 return -ENODEV;
0601 }
0602
0603 pci_read_config_dword(pdev, offset + VSE_CVP_STATUS, ®val);
0604 if (!(regval & VSE_CVP_STATUS_CVP_EN)) {
0605 dev_err(&pdev->dev,
0606 "CVP is disabled for this device: CVP_STATUS Reg 0x%x\n",
0607 regval);
0608 return -ENODEV;
0609 }
0610
0611 conf = devm_kzalloc(&pdev->dev, sizeof(*conf), GFP_KERNEL);
0612 if (!conf)
0613 return -ENOMEM;
0614
0615 conf->vsec_offset = offset;
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
0627 if (!(cmd & PCI_COMMAND_MEMORY)) {
0628 cmd |= PCI_COMMAND_MEMORY;
0629 pci_write_config_word(pdev, PCI_COMMAND, cmd);
0630 }
0631
0632 ret = pci_request_region(pdev, CVP_BAR, "CVP");
0633 if (ret) {
0634 dev_err(&pdev->dev, "Requesting CVP BAR region failed\n");
0635 goto err_disable;
0636 }
0637
0638 conf->pci_dev = pdev;
0639 conf->write_data = altera_cvp_write_data_iomem;
0640
0641 if (conf->vsec_offset == V1_VSEC_OFFSET)
0642 conf->priv = &cvp_priv_v1;
0643 else
0644 conf->priv = &cvp_priv_v2;
0645
0646 conf->map = pci_iomap(pdev, CVP_BAR, 0);
0647 if (!conf->map) {
0648 dev_warn(&pdev->dev, "Mapping CVP BAR failed\n");
0649 conf->write_data = altera_cvp_write_data_config;
0650 }
0651
0652 snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s @%s",
0653 ALTERA_CVP_MGR_NAME, pci_name(pdev));
0654
0655 mgr = fpga_mgr_register(&pdev->dev, conf->mgr_name,
0656 &altera_cvp_ops, conf);
0657 if (IS_ERR(mgr)) {
0658 ret = PTR_ERR(mgr);
0659 goto err_unmap;
0660 }
0661
0662 pci_set_drvdata(pdev, mgr);
0663
0664 return 0;
0665
0666 err_unmap:
0667 if (conf->map)
0668 pci_iounmap(pdev, conf->map);
0669 pci_release_region(pdev, CVP_BAR);
0670 err_disable:
0671 cmd &= ~PCI_COMMAND_MEMORY;
0672 pci_write_config_word(pdev, PCI_COMMAND, cmd);
0673 return ret;
0674 }
0675
0676 static void altera_cvp_remove(struct pci_dev *pdev)
0677 {
0678 struct fpga_manager *mgr = pci_get_drvdata(pdev);
0679 struct altera_cvp_conf *conf = mgr->priv;
0680 u16 cmd;
0681
0682 fpga_mgr_unregister(mgr);
0683 if (conf->map)
0684 pci_iounmap(pdev, conf->map);
0685 pci_release_region(pdev, CVP_BAR);
0686 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
0687 cmd &= ~PCI_COMMAND_MEMORY;
0688 pci_write_config_word(pdev, PCI_COMMAND, cmd);
0689 }
0690
0691 static int __init altera_cvp_init(void)
0692 {
0693 int ret;
0694
0695 ret = pci_register_driver(&altera_cvp_driver);
0696 if (ret)
0697 return ret;
0698
0699 ret = driver_create_file(&altera_cvp_driver.driver,
0700 &driver_attr_chkcfg);
0701 if (ret)
0702 pr_warn("Can't create sysfs chkcfg file\n");
0703
0704 return 0;
0705 }
0706
0707 static void __exit altera_cvp_exit(void)
0708 {
0709 driver_remove_file(&altera_cvp_driver.driver, &driver_attr_chkcfg);
0710 pci_unregister_driver(&altera_cvp_driver);
0711 }
0712
0713 module_init(altera_cvp_init);
0714 module_exit(altera_cvp_exit);
0715
0716 MODULE_LICENSE("GPL v2");
0717 MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
0718 MODULE_DESCRIPTION("Module to load Altera FPGA over CvP");