Commit | Line | Data |
---|---|---|
4fa9c49f | 1 | // SPDX-License-Identifier: GPL-2.0-only |
bfab27a1 GC |
2 | /******************************************************************************* |
3 | This contains the functions to handle the pci driver. | |
4 | ||
5 | Copyright (C) 2011-2012 Vayavya Labs Pvt Ltd | |
6 | ||
bfab27a1 GC |
7 | |
8 | Author: Rayagond Kokatanur <rayagond@vayavyalabs.com> | |
9 | Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> | |
10 | *******************************************************************************/ | |
11 | ||
190f73ab | 12 | #include <linux/clk-provider.h> |
bfab27a1 | 13 | #include <linux/pci.h> |
0763d955 AS |
14 | #include <linux/dmi.h> |
15 | ||
bfab27a1 GC |
16 | #include "stmmac.h" |
17 | ||
0763d955 AS |
18 | /* |
19 | * This struct is used to associate PCI Function of MAC controller on a board, | |
20 | * discovered via DMI, with the address of PHY connected to the MAC. The | |
21 | * negative value of the address means that MAC controller is not connected | |
22 | * with PHY. | |
23 | */ | |
8d78b690 | 24 | struct stmmac_pci_func_data { |
0763d955 AS |
25 | unsigned int func; |
26 | int phy_addr; | |
27 | }; | |
28 | ||
8d78b690 JK |
29 | struct stmmac_pci_dmi_data { |
30 | const struct stmmac_pci_func_data *func; | |
31 | size_t nfuncs; | |
32 | }; | |
33 | ||
5b99a6b6 | 34 | struct stmmac_pci_info { |
7bc519b3 | 35 | int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); |
5b99a6b6 KHL |
36 | }; |
37 | ||
c5d5287e | 38 | static int stmmac_pci_find_phy_addr(struct pci_dev *pdev, |
8d78b690 | 39 | const struct dmi_system_id *dmi_list) |
0763d955 | 40 | { |
8d78b690 JK |
41 | const struct stmmac_pci_func_data *func_data; |
42 | const struct stmmac_pci_dmi_data *dmi_data; | |
43 | const struct dmi_system_id *dmi_id; | |
44 | int func = PCI_FUNC(pdev->devfn); | |
45 | size_t n; | |
46 | ||
47 | dmi_id = dmi_first_match(dmi_list); | |
48 | if (!dmi_id) | |
c5f657e4 | 49 | return -ENODEV; |
0763d955 | 50 | |
8d78b690 JK |
51 | dmi_data = dmi_id->driver_data; |
52 | func_data = dmi_data->func; | |
53 | ||
54 | for (n = 0; n < dmi_data->nfuncs; n++, func_data++) | |
55 | if (func_data->func == func) | |
56 | return func_data->phy_addr; | |
0763d955 AS |
57 | |
58 | return -ENODEV; | |
59 | } | |
60 | ||
70fe4432 | 61 | static void common_default_data(struct plat_stmmacenet_data *plat) |
bfab27a1 | 62 | { |
c4b2b9a8 AS |
63 | plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ |
64 | plat->has_gmac = 1; | |
65 | plat->force_sf_dma_mode = 1; | |
bfab27a1 | 66 | |
1a981c05 | 67 | plat->mdio_bus_data->needs_reset = true; |
0f1f88a8 | 68 | |
1e19e084 | 69 | /* Set default value for multicast hash bins */ |
c4b2b9a8 | 70 | plat->multicast_filter_bins = HASH_TABLE_SIZE; |
1e19e084 AS |
71 | |
72 | /* Set default value for unicast filter entries */ | |
c4b2b9a8 | 73 | plat->unicast_filter_entries = 1; |
a2cd64f3 KHL |
74 | |
75 | /* Set the maxmtu to a default of JUMBO_LEN */ | |
76 | plat->maxmtu = JUMBO_LEN; | |
26d6851f JP |
77 | |
78 | /* Set default number of RX and TX queues to use */ | |
79 | plat->tx_queues_to_use = 1; | |
80 | plat->rx_queues_to_use = 1; | |
a8f5102a JP |
81 | |
82 | /* Disable Priority config by default */ | |
83 | plat->tx_queues_cfg[0].use_prio = false; | |
84 | plat->rx_queues_cfg[0].use_prio = false; | |
abe80fdc JP |
85 | |
86 | /* Disable RX queues routing by default */ | |
87 | plat->rx_queues_cfg[0].pkt_route = 0x0; | |
bfab27a1 GC |
88 | } |
89 | ||
b6a4c8f0 | 90 | static int stmmac_default_data(struct pci_dev *pdev, |
7bc519b3 | 91 | struct plat_stmmacenet_data *plat) |
70fe4432 AS |
92 | { |
93 | /* Set common default data first */ | |
94 | common_default_data(plat); | |
95 | ||
96 | plat->bus_id = 1; | |
97 | plat->phy_addr = 0; | |
909c1dde | 98 | plat->phy_interface = PHY_INTERFACE_MODE_GMII; |
70fe4432 AS |
99 | |
100 | plat->dma_cfg->pbl = 32; | |
101 | plat->dma_cfg->pblx8 = true; | |
102 | /* TODO: AXI */ | |
b6a4c8f0 JK |
103 | |
104 | return 0; | |
70fe4432 AS |
105 | } |
106 | ||
b6a4c8f0 JK |
107 | static const struct stmmac_pci_info stmmac_pci_info = { |
108 | .setup = stmmac_default_data, | |
109 | }; | |
110 | ||
99122836 VW |
111 | static int intel_mgbe_common_data(struct pci_dev *pdev, |
112 | struct plat_stmmacenet_data *plat) | |
113 | { | |
114 | int i; | |
115 | ||
116 | plat->clk_csr = 5; | |
117 | plat->has_gmac = 0; | |
118 | plat->has_gmac4 = 1; | |
119 | plat->force_sf_dma_mode = 0; | |
120 | plat->tso_en = 1; | |
121 | ||
122 | plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP; | |
123 | ||
124 | for (i = 0; i < plat->rx_queues_to_use; i++) { | |
125 | plat->rx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB; | |
126 | plat->rx_queues_cfg[i].chan = i; | |
127 | ||
128 | /* Disable Priority config by default */ | |
129 | plat->rx_queues_cfg[i].use_prio = false; | |
130 | ||
131 | /* Disable RX queues routing by default */ | |
132 | plat->rx_queues_cfg[i].pkt_route = 0x0; | |
133 | } | |
134 | ||
135 | for (i = 0; i < plat->tx_queues_to_use; i++) { | |
136 | plat->tx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB; | |
137 | ||
138 | /* Disable Priority config by default */ | |
139 | plat->tx_queues_cfg[i].use_prio = false; | |
140 | } | |
141 | ||
142 | /* FIFO size is 4096 bytes for 1 tx/rx queue */ | |
143 | plat->tx_fifo_size = plat->tx_queues_to_use * 4096; | |
144 | plat->rx_fifo_size = plat->rx_queues_to_use * 4096; | |
145 | ||
146 | plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WRR; | |
147 | plat->tx_queues_cfg[0].weight = 0x09; | |
148 | plat->tx_queues_cfg[1].weight = 0x0A; | |
149 | plat->tx_queues_cfg[2].weight = 0x0B; | |
150 | plat->tx_queues_cfg[3].weight = 0x0C; | |
151 | plat->tx_queues_cfg[4].weight = 0x0D; | |
152 | plat->tx_queues_cfg[5].weight = 0x0E; | |
153 | plat->tx_queues_cfg[6].weight = 0x0F; | |
154 | plat->tx_queues_cfg[7].weight = 0x10; | |
155 | ||
99122836 VW |
156 | plat->dma_cfg->pbl = 32; |
157 | plat->dma_cfg->pblx8 = true; | |
158 | plat->dma_cfg->fixed_burst = 0; | |
159 | plat->dma_cfg->mixed_burst = 0; | |
160 | plat->dma_cfg->aal = 0; | |
161 | ||
162 | plat->axi = devm_kzalloc(&pdev->dev, sizeof(*plat->axi), | |
163 | GFP_KERNEL); | |
164 | if (!plat->axi) | |
165 | return -ENOMEM; | |
166 | ||
167 | plat->axi->axi_lpi_en = 0; | |
168 | plat->axi->axi_xit_frm = 0; | |
169 | plat->axi->axi_wr_osr_lmt = 1; | |
170 | plat->axi->axi_rd_osr_lmt = 1; | |
171 | plat->axi->axi_blen[0] = 4; | |
172 | plat->axi->axi_blen[1] = 8; | |
173 | plat->axi->axi_blen[2] = 16; | |
174 | ||
190f73ab VW |
175 | plat->ptp_max_adj = plat->clk_ptp_rate; |
176 | ||
177 | /* Set system clock */ | |
178 | plat->stmmac_clk = clk_register_fixed_rate(&pdev->dev, | |
179 | "stmmac-clk", NULL, 0, | |
180 | plat->clk_ptp_rate); | |
181 | ||
182 | if (IS_ERR(plat->stmmac_clk)) { | |
183 | dev_warn(&pdev->dev, "Fail to register stmmac-clk\n"); | |
184 | plat->stmmac_clk = NULL; | |
185 | } | |
186 | clk_prepare_enable(plat->stmmac_clk); | |
187 | ||
99122836 VW |
188 | /* Set default value for multicast hash bins */ |
189 | plat->multicast_filter_bins = HASH_TABLE_SIZE; | |
190 | ||
191 | /* Set default value for unicast filter entries */ | |
192 | plat->unicast_filter_entries = 1; | |
193 | ||
194 | /* Set the maxmtu to a default of JUMBO_LEN */ | |
195 | plat->maxmtu = JUMBO_LEN; | |
196 | ||
197 | return 0; | |
198 | } | |
199 | ||
200 | static int ehl_common_data(struct pci_dev *pdev, | |
201 | struct plat_stmmacenet_data *plat) | |
202 | { | |
203 | int ret; | |
204 | ||
205 | plat->rx_queues_to_use = 8; | |
206 | plat->tx_queues_to_use = 8; | |
190f73ab | 207 | plat->clk_ptp_rate = 200000000; |
99122836 VW |
208 | ret = intel_mgbe_common_data(pdev, plat); |
209 | if (ret) | |
210 | return ret; | |
211 | ||
212 | return 0; | |
213 | } | |
214 | ||
215 | static int ehl_sgmii_data(struct pci_dev *pdev, | |
216 | struct plat_stmmacenet_data *plat) | |
217 | { | |
218 | plat->bus_id = 1; | |
219 | plat->phy_addr = 0; | |
909c1dde VW |
220 | plat->phy_interface = PHY_INTERFACE_MODE_SGMII; |
221 | ||
99122836 VW |
222 | return ehl_common_data(pdev, plat); |
223 | } | |
224 | ||
225 | static struct stmmac_pci_info ehl_sgmii1g_pci_info = { | |
226 | .setup = ehl_sgmii_data, | |
227 | }; | |
228 | ||
f6256585 VW |
229 | static int ehl_rgmii_data(struct pci_dev *pdev, |
230 | struct plat_stmmacenet_data *plat) | |
231 | { | |
232 | plat->bus_id = 1; | |
233 | plat->phy_addr = 0; | |
909c1dde VW |
234 | plat->phy_interface = PHY_INTERFACE_MODE_RGMII; |
235 | ||
f6256585 VW |
236 | return ehl_common_data(pdev, plat); |
237 | } | |
238 | ||
239 | static struct stmmac_pci_info ehl_rgmii1g_pci_info = { | |
240 | .setup = ehl_rgmii_data, | |
241 | }; | |
242 | ||
e125dcef VW |
243 | static int tgl_common_data(struct pci_dev *pdev, |
244 | struct plat_stmmacenet_data *plat) | |
245 | { | |
246 | int ret; | |
247 | ||
248 | plat->rx_queues_to_use = 6; | |
249 | plat->tx_queues_to_use = 4; | |
190f73ab | 250 | plat->clk_ptp_rate = 200000000; |
e125dcef VW |
251 | ret = intel_mgbe_common_data(pdev, plat); |
252 | if (ret) | |
253 | return ret; | |
254 | ||
255 | return 0; | |
256 | } | |
257 | ||
258 | static int tgl_sgmii_data(struct pci_dev *pdev, | |
259 | struct plat_stmmacenet_data *plat) | |
260 | { | |
261 | plat->bus_id = 1; | |
262 | plat->phy_addr = 0; | |
909c1dde | 263 | plat->phy_interface = PHY_INTERFACE_MODE_SGMII; |
e125dcef VW |
264 | return tgl_common_data(pdev, plat); |
265 | } | |
266 | ||
267 | static struct stmmac_pci_info tgl_sgmii1g_pci_info = { | |
268 | .setup = tgl_sgmii_data, | |
269 | }; | |
270 | ||
8d78b690 | 271 | static const struct stmmac_pci_func_data galileo_stmmac_func_data[] = { |
7bc519b3 | 272 | { |
7bc519b3 JK |
273 | .func = 6, |
274 | .phy_addr = 1, | |
275 | }, | |
8d78b690 JK |
276 | }; |
277 | ||
278 | static const struct stmmac_pci_dmi_data galileo_stmmac_dmi_data = { | |
279 | .func = galileo_stmmac_func_data, | |
280 | .nfuncs = ARRAY_SIZE(galileo_stmmac_func_data), | |
281 | }; | |
282 | ||
283 | static const struct stmmac_pci_func_data iot2040_stmmac_func_data[] = { | |
7bc519b3 | 284 | { |
7bc519b3 JK |
285 | .func = 6, |
286 | .phy_addr = 1, | |
287 | }, | |
288 | { | |
8d78b690 | 289 | .func = 7, |
7bc519b3 JK |
290 | .phy_addr = 1, |
291 | }, | |
8d78b690 JK |
292 | }; |
293 | ||
294 | static const struct stmmac_pci_dmi_data iot2040_stmmac_dmi_data = { | |
295 | .func = iot2040_stmmac_func_data, | |
296 | .nfuncs = ARRAY_SIZE(iot2040_stmmac_func_data), | |
297 | }; | |
298 | ||
299 | static const struct dmi_system_id quark_pci_dmi[] = { | |
7bc519b3 | 300 | { |
8d78b690 JK |
301 | .matches = { |
302 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "Galileo"), | |
303 | }, | |
304 | .driver_data = (void *)&galileo_stmmac_dmi_data, | |
7bc519b3 JK |
305 | }, |
306 | { | |
8d78b690 JK |
307 | .matches = { |
308 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"), | |
309 | }, | |
310 | .driver_data = (void *)&galileo_stmmac_dmi_data, | |
311 | }, | |
e0c1d14a | 312 | /* |
37e9c087 | 313 | * There are 2 types of SIMATIC IOT2000: IOT2020 and IOT2040. |
e0c1d14a SBC |
314 | * The asset tag "6ES7647-0AA00-0YA2" is only for IOT2020 which |
315 | * has only one pci network device while other asset tags are | |
316 | * for IOT2040 which has two. | |
317 | */ | |
8d78b690 JK |
318 | { |
319 | .matches = { | |
320 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), | |
321 | DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG, | |
322 | "6ES7647-0AA00-0YA2"), | |
323 | }, | |
324 | .driver_data = (void *)&galileo_stmmac_dmi_data, | |
325 | }, | |
326 | { | |
327 | .matches = { | |
328 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), | |
8d78b690 JK |
329 | }, |
330 | .driver_data = (void *)&iot2040_stmmac_dmi_data, | |
7bc519b3 JK |
331 | }, |
332 | {} | |
333 | }; | |
334 | ||
c5d5287e | 335 | static int quark_default_data(struct pci_dev *pdev, |
7bc519b3 | 336 | struct plat_stmmacenet_data *plat) |
5b99a6b6 | 337 | { |
0763d955 AS |
338 | int ret; |
339 | ||
70fe4432 AS |
340 | /* Set common default data first */ |
341 | common_default_data(plat); | |
342 | ||
0763d955 AS |
343 | /* |
344 | * Refuse to load the driver and register net device if MAC controller | |
345 | * does not connect to any PHY interface. | |
346 | */ | |
8d78b690 | 347 | ret = stmmac_pci_find_phy_addr(pdev, quark_pci_dmi); |
c5f657e4 JK |
348 | if (ret < 0) { |
349 | /* Return error to the caller on DMI enabled boards. */ | |
350 | if (dmi_get_system_info(DMI_BOARD_NAME)) | |
351 | return ret; | |
352 | ||
353 | /* | |
354 | * Galileo boards with old firmware don't support DMI. We always | |
355 | * use 1 here as PHY address, so at least the first found MAC | |
356 | * controller would be probed. | |
357 | */ | |
358 | ret = 1; | |
359 | } | |
5b99a6b6 | 360 | |
d4a62ea4 | 361 | plat->bus_id = pci_dev_id(pdev); |
0763d955 | 362 | plat->phy_addr = ret; |
909c1dde | 363 | plat->phy_interface = PHY_INTERFACE_MODE_RMII; |
5b99a6b6 KHL |
364 | |
365 | plat->dma_cfg->pbl = 16; | |
4022d039 | 366 | plat->dma_cfg->pblx8 = true; |
5b99a6b6 | 367 | plat->dma_cfg->fixed_burst = 1; |
afea0365 | 368 | /* AXI (TODO) */ |
5b99a6b6 | 369 | |
5b99a6b6 KHL |
370 | return 0; |
371 | } | |
372 | ||
c5d5287e | 373 | static const struct stmmac_pci_info quark_pci_info = { |
5b99a6b6 KHL |
374 | .setup = quark_default_data, |
375 | }; | |
376 | ||
ebecb860 JA |
377 | static int snps_gmac5_default_data(struct pci_dev *pdev, |
378 | struct plat_stmmacenet_data *plat) | |
379 | { | |
380 | int i; | |
381 | ||
382 | plat->clk_csr = 5; | |
383 | plat->has_gmac4 = 1; | |
384 | plat->force_sf_dma_mode = 1; | |
385 | plat->tso_en = 1; | |
386 | plat->pmt = 1; | |
387 | ||
ebecb860 JA |
388 | /* Set default value for multicast hash bins */ |
389 | plat->multicast_filter_bins = HASH_TABLE_SIZE; | |
390 | ||
391 | /* Set default value for unicast filter entries */ | |
392 | plat->unicast_filter_entries = 1; | |
393 | ||
394 | /* Set the maxmtu to a default of JUMBO_LEN */ | |
395 | plat->maxmtu = JUMBO_LEN; | |
396 | ||
397 | /* Set default number of RX and TX queues to use */ | |
398 | plat->tx_queues_to_use = 4; | |
399 | plat->rx_queues_to_use = 4; | |
400 | ||
401 | plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WRR; | |
402 | for (i = 0; i < plat->tx_queues_to_use; i++) { | |
403 | plat->tx_queues_cfg[i].use_prio = false; | |
404 | plat->tx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB; | |
405 | plat->tx_queues_cfg[i].weight = 25; | |
7eadf572 JA |
406 | if (i > 0) |
407 | plat->tx_queues_cfg[i].tbs_en = 1; | |
ebecb860 JA |
408 | } |
409 | ||
410 | plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP; | |
411 | for (i = 0; i < plat->rx_queues_to_use; i++) { | |
412 | plat->rx_queues_cfg[i].use_prio = false; | |
413 | plat->rx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB; | |
414 | plat->rx_queues_cfg[i].pkt_route = 0x0; | |
415 | plat->rx_queues_cfg[i].chan = i; | |
416 | } | |
417 | ||
418 | plat->bus_id = 1; | |
419 | plat->phy_addr = -1; | |
909c1dde | 420 | plat->phy_interface = PHY_INTERFACE_MODE_GMII; |
ebecb860 JA |
421 | |
422 | plat->dma_cfg->pbl = 32; | |
423 | plat->dma_cfg->pblx8 = true; | |
424 | ||
425 | /* Axi Configuration */ | |
426 | plat->axi = devm_kzalloc(&pdev->dev, sizeof(*plat->axi), GFP_KERNEL); | |
427 | if (!plat->axi) | |
428 | return -ENOMEM; | |
429 | ||
430 | plat->axi->axi_wr_osr_lmt = 31; | |
431 | plat->axi->axi_rd_osr_lmt = 31; | |
432 | ||
433 | plat->axi->axi_fb = false; | |
434 | plat->axi->axi_blen[0] = 4; | |
435 | plat->axi->axi_blen[1] = 8; | |
436 | plat->axi->axi_blen[2] = 16; | |
437 | plat->axi->axi_blen[3] = 32; | |
438 | ||
439 | return 0; | |
440 | } | |
441 | ||
442 | static const struct stmmac_pci_info snps_gmac5_pci_info = { | |
443 | .setup = snps_gmac5_default_data, | |
444 | }; | |
445 | ||
bfab27a1 GC |
446 | /** |
447 | * stmmac_pci_probe | |
448 | * | |
449 | * @pdev: pci device pointer | |
450 | * @id: pointer to table of device id/id's. | |
451 | * | |
452 | * Description: This probing function gets called for all PCI devices which | |
453 | * match the ID table and are not "owned" by other driver yet. This function | |
454 | * gets passed a "struct pci_dev *" for each device whose entry in the ID table | |
455 | * matches the device. The probe functions returns zero when the driver choose | |
456 | * to take "ownership" of the device or an error code(-ve no) otherwise. | |
457 | */ | |
979857bb | 458 | static int stmmac_pci_probe(struct pci_dev *pdev, |
1dd06ae8 | 459 | const struct pci_device_id *id) |
bfab27a1 | 460 | { |
5b99a6b6 | 461 | struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data; |
c4b2b9a8 | 462 | struct plat_stmmacenet_data *plat; |
e56788cf | 463 | struct stmmac_resources res; |
bfab27a1 | 464 | int i; |
2a3e8e93 | 465 | int ret; |
bfab27a1 | 466 | |
c4b2b9a8 AS |
467 | plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); |
468 | if (!plat) | |
469 | return -ENOMEM; | |
470 | ||
471 | plat->mdio_bus_data = devm_kzalloc(&pdev->dev, | |
472 | sizeof(*plat->mdio_bus_data), | |
473 | GFP_KERNEL); | |
474 | if (!plat->mdio_bus_data) | |
475 | return -ENOMEM; | |
476 | ||
477 | plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), | |
478 | GFP_KERNEL); | |
479 | if (!plat->dma_cfg) | |
480 | return -ENOMEM; | |
481 | ||
bfab27a1 | 482 | /* Enable pci device */ |
b7d0f08e | 483 | ret = pci_enable_device(pdev); |
bfab27a1 | 484 | if (ret) { |
7627fc07 AS |
485 | dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n", |
486 | __func__); | |
bfab27a1 GC |
487 | return ret; |
488 | } | |
bfab27a1 GC |
489 | |
490 | /* Get the base address of device */ | |
c9c13ba4 | 491 | for (i = 0; i < PCI_STD_NUM_BARS; i++) { |
bfab27a1 GC |
492 | if (pci_resource_len(pdev, i) == 0) |
493 | continue; | |
2a3e8e93 AS |
494 | ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev)); |
495 | if (ret) | |
496 | return ret; | |
bfab27a1 GC |
497 | break; |
498 | } | |
2a3e8e93 | 499 | |
bfab27a1 GC |
500 | pci_set_master(pdev); |
501 | ||
7bc519b3 | 502 | ret = info->setup(pdev, plat); |
b6a4c8f0 JK |
503 | if (ret) |
504 | return ret; | |
bfab27a1 | 505 | |
d2a029bd KHL |
506 | pci_enable_msi(pdev); |
507 | ||
e56788cf JE |
508 | memset(&res, 0, sizeof(res)); |
509 | res.addr = pcim_iomap_table(pdev)[i]; | |
510 | res.wol_irq = pdev->irq; | |
511 | res.irq = pdev->irq; | |
512 | ||
15ffac73 | 513 | return stmmac_dvr_probe(&pdev->dev, plat, &res); |
bfab27a1 GC |
514 | } |
515 | ||
516 | /** | |
49ce9c2c | 517 | * stmmac_pci_remove |
bfab27a1 GC |
518 | * |
519 | * @pdev: platform device pointer | |
520 | * Description: this function calls the main to free the net resources | |
521 | * and releases the PCI resources. | |
522 | */ | |
979857bb | 523 | static void stmmac_pci_remove(struct pci_dev *pdev) |
bfab27a1 | 524 | { |
190f73ab VW |
525 | struct net_device *ndev = dev_get_drvdata(&pdev->dev); |
526 | struct stmmac_priv *priv = netdev_priv(ndev); | |
6dea7e18 JA |
527 | int i; |
528 | ||
f4e7bd81 | 529 | stmmac_dvr_remove(&pdev->dev); |
6dea7e18 | 530 | |
190f73ab VW |
531 | if (priv->plat->stmmac_clk) |
532 | clk_unregister_fixed_rate(priv->plat->stmmac_clk); | |
533 | ||
c9c13ba4 | 534 | for (i = 0; i < PCI_STD_NUM_BARS; i++) { |
6dea7e18 JA |
535 | if (pci_resource_len(pdev, i) == 0) |
536 | continue; | |
537 | pcim_iounmap_regions(pdev, BIT(i)); | |
538 | break; | |
539 | } | |
540 | ||
b7d0f08e | 541 | pci_disable_device(pdev); |
bfab27a1 | 542 | } |
bfab27a1 | 543 | |
81a8b079 | 544 | static int __maybe_unused stmmac_pci_suspend(struct device *dev) |
b7d0f08e JA |
545 | { |
546 | struct pci_dev *pdev = to_pci_dev(dev); | |
547 | int ret; | |
548 | ||
549 | ret = stmmac_suspend(dev); | |
550 | if (ret) | |
551 | return ret; | |
552 | ||
553 | ret = pci_save_state(pdev); | |
554 | if (ret) | |
555 | return ret; | |
556 | ||
557 | pci_disable_device(pdev); | |
558 | pci_wake_from_d3(pdev, true); | |
559 | return 0; | |
560 | } | |
561 | ||
81a8b079 | 562 | static int __maybe_unused stmmac_pci_resume(struct device *dev) |
b7d0f08e JA |
563 | { |
564 | struct pci_dev *pdev = to_pci_dev(dev); | |
565 | int ret; | |
566 | ||
567 | pci_restore_state(pdev); | |
568 | pci_set_power_state(pdev, PCI_D0); | |
569 | ||
570 | ret = pci_enable_device(pdev); | |
571 | if (ret) | |
572 | return ret; | |
573 | ||
574 | pci_set_master(pdev); | |
575 | ||
576 | return stmmac_resume(dev); | |
577 | } | |
578 | ||
579 | static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume); | |
3be3d81b | 580 | |
b6a4c8f0 JK |
581 | /* synthetic ID, no official vendor */ |
582 | #define PCI_VENDOR_ID_STMMAC 0x700 | |
583 | ||
5b99a6b6 | 584 | #define STMMAC_QUARK_ID 0x0937 |
bfab27a1 | 585 | #define STMMAC_DEVICE_ID 0x1108 |
f6256585 | 586 | #define STMMAC_EHL_RGMII1G_ID 0x4b30 |
99122836 | 587 | #define STMMAC_EHL_SGMII1G_ID 0x4b31 |
e125dcef | 588 | #define STMMAC_TGL_SGMII1G_ID 0xa0ac |
ebecb860 | 589 | #define STMMAC_GMAC5_ID 0x7102 |
bfab27a1 | 590 | |
b6a4c8f0 JK |
591 | #define STMMAC_DEVICE(vendor_id, dev_id, info) { \ |
592 | PCI_VDEVICE(vendor_id, dev_id), \ | |
593 | .driver_data = (kernel_ulong_t)&info \ | |
594 | } | |
595 | ||
9baa3c34 | 596 | static const struct pci_device_id stmmac_id_table[] = { |
b6a4c8f0 JK |
597 | STMMAC_DEVICE(STMMAC, STMMAC_DEVICE_ID, stmmac_pci_info), |
598 | STMMAC_DEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_MAC, stmmac_pci_info), | |
599 | STMMAC_DEVICE(INTEL, STMMAC_QUARK_ID, quark_pci_info), | |
f6256585 | 600 | STMMAC_DEVICE(INTEL, STMMAC_EHL_RGMII1G_ID, ehl_rgmii1g_pci_info), |
99122836 | 601 | STMMAC_DEVICE(INTEL, STMMAC_EHL_SGMII1G_ID, ehl_sgmii1g_pci_info), |
e125dcef | 602 | STMMAC_DEVICE(INTEL, STMMAC_TGL_SGMII1G_ID, tgl_sgmii1g_pci_info), |
ebecb860 | 603 | STMMAC_DEVICE(SYNOPSYS, STMMAC_GMAC5_ID, snps_gmac5_pci_info), |
5437f4b2 | 604 | {} |
bfab27a1 GC |
605 | }; |
606 | ||
607 | MODULE_DEVICE_TABLE(pci, stmmac_id_table); | |
608 | ||
b2e2f0c7 | 609 | static struct pci_driver stmmac_pci_driver = { |
bfab27a1 GC |
610 | .name = STMMAC_RESOURCE_NAME, |
611 | .id_table = stmmac_id_table, | |
612 | .probe = stmmac_pci_probe, | |
979857bb | 613 | .remove = stmmac_pci_remove, |
3be3d81b AS |
614 | .driver = { |
615 | .pm = &stmmac_pm_ops, | |
616 | }, | |
bfab27a1 GC |
617 | }; |
618 | ||
b2e2f0c7 AS |
619 | module_pci_driver(stmmac_pci_driver); |
620 | ||
bfab27a1 GC |
621 | MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver"); |
622 | MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>"); | |
623 | MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); | |
624 | MODULE_LICENSE("GPL"); |