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