1 /** 2 * macb_pci.c - 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 /* sanity check */ 49 if (!id) 50 return -EINVAL; 51 52 /* enable pci device */ 53 err = pci_enable_device(pdev); 54 if (err < 0) { 55 dev_err(&pdev->dev, "Enabling PCI device has failed: 0x%04X", 56 err); 57 return -EACCES; 58 } 59 60 pci_set_master(pdev); 61 62 /* set up resources */ 63 memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); 64 res[0].start = pdev->resource[0].start; 65 res[0].end = pdev->resource[0].end; 66 res[0].name = PCI_DRIVER_NAME; 67 res[0].flags = IORESOURCE_MEM; 68 res[1].start = pdev->irq; 69 res[1].name = PCI_DRIVER_NAME; 70 res[1].flags = IORESOURCE_IRQ; 71 72 dev_info(&pdev->dev, "EMAC physical base addr = 0x%p\n", 73 (void *)(uintptr_t)pci_resource_start(pdev, 0)); 74 75 /* set up macb platform data */ 76 memset(&plat_data, 0, sizeof(plat_data)); 77 78 /* initialize clocks */ 79 plat_data.pclk = clk_register_fixed_rate(&pdev->dev, "pclk", NULL, 0, 80 GEM_PCLK_RATE); 81 if (IS_ERR(plat_data.pclk)) { 82 err = PTR_ERR(plat_data.pclk); 83 goto err_pclk_register; 84 } 85 86 plat_data.hclk = clk_register_fixed_rate(&pdev->dev, "hclk", NULL, 0, 87 GEM_HCLK_RATE); 88 if (IS_ERR(plat_data.hclk)) { 89 err = PTR_ERR(plat_data.hclk); 90 goto err_hclk_register; 91 } 92 93 /* set up platform device info */ 94 memset(&plat_info, 0, sizeof(plat_info)); 95 plat_info.parent = &pdev->dev; 96 plat_info.fwnode = pdev->dev.fwnode; 97 plat_info.name = PLAT_DRIVER_NAME; 98 plat_info.id = pdev->devfn; 99 plat_info.res = res; 100 plat_info.num_res = ARRAY_SIZE(res); 101 plat_info.data = &plat_data; 102 plat_info.size_data = sizeof(plat_data); 103 plat_info.dma_mask = DMA_BIT_MASK(32); 104 105 /* register platform device */ 106 plat_dev = platform_device_register_full(&plat_info); 107 if (IS_ERR(plat_dev)) { 108 err = PTR_ERR(plat_dev); 109 goto err_plat_dev_register; 110 } 111 112 pci_set_drvdata(pdev, plat_dev); 113 114 return 0; 115 116 err_plat_dev_register: 117 clk_unregister(plat_data.hclk); 118 119 err_hclk_register: 120 clk_unregister(plat_data.pclk); 121 122 err_pclk_register: 123 pci_disable_device(pdev); 124 return err; 125 } 126 127 static void macb_remove(struct pci_dev *pdev) 128 { 129 struct platform_device *plat_dev = pci_get_drvdata(pdev); 130 struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev); 131 132 platform_device_unregister(plat_dev); 133 pci_disable_device(pdev); 134 clk_unregister(plat_data->pclk); 135 clk_unregister(plat_data->hclk); 136 } 137 138 static struct pci_device_id dev_id_table[] = { 139 { PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), }, 140 { 0, } 141 }; 142 143 static struct pci_driver macb_pci_driver = { 144 .name = PCI_DRIVER_NAME, 145 .id_table = dev_id_table, 146 .probe = macb_probe, 147 .remove = macb_remove, 148 }; 149 150 module_pci_driver(macb_pci_driver); 151 MODULE_DEVICE_TABLE(pci, dev_id_table); 152 MODULE_LICENSE("GPL"); 153 MODULE_DESCRIPTION("Cadence NIC PCI wrapper"); 154