1 // SPDX-License-Identifier: GPL-2.0-only 2 /** 3 * DOC: Cadence GEM PCI wrapper. 4 * 5 * Copyright (C) 2016 Cadence Design Systems - https://www.cadence.com 6 * 7 * Authors: Rafal Ozieblo <rafalo@cadence.com> 8 * Bartosz Folta <bfolta@cadence.com> 9 */ 10 11 #include <linux/clk.h> 12 #include <linux/clk-provider.h> 13 #include <linux/etherdevice.h> 14 #include <linux/module.h> 15 #include <linux/pci.h> 16 #include <linux/platform_device.h> 17 #include "macb.h" 18 19 #define PCI_DRIVER_NAME "macb_pci" 20 #define PLAT_DRIVER_NAME "macb" 21 22 #define CDNS_VENDOR_ID 0x17cd 23 #define CDNS_DEVICE_ID 0xe007 24 25 #define GEM_PCLK_RATE 50000000 26 #define GEM_HCLK_RATE 50000000 27 28 static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id) 29 { 30 int err; 31 struct platform_device *plat_dev; 32 struct platform_device_info plat_info; 33 struct macb_platform_data plat_data; 34 struct resource res[2]; 35 36 /* enable pci device */ 37 err = pcim_enable_device(pdev); 38 if (err < 0) { 39 dev_err(&pdev->dev, "Enabling PCI device has failed: %d", err); 40 return err; 41 } 42 43 pci_set_master(pdev); 44 45 /* set up resources */ 46 memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); 47 res[0].start = pci_resource_start(pdev, 0); 48 res[0].end = pci_resource_end(pdev, 0); 49 res[0].name = PCI_DRIVER_NAME; 50 res[0].flags = IORESOURCE_MEM; 51 res[1].start = pci_irq_vector(pdev, 0); 52 res[1].name = PCI_DRIVER_NAME; 53 res[1].flags = IORESOURCE_IRQ; 54 55 dev_info(&pdev->dev, "EMAC physical base addr: %pa\n", 56 &res[0].start); 57 58 /* set up macb platform data */ 59 memset(&plat_data, 0, sizeof(plat_data)); 60 61 /* initialize clocks */ 62 plat_data.pclk = clk_register_fixed_rate(&pdev->dev, "pclk", NULL, 0, 63 GEM_PCLK_RATE); 64 if (IS_ERR(plat_data.pclk)) { 65 err = PTR_ERR(plat_data.pclk); 66 goto err_pclk_register; 67 } 68 69 plat_data.hclk = clk_register_fixed_rate(&pdev->dev, "hclk", NULL, 0, 70 GEM_HCLK_RATE); 71 if (IS_ERR(plat_data.hclk)) { 72 err = PTR_ERR(plat_data.hclk); 73 goto err_hclk_register; 74 } 75 76 /* set up platform device info */ 77 memset(&plat_info, 0, sizeof(plat_info)); 78 plat_info.parent = &pdev->dev; 79 plat_info.fwnode = pdev->dev.fwnode; 80 plat_info.name = PLAT_DRIVER_NAME; 81 plat_info.id = pdev->devfn; 82 plat_info.res = res; 83 plat_info.num_res = ARRAY_SIZE(res); 84 plat_info.data = &plat_data; 85 plat_info.size_data = sizeof(plat_data); 86 plat_info.dma_mask = pdev->dma_mask; 87 88 /* register platform device */ 89 plat_dev = platform_device_register_full(&plat_info); 90 if (IS_ERR(plat_dev)) { 91 err = PTR_ERR(plat_dev); 92 goto err_plat_dev_register; 93 } 94 95 pci_set_drvdata(pdev, plat_dev); 96 97 return 0; 98 99 err_plat_dev_register: 100 clk_unregister(plat_data.hclk); 101 102 err_hclk_register: 103 clk_unregister(plat_data.pclk); 104 105 err_pclk_register: 106 return err; 107 } 108 109 static void macb_remove(struct pci_dev *pdev) 110 { 111 struct platform_device *plat_dev = pci_get_drvdata(pdev); 112 struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev); 113 114 platform_device_unregister(plat_dev); 115 clk_unregister(plat_data->pclk); 116 clk_unregister(plat_data->hclk); 117 } 118 119 static const struct pci_device_id dev_id_table[] = { 120 { PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), }, 121 { 0, } 122 }; 123 124 static struct pci_driver macb_pci_driver = { 125 .name = PCI_DRIVER_NAME, 126 .id_table = dev_id_table, 127 .probe = macb_probe, 128 .remove = macb_remove, 129 }; 130 131 module_pci_driver(macb_pci_driver); 132 MODULE_DEVICE_TABLE(pci, dev_id_table); 133 MODULE_LICENSE("GPL"); 134 MODULE_DESCRIPTION("Cadence NIC PCI wrapper"); 135