File Index
Files and directories
Sign in
FILE

altera-cvp.c

File preview with syntax highlighting.

linux-6.19.14/drivers/fpga/altera-cvp.c C
  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 */
 67static bool altera_cvp_chkcfg;
 68
 69struct cvp_priv;
 70
 71struct 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
 83struct 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
 92static 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
 99static 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
106static 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
113static 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
129static void altera_cvp_write_data_iomem(struct altera_cvp_conf *conf, u32 val)
130{
131	writel(val, conf->map);
132}
133
134static 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 */
141static 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
156static 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
178static 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
200static 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
225static 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
261static 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
281static 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
314static 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
427static 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
480static 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
514static 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
521static 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
528static 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
536static ssize_t chkcfg_show(struct device_driver *dev, char *buf)
537{
538	return snprintf(buf, 3, "%d\n", altera_cvp_chkcfg);
539}
540
541static 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
553static DRIVER_ATTR_RW(chkcfg);
554
555static int altera_cvp_probe(struct pci_dev *pdev,
556			    const struct pci_device_id *dev_id);
557static void altera_cvp_remove(struct pci_dev *pdev);
558
559static struct pci_device_id altera_cvp_id_tbl[] = {
560	{ PCI_VDEVICE(ALTERA, PCI_ANY_ID) },
561	{ }
562};
563MODULE_DEVICE_TABLE(pci, altera_cvp_id_tbl);
564
565static 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
572static 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
655err_unmap:
656	if (conf->map)
657		pci_iounmap(pdev, conf->map);
658	pci_release_region(pdev, CVP_BAR);
659err_disable:
660	cmd &= ~PCI_COMMAND_MEMORY;
661	pci_write_config_word(pdev, PCI_COMMAND, cmd);
662	return ret;
663}
664
665static 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
680static 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
696static 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
702module_init(altera_cvp_init);
703module_exit(altera_cvp_exit);
704
705MODULE_LICENSE("GPL v2");
706MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
707MODULE_DESCRIPTION("Module to load Altera FPGA over CvP");
~/ Read-only file preview.