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