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