1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /******************************************************************************* 3 * 4 * CTU CAN FD IP Core 5 * 6 * Copyright (C) 2015-2018 Ondrej Ille <ondrej.ille@gmail.com> FEE CTU 7 * Copyright (C) 2018-2021 Ondrej Ille <ondrej.ille@gmail.com> self-funded 8 * Copyright (C) 2018-2019 Martin Jerabek <martin.jerabek01@gmail.com> FEE CTU 9 * Copyright (C) 2018-2022 Pavel Pisa <pisa@cmp.felk.cvut.cz> FEE CTU/self-funded 10 * 11 * Project advisors: 12 * Jiri Novak <jnovak@fel.cvut.cz> 13 * Pavel Pisa <pisa@cmp.felk.cvut.cz> 14 * 15 * Department of Measurement (http://meas.fel.cvut.cz/) 16 * Faculty of Electrical Engineering (http://www.fel.cvut.cz) 17 * Czech Technical University (http://www.cvut.cz/) 18 ******************************************************************************/ 19 20 #include <linux/module.h> 21 #include <linux/pci.h> 22 23 #include "ctucanfd.h" 24 25 #ifndef PCI_DEVICE_DATA 26 #define PCI_DEVICE_DATA(vend, dev, data) \ 27 .vendor = PCI_VENDOR_ID_##vend, \ 28 .device = PCI_DEVICE_ID_##vend##_##dev, \ 29 .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0, \ 30 .driver_data = (kernel_ulong_t)(data) 31 #endif 32 33 #ifndef PCI_VENDOR_ID_TEDIA 34 #define PCI_VENDOR_ID_TEDIA 0x1760 35 #endif 36 37 #ifndef PCI_DEVICE_ID_TEDIA_CTUCAN_VER21 38 #define PCI_DEVICE_ID_TEDIA_CTUCAN_VER21 0xff00 39 #endif 40 41 #define CTUCAN_BAR0_CTUCAN_ID 0x0000 42 #define CTUCAN_BAR0_CRA_BASE 0x4000 43 #define CYCLONE_IV_CRA_A2P_IE (0x0050) 44 45 #define CTUCAN_WITHOUT_CTUCAN_ID 0 46 #define CTUCAN_WITH_CTUCAN_ID 1 47 48 static bool use_msi = true; 49 module_param(use_msi, bool, 0444); 50 MODULE_PARM_DESC(use_msi, "PCIe implementation use MSI interrupts. Default: 1 (yes)"); 51 52 static bool pci_use_second = true; 53 module_param(pci_use_second, bool, 0444); 54 MODULE_PARM_DESC(pci_use_second, "Use the second CAN core on PCIe card. Default: 1 (yes)"); 55 56 struct ctucan_pci_board_data { 57 void __iomem *bar0_base; 58 void __iomem *cra_base; 59 void __iomem *bar1_base; 60 struct list_head ndev_list_head; 61 int use_msi; 62 }; 63 64 static struct ctucan_pci_board_data *ctucan_pci_get_bdata(struct pci_dev *pdev) 65 { 66 return (struct ctucan_pci_board_data *)pci_get_drvdata(pdev); 67 } 68 69 static void ctucan_pci_set_drvdata(struct device *dev, 70 struct net_device *ndev) 71 { 72 struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); 73 struct ctucan_priv *priv = netdev_priv(ndev); 74 struct ctucan_pci_board_data *bdata = ctucan_pci_get_bdata(pdev); 75 76 list_add(&priv->peers_on_pdev, &bdata->ndev_list_head); 77 priv->irq_flags = IRQF_SHARED; 78 } 79 80 /** 81 * ctucan_pci_probe - PCI registration call 82 * @pdev: Handle to the pci device structure 83 * @ent: Pointer to the entry from ctucan_pci_tbl 84 * 85 * This function does all the memory allocation and registration for the CAN 86 * device. 87 * 88 * Return: 0 on success and failure value on error 89 */ 90 static int ctucan_pci_probe(struct pci_dev *pdev, 91 const struct pci_device_id *ent) 92 { 93 struct device *dev = &pdev->dev; 94 unsigned long driver_data = ent->driver_data; 95 struct ctucan_pci_board_data *bdata; 96 void __iomem *addr; 97 void __iomem *cra_addr; 98 void __iomem *bar0_base; 99 u32 cra_a2p_ie; 100 u32 ctucan_id = 0; 101 int ret; 102 unsigned int ntxbufs; 103 unsigned int num_cores = 1; 104 unsigned int core_i = 0; 105 int irq; 106 int msi_ok = 0; 107 108 ret = pci_enable_device(pdev); 109 if (ret) { 110 dev_err(dev, "pci_enable_device FAILED\n"); 111 goto err; 112 } 113 114 ret = pci_request_regions(pdev, KBUILD_MODNAME); 115 if (ret) { 116 dev_err(dev, "pci_request_regions FAILED\n"); 117 goto err_disable_device; 118 } 119 120 if (use_msi) { 121 ret = pci_enable_msi(pdev); 122 if (!ret) { 123 dev_info(dev, "MSI enabled\n"); 124 pci_set_master(pdev); 125 msi_ok = 1; 126 } 127 } 128 129 dev_info(dev, "ctucan BAR0 0x%08llx 0x%08llx\n", 130 (long long)pci_resource_start(pdev, 0), 131 (long long)pci_resource_len(pdev, 0)); 132 133 dev_info(dev, "ctucan BAR1 0x%08llx 0x%08llx\n", 134 (long long)pci_resource_start(pdev, 1), 135 (long long)pci_resource_len(pdev, 1)); 136 137 addr = pci_iomap(pdev, 1, pci_resource_len(pdev, 1)); 138 if (!addr) { 139 dev_err(dev, "PCI BAR 1 cannot be mapped\n"); 140 ret = -ENOMEM; 141 goto err_release_regions; 142 } 143 144 /* Cyclone IV PCI Express Control Registers Area */ 145 bar0_base = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); 146 if (!bar0_base) { 147 dev_err(dev, "PCI BAR 0 cannot be mapped\n"); 148 ret = -EIO; 149 goto err_pci_iounmap_bar1; 150 } 151 152 if (driver_data == CTUCAN_WITHOUT_CTUCAN_ID) { 153 cra_addr = bar0_base; 154 num_cores = 2; 155 } else { 156 cra_addr = bar0_base + CTUCAN_BAR0_CRA_BASE; 157 ctucan_id = ioread32(bar0_base + CTUCAN_BAR0_CTUCAN_ID); 158 dev_info(dev, "ctucan_id 0x%08lx\n", (unsigned long)ctucan_id); 159 num_cores = ctucan_id & 0xf; 160 } 161 162 irq = pdev->irq; 163 164 ntxbufs = 4; 165 166 bdata = kzalloc(sizeof(*bdata), GFP_KERNEL); 167 if (!bdata) { 168 ret = -ENOMEM; 169 goto err_pci_iounmap_bar0; 170 } 171 172 INIT_LIST_HEAD(&bdata->ndev_list_head); 173 bdata->bar0_base = bar0_base; 174 bdata->cra_base = cra_addr; 175 bdata->bar1_base = addr; 176 bdata->use_msi = msi_ok; 177 178 pci_set_drvdata(pdev, bdata); 179 180 ret = ctucan_probe_common(dev, addr, irq, ntxbufs, 100000000, 181 0, ctucan_pci_set_drvdata); 182 if (ret < 0) 183 goto err_free_board; 184 185 core_i++; 186 187 while (pci_use_second && (core_i < num_cores)) { 188 addr += 0x4000; 189 ret = ctucan_probe_common(dev, addr, irq, ntxbufs, 100000000, 190 0, ctucan_pci_set_drvdata); 191 if (ret < 0) { 192 dev_info(dev, "CTU CAN FD core %d initialization failed\n", 193 core_i); 194 break; 195 } 196 core_i++; 197 } 198 199 /* enable interrupt in 200 * Avalon-MM to PCI Express Interrupt Enable Register 201 */ 202 cra_a2p_ie = ioread32(cra_addr + CYCLONE_IV_CRA_A2P_IE); 203 dev_info(dev, "cra_a2p_ie 0x%08x\n", cra_a2p_ie); 204 cra_a2p_ie |= 1; 205 iowrite32(cra_a2p_ie, cra_addr + CYCLONE_IV_CRA_A2P_IE); 206 cra_a2p_ie = ioread32(cra_addr + CYCLONE_IV_CRA_A2P_IE); 207 dev_info(dev, "cra_a2p_ie 0x%08x\n", cra_a2p_ie); 208 209 return 0; 210 211 err_free_board: 212 pci_set_drvdata(pdev, NULL); 213 kfree(bdata); 214 err_pci_iounmap_bar0: 215 pci_iounmap(pdev, cra_addr); 216 err_pci_iounmap_bar1: 217 pci_iounmap(pdev, addr); 218 err_release_regions: 219 if (msi_ok) { 220 pci_disable_msi(pdev); 221 pci_clear_master(pdev); 222 } 223 pci_release_regions(pdev); 224 err_disable_device: 225 pci_disable_device(pdev); 226 err: 227 return ret; 228 } 229 230 /** 231 * ctucan_pci_remove - Unregister the device after releasing the resources 232 * @pdev: Handle to the pci device structure 233 * 234 * This function frees all the resources allocated to the device. 235 * Return: 0 always 236 */ 237 static void ctucan_pci_remove(struct pci_dev *pdev) 238 { 239 struct net_device *ndev; 240 struct ctucan_priv *priv = NULL; 241 struct ctucan_pci_board_data *bdata = ctucan_pci_get_bdata(pdev); 242 243 dev_dbg(&pdev->dev, "ctucan_remove"); 244 245 if (!bdata) { 246 dev_err(&pdev->dev, "%s: no list of devices\n", __func__); 247 return; 248 } 249 250 /* disable interrupt in 251 * Avalon-MM to PCI Express Interrupt Enable Register 252 */ 253 if (bdata->cra_base) 254 iowrite32(0, bdata->cra_base + CYCLONE_IV_CRA_A2P_IE); 255 256 while ((priv = list_first_entry_or_null(&bdata->ndev_list_head, struct ctucan_priv, 257 peers_on_pdev)) != NULL) { 258 ndev = priv->can.dev; 259 260 unregister_candev(ndev); 261 262 netif_napi_del(&priv->napi); 263 264 list_del_init(&priv->peers_on_pdev); 265 free_candev(ndev); 266 } 267 268 pci_iounmap(pdev, bdata->bar1_base); 269 270 if (bdata->use_msi) { 271 pci_disable_msi(pdev); 272 pci_clear_master(pdev); 273 } 274 275 pci_release_regions(pdev); 276 pci_disable_device(pdev); 277 278 pci_iounmap(pdev, bdata->bar0_base); 279 280 pci_set_drvdata(pdev, NULL); 281 kfree(bdata); 282 } 283 284 static SIMPLE_DEV_PM_OPS(ctucan_pci_pm_ops, ctucan_suspend, ctucan_resume); 285 286 static const struct pci_device_id ctucan_pci_tbl[] = { 287 {PCI_DEVICE_DATA(TEDIA, CTUCAN_VER21, 288 CTUCAN_WITH_CTUCAN_ID)}, 289 {}, 290 }; 291 292 static struct pci_driver ctucan_pci_driver = { 293 .name = KBUILD_MODNAME, 294 .id_table = ctucan_pci_tbl, 295 .probe = ctucan_pci_probe, 296 .remove = ctucan_pci_remove, 297 .driver.pm = &ctucan_pci_pm_ops, 298 }; 299 300 module_pci_driver(ctucan_pci_driver); 301 302 MODULE_LICENSE("GPL"); 303 MODULE_AUTHOR("Pavel Pisa <pisa@cmp.felk.cvut.cz>"); 304 MODULE_DESCRIPTION("CTU CAN FD for PCI bus"); 305