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(dev: 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(dev: pdev, nr: 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(dev: &pdev->dev, name: "pclk" , NULL, flags: 0, |
63 | GEM_PCLK_RATE); |
64 | if (IS_ERR(ptr: plat_data.pclk)) { |
65 | err = PTR_ERR(ptr: plat_data.pclk); |
66 | goto err_pclk_register; |
67 | } |
68 | |
69 | plat_data.hclk = clk_register_fixed_rate(dev: &pdev->dev, name: "hclk" , NULL, flags: 0, |
70 | GEM_HCLK_RATE); |
71 | if (IS_ERR(ptr: plat_data.hclk)) { |
72 | err = PTR_ERR(ptr: 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(pdevinfo: &plat_info); |
90 | if (IS_ERR(ptr: plat_dev)) { |
91 | err = PTR_ERR(ptr: plat_dev); |
92 | goto err_plat_dev_register; |
93 | } |
94 | |
95 | pci_set_drvdata(pdev, data: plat_dev); |
96 | |
97 | return 0; |
98 | |
99 | err_plat_dev_register: |
100 | clk_unregister(clk: plat_data.hclk); |
101 | |
102 | err_hclk_register: |
103 | clk_unregister(clk: 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(dev: &plat_dev->dev); |
113 | |
114 | clk_unregister(clk: plat_data->pclk); |
115 | clk_unregister(clk: plat_data->hclk); |
116 | platform_device_unregister(plat_dev); |
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 | |