in altera-cvp.c [576:674]
static int altera_cvp_probe(struct pci_dev *pdev,
const struct pci_device_id *dev_id)
{
struct altera_cvp_conf *conf;
struct fpga_manager *mgr;
int ret, offset;
u16 cmd, val;
u32 regval;
/* 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, 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, 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",
regval);
return -ENODEV;
}
conf = devm_kzalloc(&pdev->dev, sizeof(*conf), GFP_KERNEL);
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
* have additional big IOMEM resources (e.g. 4GiB BARs) on 32-bit
* platform. Such BARs will not have an assigned address range and
* pci_enable_device() will fail, complaining about not claimed BAR,
* even if the concerned BAR is not needed for FPGA configuration
* at all. Thus, enable the device via PCI config space command.
*/
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
if (!(cmd & PCI_COMMAND_MEMORY)) {
cmd |= PCI_COMMAND_MEMORY;
pci_write_config_word(pdev, PCI_COMMAND, cmd);
}
ret = pci_request_region(pdev, CVP_BAR, "CVP");
if (ret) {
dev_err(&pdev->dev, "Requesting CVP BAR region failed\n");
goto err_disable;
}
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");
conf->write_data = altera_cvp_write_data_config;
}
snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s @%s",
ALTERA_CVP_MGR_NAME, pci_name(pdev));
mgr = fpga_mgr_register(&pdev->dev, conf->mgr_name,
&altera_cvp_ops, conf);
if (IS_ERR(mgr)) {
ret = PTR_ERR(mgr);
goto err_unmap;
}
pci_set_drvdata(pdev, mgr);
return 0;
err_unmap:
if (conf->map)
pci_iounmap(pdev, conf->map);
pci_release_region(pdev, CVP_BAR);
err_disable:
cmd &= ~PCI_COMMAND_MEMORY;
pci_write_config_word(pdev, PCI_COMMAND, cmd);
return ret;
}