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