projects/linux·blob master · refs

709 lines · 18.6 KiB

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