1e8f0c23aSPavel Pisa // SPDX-License-Identifier: GPL-2.0-or-later 2e8f0c23aSPavel Pisa /******************************************************************************* 3e8f0c23aSPavel Pisa * 4e8f0c23aSPavel Pisa * CTU CAN FD IP Core 5e8f0c23aSPavel Pisa * 6e8f0c23aSPavel Pisa * Copyright (C) 2015-2018 Ondrej Ille <ondrej.ille@gmail.com> FEE CTU 7e8f0c23aSPavel Pisa * Copyright (C) 2018-2021 Ondrej Ille <ondrej.ille@gmail.com> self-funded 8e8f0c23aSPavel Pisa * Copyright (C) 2018-2019 Martin Jerabek <martin.jerabek01@gmail.com> FEE CTU 9e8f0c23aSPavel Pisa * Copyright (C) 2018-2022 Pavel Pisa <pisa@cmp.felk.cvut.cz> FEE CTU/self-funded 10e8f0c23aSPavel Pisa * 11e8f0c23aSPavel Pisa * Project advisors: 12e8f0c23aSPavel Pisa * Jiri Novak <jnovak@fel.cvut.cz> 13e8f0c23aSPavel Pisa * Pavel Pisa <pisa@cmp.felk.cvut.cz> 14e8f0c23aSPavel Pisa * 15e8f0c23aSPavel Pisa * Department of Measurement (http://meas.fel.cvut.cz/) 16e8f0c23aSPavel Pisa * Faculty of Electrical Engineering (http://www.fel.cvut.cz) 17e8f0c23aSPavel Pisa * Czech Technical University (http://www.cvut.cz/) 18e8f0c23aSPavel Pisa ******************************************************************************/ 19e8f0c23aSPavel Pisa 20e8f0c23aSPavel Pisa #include <linux/module.h> 21e8f0c23aSPavel Pisa #include <linux/netdevice.h> 22e8f0c23aSPavel Pisa #include <linux/of.h> 23e8f0c23aSPavel Pisa #include <linux/platform_device.h> 24e8f0c23aSPavel Pisa #include <linux/pm_runtime.h> 25e8f0c23aSPavel Pisa 26e8f0c23aSPavel Pisa #include "ctucanfd.h" 27e8f0c23aSPavel Pisa 28e8f0c23aSPavel Pisa #define DRV_NAME "ctucanfd" 29e8f0c23aSPavel Pisa 30e8f0c23aSPavel Pisa static void ctucan_platform_set_drvdata(struct device *dev, 31e8f0c23aSPavel Pisa struct net_device *ndev) 32e8f0c23aSPavel Pisa { 33e8f0c23aSPavel Pisa struct platform_device *pdev = container_of(dev, struct platform_device, 34e8f0c23aSPavel Pisa dev); 35e8f0c23aSPavel Pisa 36e8f0c23aSPavel Pisa platform_set_drvdata(pdev, ndev); 37e8f0c23aSPavel Pisa } 38e8f0c23aSPavel Pisa 39e8f0c23aSPavel Pisa /** 40e8f0c23aSPavel Pisa * ctucan_platform_probe - Platform registration call 41e8f0c23aSPavel Pisa * @pdev: Handle to the platform device structure 42e8f0c23aSPavel Pisa * 43e8f0c23aSPavel Pisa * This function does all the memory allocation and registration for the CAN 44e8f0c23aSPavel Pisa * device. 45e8f0c23aSPavel Pisa * 46e8f0c23aSPavel Pisa * Return: 0 on success and failure value on error 47e8f0c23aSPavel Pisa */ 48e8f0c23aSPavel Pisa static int ctucan_platform_probe(struct platform_device *pdev) 49e8f0c23aSPavel Pisa { 50e8f0c23aSPavel Pisa struct device *dev = &pdev->dev; 51e8f0c23aSPavel Pisa void __iomem *addr; 52e8f0c23aSPavel Pisa int ret; 53e8f0c23aSPavel Pisa unsigned int ntxbufs; 54e8f0c23aSPavel Pisa int irq; 55e8f0c23aSPavel Pisa 56e8f0c23aSPavel Pisa /* Get the virtual base address for the device */ 57470ac62dSYang Li addr = devm_platform_ioremap_resource(pdev, 0); 58e8f0c23aSPavel Pisa if (IS_ERR(addr)) { 59e8f0c23aSPavel Pisa ret = PTR_ERR(addr); 60e8f0c23aSPavel Pisa goto err; 61e8f0c23aSPavel Pisa } 62e8f0c23aSPavel Pisa irq = platform_get_irq(pdev, 0); 63e8f0c23aSPavel Pisa if (irq < 0) { 64e8f0c23aSPavel Pisa ret = irq; 65e8f0c23aSPavel Pisa goto err; 66e8f0c23aSPavel Pisa } 67e8f0c23aSPavel Pisa 68e8f0c23aSPavel Pisa /* Number of tx bufs might be change in HW for future. If so, 69e8f0c23aSPavel Pisa * it will be passed as property via device tree 70e8f0c23aSPavel Pisa */ 71e8f0c23aSPavel Pisa ntxbufs = 4; 72e8f0c23aSPavel Pisa ret = ctucan_probe_common(dev, addr, irq, ntxbufs, 0, 73e8f0c23aSPavel Pisa 1, ctucan_platform_set_drvdata); 74e8f0c23aSPavel Pisa 75e8f0c23aSPavel Pisa if (ret < 0) 76e8f0c23aSPavel Pisa platform_set_drvdata(pdev, NULL); 77e8f0c23aSPavel Pisa 78e8f0c23aSPavel Pisa err: 79e8f0c23aSPavel Pisa return ret; 80e8f0c23aSPavel Pisa } 81e8f0c23aSPavel Pisa 82e8f0c23aSPavel Pisa /** 83e8f0c23aSPavel Pisa * ctucan_platform_remove - Unregister the device after releasing the resources 84e8f0c23aSPavel Pisa * @pdev: Handle to the platform device structure 85e8f0c23aSPavel Pisa * 86e8f0c23aSPavel Pisa * This function frees all the resources allocated to the device. 87e8f0c23aSPavel Pisa * Return: 0 always 88e8f0c23aSPavel Pisa */ 8945413bf7SUwe Kleine-König static void ctucan_platform_remove(struct platform_device *pdev) 90e8f0c23aSPavel Pisa { 91e8f0c23aSPavel Pisa struct net_device *ndev = platform_get_drvdata(pdev); 92e8f0c23aSPavel Pisa struct ctucan_priv *priv = netdev_priv(ndev); 93e8f0c23aSPavel Pisa 94e8f0c23aSPavel Pisa netdev_dbg(ndev, "ctucan_remove"); 95e8f0c23aSPavel Pisa 96e8f0c23aSPavel Pisa unregister_candev(ndev); 97e8f0c23aSPavel Pisa pm_runtime_disable(&pdev->dev); 98e8f0c23aSPavel Pisa netif_napi_del(&priv->napi); 99e8f0c23aSPavel Pisa free_candev(ndev); 100e8f0c23aSPavel Pisa } 101e8f0c23aSPavel Pisa 102e8f0c23aSPavel Pisa static SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume); 103e8f0c23aSPavel Pisa 104e8f0c23aSPavel Pisa /* Match table for OF platform binding */ 105e8f0c23aSPavel Pisa static const struct of_device_id ctucan_of_match[] = { 106e8f0c23aSPavel Pisa { .compatible = "ctu,ctucanfd-2", }, 107e8f0c23aSPavel Pisa { .compatible = "ctu,ctucanfd", }, 108e8f0c23aSPavel Pisa { /* end of list */ }, 109e8f0c23aSPavel Pisa }; 110e8f0c23aSPavel Pisa MODULE_DEVICE_TABLE(of, ctucan_of_match); 111e8f0c23aSPavel Pisa 112e8f0c23aSPavel Pisa static struct platform_driver ctucanfd_driver = { 113e8f0c23aSPavel Pisa .probe = ctucan_platform_probe, 114*221013afSUwe Kleine-König .remove = ctucan_platform_remove, 115e8f0c23aSPavel Pisa .driver = { 116e8f0c23aSPavel Pisa .name = DRV_NAME, 117e8f0c23aSPavel Pisa .pm = &ctucan_platform_pm_ops, 118e8f0c23aSPavel Pisa .of_match_table = ctucan_of_match, 119e8f0c23aSPavel Pisa }, 120e8f0c23aSPavel Pisa }; 121e8f0c23aSPavel Pisa 122e8f0c23aSPavel Pisa module_platform_driver(ctucanfd_driver); 123e8f0c23aSPavel Pisa 124e8f0c23aSPavel Pisa MODULE_LICENSE("GPL"); 125e8f0c23aSPavel Pisa MODULE_AUTHOR("Martin Jerabek"); 126e8f0c23aSPavel Pisa MODULE_DESCRIPTION("CTU CAN FD for platform"); 127