diff --git a/driver/ctu_can_fd.c b/driver/ctu_can_fd.c index e72e9e5c152a0c96e66e2b18ffbf282d81835cc6..e1752da36f00c6d41c3a6f1ff0dd0e69de39586d 100644 --- a/driver/ctu_can_fd.c +++ b/driver/ctu_can_fd.c @@ -1189,9 +1189,28 @@ module_platform_driver(ctucanfd_driver); #include -#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 = {