diff options
Diffstat (limited to 'drivers/fpga/altera-cvp.c')
| -rw-r--r-- | drivers/fpga/altera-cvp.c | 342 | 
1 files changed, 270 insertions, 72 deletions
diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 770915fb97f9..4e0edb60bfba 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -22,10 +22,10 @@  #define TIMEOUT_US	2000	/* CVP STATUS timeout for USERMODE polling */  /* Vendor Specific Extended Capability Registers */ -#define VSE_PCIE_EXT_CAP_ID		0x200 +#define VSE_PCIE_EXT_CAP_ID		0x0  #define VSE_PCIE_EXT_CAP_ID_VAL		0x000b	/* 16bit */ -#define VSE_CVP_STATUS			0x21c	/* 32bit */ +#define VSE_CVP_STATUS			0x1c	/* 32bit */  #define VSE_CVP_STATUS_CFG_RDY		BIT(18)	/* CVP_CONFIG_READY */  #define VSE_CVP_STATUS_CFG_ERR		BIT(19)	/* CVP_CONFIG_ERROR */  #define VSE_CVP_STATUS_CVP_EN		BIT(20)	/* ctrl block is enabling CVP */ @@ -33,41 +33,93 @@  #define VSE_CVP_STATUS_CFG_DONE		BIT(23)	/* CVP_CONFIG_DONE */  #define VSE_CVP_STATUS_PLD_CLK_IN_USE	BIT(24)	/* PLD_CLK_IN_USE */ -#define VSE_CVP_MODE_CTRL		0x220	/* 32bit */ +#define VSE_CVP_MODE_CTRL		0x20	/* 32bit */  #define VSE_CVP_MODE_CTRL_CVP_MODE	BIT(0)	/* CVP (1) or normal mode (0) */  #define VSE_CVP_MODE_CTRL_HIP_CLK_SEL	BIT(1) /* PMA (1) or fabric clock (0) */  #define VSE_CVP_MODE_CTRL_NUMCLKS_OFF	8	/* NUMCLKS bits offset */  #define VSE_CVP_MODE_CTRL_NUMCLKS_MASK	GENMASK(15, 8) -#define VSE_CVP_DATA			0x228	/* 32bit */ -#define VSE_CVP_PROG_CTRL		0x22c	/* 32bit */ +#define VSE_CVP_DATA			0x28	/* 32bit */ +#define VSE_CVP_PROG_CTRL		0x2c	/* 32bit */  #define VSE_CVP_PROG_CTRL_CONFIG	BIT(0)  #define VSE_CVP_PROG_CTRL_START_XFER	BIT(1) +#define VSE_CVP_PROG_CTRL_MASK		GENMASK(1, 0) -#define VSE_UNCOR_ERR_STATUS		0x234	/* 32bit */ +#define VSE_UNCOR_ERR_STATUS		0x34	/* 32bit */  #define VSE_UNCOR_ERR_CVP_CFG_ERR	BIT(5)	/* CVP_CONFIG_ERROR_LATCHED */ +#define V1_VSEC_OFFSET			0x200	/* Vendor Specific Offset V1 */ +/* V2 Defines */ +#define VSE_CVP_TX_CREDITS		0x49	/* 8bit */ + +#define V2_CREDIT_TIMEOUT_US		20000 +#define V2_CHECK_CREDIT_US		10 +#define V2_POLL_TIMEOUT_US		1000000 +#define V2_USER_TIMEOUT_US		500000 + +#define V1_POLL_TIMEOUT_US		10 +  #define DRV_NAME		"altera-cvp"  #define ALTERA_CVP_MGR_NAME	"Altera CvP FPGA Manager" +/* Write block sizes */ +#define ALTERA_CVP_V1_SIZE	4 +#define ALTERA_CVP_V2_SIZE	4096 +  /* Optional CvP config error status check for debugging */  static bool altera_cvp_chkcfg; +struct cvp_priv; +  struct altera_cvp_conf {  	struct fpga_manager	*mgr;  	struct pci_dev		*pci_dev;  	void __iomem		*map; -	void			(*write_data)(struct altera_cvp_conf *, u32); +	void			(*write_data)(struct altera_cvp_conf *conf, +					      u32 data);  	char			mgr_name[64];  	u8			numclks; +	u32			sent_packets; +	u32			vsec_offset; +	const struct cvp_priv	*priv; +}; + +struct cvp_priv { +	void	(*switch_clk)(struct altera_cvp_conf *conf); +	int	(*clear_state)(struct altera_cvp_conf *conf); +	int	(*wait_credit)(struct fpga_manager *mgr, u32 blocks); +	size_t	block_size; +	int	poll_time_us; +	int	user_time_us;  }; +static int altera_read_config_byte(struct altera_cvp_conf *conf, +				   int where, u8 *val) +{ +	return pci_read_config_byte(conf->pci_dev, conf->vsec_offset + where, +				    val); +} + +static int altera_read_config_dword(struct altera_cvp_conf *conf, +				    int where, u32 *val) +{ +	return pci_read_config_dword(conf->pci_dev, conf->vsec_offset + where, +				     val); +} + +static int altera_write_config_dword(struct altera_cvp_conf *conf, +				     int where, u32 val) +{ +	return pci_write_config_dword(conf->pci_dev, conf->vsec_offset + where, +				      val); +} +  static enum fpga_mgr_states altera_cvp_state(struct fpga_manager *mgr)  {  	struct altera_cvp_conf *conf = mgr->priv;  	u32 status; -	pci_read_config_dword(conf->pci_dev, VSE_CVP_STATUS, &status); +	altera_read_config_dword(conf, VSE_CVP_STATUS, &status);  	if (status & VSE_CVP_STATUS_CFG_DONE)  		return FPGA_MGR_STATE_OPERATING; @@ -85,7 +137,8 @@ static void altera_cvp_write_data_iomem(struct altera_cvp_conf *conf, u32 val)  static void altera_cvp_write_data_config(struct altera_cvp_conf *conf, u32 val)  { -	pci_write_config_dword(conf->pci_dev, VSE_CVP_DATA, val); +	pci_write_config_dword(conf->pci_dev, conf->vsec_offset + VSE_CVP_DATA, +			       val);  }  /* switches between CvP clock and internal clock */ @@ -95,10 +148,10 @@ static void altera_cvp_dummy_write(struct altera_cvp_conf *conf)  	u32 val;  	/* set 1 CVP clock cycle for every CVP Data Register Write */ -	pci_read_config_dword(conf->pci_dev, VSE_CVP_MODE_CTRL, &val); +	altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);  	val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK;  	val |= 1 << VSE_CVP_MODE_CTRL_NUMCLKS_OFF; -	pci_write_config_dword(conf->pci_dev, VSE_CVP_MODE_CTRL, val); +	altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);  	for (i = 0; i < CVP_DUMMY_WR; i++)  		conf->write_data(conf, 0); /* dummy data, could be any value */ @@ -115,7 +168,7 @@ static int altera_cvp_wait_status(struct altera_cvp_conf *conf, u32 status_mask,  		retries++;  	do { -		pci_read_config_dword(conf->pci_dev, VSE_CVP_STATUS, &val); +		altera_read_config_dword(conf, VSE_CVP_STATUS, &val);  		if ((val & status_mask) == status_val)  			return 0; @@ -126,32 +179,136 @@ static int altera_cvp_wait_status(struct altera_cvp_conf *conf, u32 status_mask,  	return -ETIMEDOUT;  } +static int altera_cvp_chk_error(struct fpga_manager *mgr, size_t bytes) +{ +	struct altera_cvp_conf *conf = mgr->priv; +	u32 val; +	int ret; + +	/* STEP 10 (optional) - check CVP_CONFIG_ERROR flag */ +	ret = altera_read_config_dword(conf, VSE_CVP_STATUS, &val); +	if (ret || (val & VSE_CVP_STATUS_CFG_ERR)) { +		dev_err(&mgr->dev, "CVP_CONFIG_ERROR after %zu bytes!\n", +			bytes); +		return -EPROTO; +	} +	return 0; +} + +/* + * CvP Version2 Functions + * Recent Intel FPGAs use a credit mechanism to throttle incoming + * bitstreams and a different method of clearing the state. + */ + +static int altera_cvp_v2_clear_state(struct altera_cvp_conf *conf) +{ +	u32 val; +	int ret; + +	/* Clear the START_XFER and CVP_CONFIG bits */ +	ret = altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val); +	if (ret) { +		dev_err(&conf->pci_dev->dev, +			"Error reading CVP Program Control Register\n"); +		return ret; +	} + +	val &= ~VSE_CVP_PROG_CTRL_MASK; +	ret = altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val); +	if (ret) { +		dev_err(&conf->pci_dev->dev, +			"Error writing CVP Program Control Register\n"); +		return ret; +	} + +	return altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0, +				      conf->priv->poll_time_us); +} + +static int altera_cvp_v2_wait_for_credit(struct fpga_manager *mgr, +					 u32 blocks) +{ +	u32 timeout = V2_CREDIT_TIMEOUT_US / V2_CHECK_CREDIT_US; +	struct altera_cvp_conf *conf = mgr->priv; +	int ret; +	u8 val; + +	do { +		ret = altera_read_config_byte(conf, VSE_CVP_TX_CREDITS, &val); +		if (ret) { +			dev_err(&conf->pci_dev->dev, +				"Error reading CVP Credit Register\n"); +			return ret; +		} + +		/* Return if there is space in FIFO */ +		if (val - (u8)conf->sent_packets) +			return 0; + +		ret = altera_cvp_chk_error(mgr, blocks * ALTERA_CVP_V2_SIZE); +		if (ret) { +			dev_err(&conf->pci_dev->dev, +				"CE Bit error credit reg[0x%x]:sent[0x%x]\n", +				val, conf->sent_packets); +			return -EAGAIN; +		} + +		/* Limit the check credit byte traffic */ +		usleep_range(V2_CHECK_CREDIT_US, V2_CHECK_CREDIT_US + 1); +	} while (timeout--); + +	dev_err(&conf->pci_dev->dev, "Timeout waiting for credit\n"); +	return -ETIMEDOUT; +} + +static int altera_cvp_send_block(struct altera_cvp_conf *conf, +				 const u32 *data, size_t len) +{ +	u32 mask, words = len / sizeof(u32); +	int i, remainder; + +	for (i = 0; i < words; i++) +		conf->write_data(conf, *data++); + +	/* write up to 3 trailing bytes, if any */ +	remainder = len % sizeof(u32); +	if (remainder) { +		mask = BIT(remainder * 8) - 1; +		if (mask) +			conf->write_data(conf, *data & mask); +	} + +	return 0; +} +  static int altera_cvp_teardown(struct fpga_manager *mgr,  			       struct fpga_image_info *info)  {  	struct altera_cvp_conf *conf = mgr->priv; -	struct pci_dev *pdev = conf->pci_dev;  	int ret;  	u32 val;  	/* STEP 12 - reset START_XFER bit */ -	pci_read_config_dword(pdev, VSE_CVP_PROG_CTRL, &val); +	altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);  	val &= ~VSE_CVP_PROG_CTRL_START_XFER; -	pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); +	altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);  	/* STEP 13 - reset CVP_CONFIG bit */  	val &= ~VSE_CVP_PROG_CTRL_CONFIG; -	pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); +	altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);  	/*  	 * STEP 14  	 * - set CVP_NUMCLKS to 1 and then issue CVP_DUMMY_WR dummy  	 *   writes to the HIP  	 */ -	altera_cvp_dummy_write(conf); /* from CVP clock to internal clock */ +	if (conf->priv->switch_clk) +		conf->priv->switch_clk(conf);  	/* STEP 15 - poll CVP_CONFIG_READY bit for 0 with 10us timeout */ -	ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0, 10); +	ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0, +				     conf->priv->poll_time_us);  	if (ret)  		dev_err(&mgr->dev, "CFG_RDY == 0 timeout\n"); @@ -163,7 +320,6 @@ static int altera_cvp_write_init(struct fpga_manager *mgr,  				 const char *buf, size_t count)  {  	struct altera_cvp_conf *conf = mgr->priv; -	struct pci_dev *pdev = conf->pci_dev;  	u32 iflags, val;  	int ret; @@ -183,7 +339,7 @@ static int altera_cvp_write_init(struct fpga_manager *mgr,  		conf->numclks = 1; /* for uncompressed and unencrypted images */  	/* STEP 1 - read CVP status and check CVP_EN flag */ -	pci_read_config_dword(pdev, VSE_CVP_STATUS, &val); +	altera_read_config_dword(conf, VSE_CVP_STATUS, &val);  	if (!(val & VSE_CVP_STATUS_CVP_EN)) {  		dev_err(&mgr->dev, "CVP mode off: 0x%04x\n", val);  		return -ENODEV; @@ -201,30 +357,42 @@ static int altera_cvp_write_init(struct fpga_manager *mgr,  	 * - set HIP_CLK_SEL and CVP_MODE (must be set in the order mentioned)  	 */  	/* switch from fabric to PMA clock */ -	pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); +	altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);  	val |= VSE_CVP_MODE_CTRL_HIP_CLK_SEL; -	pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); +	altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);  	/* set CVP mode */ -	pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); +	altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);  	val |= VSE_CVP_MODE_CTRL_CVP_MODE; -	pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); +	altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);  	/*  	 * STEP 3  	 * - set CVP_NUMCLKS to 1 and issue CVP_DUMMY_WR dummy writes to the HIP  	 */ -	altera_cvp_dummy_write(conf); +	if (conf->priv->switch_clk) +		conf->priv->switch_clk(conf); + +	if (conf->priv->clear_state) { +		ret = conf->priv->clear_state(conf); +		if (ret) { +			dev_err(&mgr->dev, "Problem clearing out state\n"); +			return ret; +		} +	} + +	conf->sent_packets = 0;  	/* STEP 4 - set CVP_CONFIG bit */ -	pci_read_config_dword(pdev, VSE_CVP_PROG_CTRL, &val); +	altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);  	/* request control block to begin transfer using CVP */  	val |= VSE_CVP_PROG_CTRL_CONFIG; -	pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); +	altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val); -	/* STEP 5 - poll CVP_CONFIG READY for 1 with 10us timeout */ +	/* STEP 5 - poll CVP_CONFIG READY for 1 with timeout */  	ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, -				     VSE_CVP_STATUS_CFG_RDY, 10); +				     VSE_CVP_STATUS_CFG_RDY, +				     conf->priv->poll_time_us);  	if (ret) {  		dev_warn(&mgr->dev, "CFG_RDY == 1 timeout\n");  		return ret; @@ -234,33 +402,28 @@ static int altera_cvp_write_init(struct fpga_manager *mgr,  	 * STEP 6  	 * - set CVP_NUMCLKS to 1 and issue CVP_DUMMY_WR dummy writes to the HIP  	 */ -	altera_cvp_dummy_write(conf); +	if (conf->priv->switch_clk) +		conf->priv->switch_clk(conf); + +	if (altera_cvp_chkcfg) { +		ret = altera_cvp_chk_error(mgr, 0); +		if (ret) { +			dev_warn(&mgr->dev, "CFG_RDY == 1 timeout\n"); +			return ret; +		} +	}  	/* STEP 7 - set START_XFER */ -	pci_read_config_dword(pdev, VSE_CVP_PROG_CTRL, &val); +	altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val);  	val |= VSE_CVP_PROG_CTRL_START_XFER; -	pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); +	altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val);  	/* STEP 8 - start transfer (set CVP_NUMCLKS for bitstream) */ -	pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); -	val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK; -	val |= conf->numclks << VSE_CVP_MODE_CTRL_NUMCLKS_OFF; -	pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); - -	return 0; -} - -static inline int altera_cvp_chk_error(struct fpga_manager *mgr, size_t bytes) -{ -	struct altera_cvp_conf *conf = mgr->priv; -	u32 val; - -	/* STEP 10 (optional) - check CVP_CONFIG_ERROR flag */ -	pci_read_config_dword(conf->pci_dev, VSE_CVP_STATUS, &val); -	if (val & VSE_CVP_STATUS_CFG_ERR) { -		dev_err(&mgr->dev, "CVP_CONFIG_ERROR after %zu bytes!\n", -			bytes); -		return -EPROTO; +	if (conf->priv->switch_clk) { +		altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val); +		val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK; +		val |= conf->numclks << VSE_CVP_MODE_CTRL_NUMCLKS_OFF; +		altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);  	}  	return 0;  } @@ -269,20 +432,32 @@ static int altera_cvp_write(struct fpga_manager *mgr, const char *buf,  			    size_t count)  {  	struct altera_cvp_conf *conf = mgr->priv; +	size_t done, remaining, len;  	const u32 *data; -	size_t done, remaining;  	int status = 0; -	u32 mask;  	/* STEP 9 - write 32-bit data from RBF file to CVP data register */  	data = (u32 *)buf;  	remaining = count;  	done = 0; -	while (remaining >= 4) { -		conf->write_data(conf, *data++); -		done += 4; -		remaining -= 4; +	while (remaining) { +		/* Use credit throttling if available */ +		if (conf->priv->wait_credit) { +			status = conf->priv->wait_credit(mgr, done); +			if (status) { +				dev_err(&conf->pci_dev->dev, +					"Wait Credit ERR: 0x%x\n", status); +				return status; +			} +		} + +		len = min(conf->priv->block_size, remaining); +		altera_cvp_send_block(conf, data, len); +		data += len / sizeof(u32); +		done += len; +		remaining -= len; +		conf->sent_packets++;  		/*  		 * STEP 10 (optional) and STEP 11 @@ -300,11 +475,6 @@ static int altera_cvp_write(struct fpga_manager *mgr, const char *buf,  		}  	} -	/* write up to 3 trailing bytes, if any */ -	mask = BIT(remaining * 8) - 1; -	if (mask) -		conf->write_data(conf, *data & mask); -  	if (altera_cvp_chkcfg)  		status = altera_cvp_chk_error(mgr, count); @@ -315,31 +485,30 @@ static int altera_cvp_write_complete(struct fpga_manager *mgr,  				     struct fpga_image_info *info)  {  	struct altera_cvp_conf *conf = mgr->priv; -	struct pci_dev *pdev = conf->pci_dev; +	u32 mask, val;  	int ret; -	u32 mask; -	u32 val;  	ret = altera_cvp_teardown(mgr, info);  	if (ret)  		return ret;  	/* STEP 16 - check CVP_CONFIG_ERROR_LATCHED bit */ -	pci_read_config_dword(pdev, VSE_UNCOR_ERR_STATUS, &val); +	altera_read_config_dword(conf, VSE_UNCOR_ERR_STATUS, &val);  	if (val & VSE_UNCOR_ERR_CVP_CFG_ERR) {  		dev_err(&mgr->dev, "detected CVP_CONFIG_ERROR_LATCHED!\n");  		return -EPROTO;  	}  	/* STEP 17 - reset CVP_MODE and HIP_CLK_SEL bit */ -	pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); +	altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val);  	val &= ~VSE_CVP_MODE_CTRL_HIP_CLK_SEL;  	val &= ~VSE_CVP_MODE_CTRL_CVP_MODE; -	pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); +	altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val);  	/* STEP 18 - poll PLD_CLK_IN_USE and USER_MODE bits */  	mask = VSE_CVP_STATUS_PLD_CLK_IN_USE | VSE_CVP_STATUS_USERMODE; -	ret = altera_cvp_wait_status(conf, mask, mask, TIMEOUT_US); +	ret = altera_cvp_wait_status(conf, mask, mask, +				     conf->priv->user_time_us);  	if (ret)  		dev_err(&mgr->dev, "PLD_CLK_IN_USE|USERMODE timeout\n"); @@ -353,6 +522,21 @@ static const struct fpga_manager_ops altera_cvp_ops = {  	.write_complete	= altera_cvp_write_complete,  }; +static const struct cvp_priv cvp_priv_v1 = { +	.switch_clk	= altera_cvp_dummy_write, +	.block_size	= ALTERA_CVP_V1_SIZE, +	.poll_time_us	= V1_POLL_TIMEOUT_US, +	.user_time_us	= TIMEOUT_US, +}; + +static const struct cvp_priv cvp_priv_v2 = { +	.clear_state	= altera_cvp_v2_clear_state, +	.wait_credit	= altera_cvp_v2_wait_for_credit, +	.block_size	= ALTERA_CVP_V2_SIZE, +	.poll_time_us	= V2_POLL_TIMEOUT_US, +	.user_time_us	= V2_USER_TIMEOUT_US, +}; +  static ssize_t chkcfg_show(struct device_driver *dev, char *buf)  {  	return snprintf(buf, 3, "%d\n", altera_cvp_chkcfg); @@ -394,22 +578,29 @@ static int altera_cvp_probe(struct pci_dev *pdev,  {  	struct altera_cvp_conf *conf;  	struct fpga_manager *mgr; +	int ret, offset;  	u16 cmd, val;  	u32 regval; -	int ret; + +	/* Discover the Vendor Specific Offset for this device */ +	offset = pci_find_next_ext_capability(pdev, 0, PCI_EXT_CAP_ID_VNDR); +	if (!offset) { +		dev_err(&pdev->dev, "No Vendor Specific Offset.\n"); +		return -ENODEV; +	}  	/*  	 * First check if this is the expected FPGA device. PCI config  	 * space access works without enabling the PCI device, memory  	 * space access is enabled further down.  	 */ -	pci_read_config_word(pdev, VSE_PCIE_EXT_CAP_ID, &val); +	pci_read_config_word(pdev, offset + VSE_PCIE_EXT_CAP_ID, &val);  	if (val != VSE_PCIE_EXT_CAP_ID_VAL) {  		dev_err(&pdev->dev, "Wrong EXT_CAP_ID value 0x%x\n", val);  		return -ENODEV;  	} -	pci_read_config_dword(pdev, VSE_CVP_STATUS, ®val); +	pci_read_config_dword(pdev, offset + VSE_CVP_STATUS, ®val);  	if (!(regval & VSE_CVP_STATUS_CVP_EN)) {  		dev_err(&pdev->dev,  			"CVP is disabled for this device: CVP_STATUS Reg 0x%x\n", @@ -421,6 +612,8 @@ static int altera_cvp_probe(struct pci_dev *pdev,  	if (!conf)  		return -ENOMEM; +	conf->vsec_offset = offset; +  	/*  	 * Enable memory BAR access. We cannot use pci_enable_device() here  	 * because it will make the driver unusable with FPGA devices that @@ -445,6 +638,11 @@ static int altera_cvp_probe(struct pci_dev *pdev,  	conf->pci_dev = pdev;  	conf->write_data = altera_cvp_write_data_iomem; +	if (conf->vsec_offset == V1_VSEC_OFFSET) +		conf->priv = &cvp_priv_v1; +	else +		conf->priv = &cvp_priv_v2; +  	conf->map = pci_iomap(pdev, CVP_BAR, 0);  	if (!conf->map) {  		dev_warn(&pdev->dev, "Mapping CVP BAR failed\n");  |