Commit 408631e7 authored by Pavel Pisa's avatar Pavel Pisa
Browse files

driver: add reserved vendor and device ID and identification register.



The design with new unique ID implements identification
register at start of BAR0 which provides information
about number of implemented cores.
Signed-off-by: Pavel Pisa's avatarPavel Pisa <pisa@cmp.felk.cvut.cz>
parent 45cb2bf3
......@@ -1189,9 +1189,28 @@ module_platform_driver(ctucanfd_driver);
#include <linux/pci.h>
#define CYCLONE_IV_CRA_A2P_IE 0x0050
#ifndef PCI_DEVICE_DATA
#define PCI_DEVICE_DATA(vend, dev, data) \
.vendor = PCI_VENDOR_ID_##vend, .device = PCI_DEVICE_ID_##vend##_##dev, \
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0, \
.driver_data = (kernel_ulong_t)(data)
#endif
#ifndef PCI_VENDOR_ID_TEDIA
#define PCI_VENDOR_ID_TEDIA 0x1760
#endif
#define PCI_DEVICE_ID_ALTERA_CTUCAN_TEST 0xCAFD
#define PCI_DEVICE_ID_TEDIA_CTUCAN_VER21 0xff00
#define CTUCAN_BAR0_CTUCAN_ID 0x0000
#define CTUCAN_BAR0_CRA_BASE 0x4000
#define CYCLONE_IV_CRA_A2P_IE (0x0050)
#define CTUCAN_WITHOUT_CTUCAN_ID 0
#define CTUCAN_WITH_CTUCAN_ID 1
struct ctucan_pci_board_data {
void __iomem *bar0_base;
void __iomem *cra_base;
void __iomem *bar1_base;
struct list_head ndev_list_head;
......@@ -1227,12 +1246,17 @@ static int ctucan_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct device *dev = &pdev->dev;
unsigned long driver_data = ent->driver_data;
struct ctucan_pci_board_data *bdata;
void __iomem *addr;
void __iomem *cra_addr;
void __iomem *bar0_base;
u32 cra_a2p_ie;
u32 ctucan_id = 0;
int ret;
unsigned int ntxbufs;
unsigned int num_cores = 1;
unsigned int core_i = 0;
int irq;
int msi_ok = 0;
......@@ -1273,13 +1297,23 @@ static int ctucan_pci_probe(struct pci_dev *pdev,
}
/* Cyclone IV PCI Express Control Registers Area */
cra_addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
if (!cra_addr) {
bar0_base = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
if (!bar0_base) {
dev_err(dev, "PCI BAR 0 cannot be mapped\n");
ret = -EIO;
goto err_pci_iounmap_bar1;
}
if (driver_data == CTUCAN_WITHOUT_CTUCAN_ID) {
cra_addr = bar0_base;
num_cores = 2;
} else {
cra_addr = (char *)bar0_base + CTUCAN_BAR0_CRA_BASE;
ctucan_id = ioread32((char *)bar0_base + CTUCAN_BAR0_CTUCAN_ID);
dev_info(dev, "ctucan_id 0x%08lx\n", (unsigned long)ctucan_id);
num_cores = ctucan_id & 0xf;
}
irq = pdev->irq;
ntxbufs = 4;
......@@ -1292,6 +1326,7 @@ static int ctucan_pci_probe(struct pci_dev *pdev,
}
INIT_LIST_HEAD(&bdata->ndev_list_head);
bdata->bar0_base = bar0_base;
bdata->cra_base = cra_addr;
bdata->bar1_base = addr;
bdata->use_msi = msi_ok;
......@@ -1303,13 +1338,18 @@ static int ctucan_pci_probe(struct pci_dev *pdev,
if (ret < 0)
goto err_free_board;
if (pci_use_second) {
core_i++;
while (pci_use_second && (core_i < num_cores)) {
addr += 0x4000;
ret = ctucan_probe_common(dev, addr, irq, ntxbufs, 100000000,
0, ctucan_pci_set_drvdata);
if (ret < 0) {
dev_info(dev, "second CTU CAN FD core initialization failed\n");
dev_info(dev, "CTU CAN FD core %d initialization failed\n",
core_i);
break;
}
core_i++;
}
/* enable interrupt in
......@@ -1393,18 +1433,24 @@ static void ctucan_pci_remove(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_iounmap(pdev, bdata->cra_base);
pci_iounmap(pdev, bdata->bar0_base);
pci_set_drvdata(pdev, NULL);
kfree(bdata);
}
#define CTU_CAN_FD_DEVICE_ID 0xCAFD
#define CTU_CAN_FD_VENDOR_ID 0x1760
#define CTU_CAN_FD_DEVICE_ID 0xff00
#define CTU_CAN_FD_DEVICE_ID_TEST 0xCAFD
static SIMPLE_DEV_PM_OPS(ctucan_pci_pm_ops, ctucan_suspend, ctucan_resume);
static const struct pci_device_id ctucan_pci_tbl[] = {
{PCI_VDEVICE(ALTERA, CTU_CAN_FD_DEVICE_ID)},
{PCI_DEVICE_DATA(ALTERA, CTUCAN_TEST,
CTUCAN_WITHOUT_CTUCAN_ID)},
{PCI_DEVICE_DATA(TEDIA, CTUCAN_VER21,
CTUCAN_WITH_CTUCAN_ID)},
{},
};
static struct pci_driver ctucan_pci_driver = {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment