1 /** 2 * Cadence GEM PCI wrapper. 3 * 4 * Copyright (C) 2016 Cadence Design Systems - http://www.cadence.com 5 * 6 * Authors: Rafal Ozieblo <rafalo@cadence.com> 7 * Bartosz Folta <bfolta@cadence.com> 8 * 9 * This program is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 of 11 * the License as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include <linux/clk.h> 23 #include <linux/clk-provider.h> 24 #include <linux/etherdevice.h> 25 #include <linux/module.h> 26 #include <linux/pci.h> 27 #include <linux/platform_data/macb.h> 28 #include <linux/platform_device.h> 29 #include "macb.h" 30 31 #define PCI_DRIVER_NAME "macb_pci" 32 #define PLAT_DRIVER_NAME "macb" 33 34 #define CDNS_VENDOR_ID 0x17cd 35 #define CDNS_DEVICE_ID 0xe007 36 37 #define GEM_PCLK_RATE 50000000 38 #define GEM_HCLK_RATE 50000000 39 40 static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id) 41 { 42 int err; 43 struct platform_device *plat_dev; 44 struct platform_device_info plat_info; 45 struct macb_platform_data plat_data; 46 struct resource res[2]; 47 48 /* enable pci device */ 49 err = pcim_enable_device(pdev); 50 if (err < 0) { 51 dev_err(&pdev->dev, "Enabling PCI device has failed: %d", err); 52 return err; 53 } 54 55 pci_set_master(pdev); 56 57 /* set up resources */ 58 memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); 59 res[0].start = pci_resource_start(pdev, 0); 60 res[0].end = pci_resource_end(pdev, 0); 61 res[0].name = PCI_DRIVER_NAME; 62 res[0].flags = IORESOURCE_MEM; 63 res[1].start = pci_irq_vector(pdev, 0); 64 res[1].name = PCI_DRIVER_NAME; 65 res[1].flags = IORESOURCE_IRQ; 66 67 dev_info(&pdev->dev, "EMAC physical base addr: %pa\n", 68 &res[0].start); 69 70 /* set up macb platform data */ 71 memset(&plat_data, 0, sizeof(plat_data)); 72 73 /* initialize clocks */ 74 plat_data.pclk = clk_register_fixed_rate(&pdev->dev, "pclk", NULL, 0, 75 GEM_PCLK_RATE); 76 if (IS_ERR(plat_data.pclk)) { 77 err = PTR_ERR(plat_data.pclk); 78 goto err_pclk_register; 79 } 80 81 plat_data.hclk = clk_register_fixed_rate(&pdev->dev, "hclk", NULL, 0, 82 GEM_HCLK_RATE); 83 if (IS_ERR(plat_data.hclk)) { 84 err = PTR_ERR(plat_data.hclk); 85 goto err_hclk_register; 86 } 87 88 /* set up platform device info */ 89 memset(&plat_info, 0, sizeof(plat_info)); 90 plat_info.parent = &pdev->dev; 91 plat_info.fwnode = pdev->dev.fwnode; 92 plat_info.name = PLAT_DRIVER_NAME; 93 plat_info.id = pdev->devfn; 94 plat_info.res = res; 95 plat_info.num_res = ARRAY_SIZE(res); 96 plat_info.data = &plat_data; 97 plat_info.size_data = sizeof(plat_data); 98 plat_info.dma_mask = pdev->dma_mask; 99 100 /* register platform device */ 101 plat_dev = platform_device_register_full(&plat_info); 102 if (IS_ERR(plat_dev)) { 103 err = PTR_ERR(plat_dev); 104 goto err_plat_dev_register; 105 } 106 107 pci_set_drvdata(pdev, plat_dev); 108 109 return 0; 110 111 err_plat_dev_register: 112 clk_unregister(plat_data.hclk); 113 114 err_hclk_register: 115 clk_unregister(plat_data.pclk); 116 117 err_pclk_register: 118 return err; 119 } 120 121 static void macb_remove(struct pci_dev *pdev) 122 { 123 struct platform_device *plat_dev = pci_get_drvdata(pdev); 124 struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev); 125 126 platform_device_unregister(plat_dev); 127 clk_unregister(plat_data->pclk); 128 clk_unregister(plat_data->hclk); 129 } 130 131 static const struct pci_device_id dev_id_table[] = { 132 { PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), }, 133 { 0, } 134 }; 135 136 static struct pci_driver macb_pci_driver = { 137 .name = PCI_DRIVER_NAME, 138 .id_table = dev_id_table, 139 .probe = macb_probe, 140 .remove = macb_remove, 141 }; 142 143 module_pci_driver(macb_pci_driver); 144 MODULE_DEVICE_TABLE(pci, dev_id_table); 145 MODULE_LICENSE("GPL"); 146 MODULE_DESCRIPTION("Cadence NIC PCI wrapper"); 147