]>
Commit | Line | Data |
---|---|---|
c6eec6f3 AT |
1 | /* |
2 | * dwmac-stm32.c - DWMAC Specific Glue layer for STM32 MCU | |
3 | * | |
f6454f80 BG |
4 | * Copyright (C) STMicroelectronics SA 2017 |
5 | * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics. | |
c6eec6f3 AT |
6 | * License terms: GNU General Public License (GPL), version 2 |
7 | * | |
8 | */ | |
9 | ||
10 | #include <linux/clk.h> | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/mfd/syscon.h> | |
13 | #include <linux/module.h> | |
14 | #include <linux/of.h> | |
15 | #include <linux/of_device.h> | |
16 | #include <linux/of_net.h> | |
17 | #include <linux/phy.h> | |
18 | #include <linux/platform_device.h> | |
6528e02c | 19 | #include <linux/pm_wakeirq.h> |
c6eec6f3 AT |
20 | #include <linux/regmap.h> |
21 | #include <linux/slab.h> | |
22 | #include <linux/stmmac.h> | |
23 | ||
24 | #include "stmmac_platform.h" | |
25 | ||
6528e02c CR |
26 | #define SYSCFG_MCU_ETH_MASK BIT(23) |
27 | #define SYSCFG_MP1_ETH_MASK GENMASK(23, 16) | |
22947335 | 28 | #define SYSCFG_PMCCLRR_OFFSET 0x40 |
6528e02c CR |
29 | |
30 | #define SYSCFG_PMCR_ETH_CLK_SEL BIT(16) | |
31 | #define SYSCFG_PMCR_ETH_REF_CLK_SEL BIT(17) | |
22947335 CR |
32 | |
33 | /* Ethernet PHY interface selection in register SYSCFG Configuration | |
34 | *------------------------------------------ | |
35 | * src |BIT(23)| BIT(22)| BIT(21)|BIT(20)| | |
36 | *------------------------------------------ | |
37 | * MII | 0 | 0 | 0 | 1 | | |
38 | *------------------------------------------ | |
39 | * GMII | 0 | 0 | 0 | 0 | | |
40 | *------------------------------------------ | |
41 | * RGMII | 0 | 0 | 1 | n/a | | |
42 | *------------------------------------------ | |
43 | * RMII | 1 | 0 | 0 | n/a | | |
44 | *------------------------------------------ | |
45 | */ | |
6528e02c CR |
46 | #define SYSCFG_PMCR_ETH_SEL_MII BIT(20) |
47 | #define SYSCFG_PMCR_ETH_SEL_RGMII BIT(21) | |
48 | #define SYSCFG_PMCR_ETH_SEL_RMII BIT(23) | |
49 | #define SYSCFG_PMCR_ETH_SEL_GMII 0 | |
50 | #define SYSCFG_MCU_ETH_SEL_MII 0 | |
51 | #define SYSCFG_MCU_ETH_SEL_RMII 1 | |
c6eec6f3 | 52 | |
22947335 CR |
53 | /* STM32MP1 register definitions |
54 | * | |
55 | * Below table summarizes the clock requirement and clock sources for | |
56 | * supported phy interface modes. | |
57 | * __________________________________________________________________________ | |
58 | *|PHY_MODE | Normal | PHY wo crystal| PHY wo crystal |No 125Mhz from PHY| | |
59 | *| | | 25MHz | 50MHz | | | |
60 | * --------------------------------------------------------------------------- | |
61 | *| MII | - | eth-ck | n/a | n/a | | |
62 | *| | | | | | | |
63 | * --------------------------------------------------------------------------- | |
64 | *| GMII | - | eth-ck | n/a | n/a | | |
65 | *| | | | | | | |
66 | * --------------------------------------------------------------------------- | |
67 | *| RGMII | - | eth-ck | n/a | eth-ck (no pin) | | |
68 | *| | | | | st,eth-clk-sel | | |
69 | * --------------------------------------------------------------------------- | |
70 | *| RMII | - | eth-ck | eth-ck | n/a | | |
71 | *| | | | st,eth-ref-clk-sel | | | |
72 | * --------------------------------------------------------------------------- | |
73 | * | |
74 | * BIT(17) : set this bit in RMII mode when you have PHY without crystal 50MHz | |
75 | * BIT(16) : set this bit in GMII/RGMII PHY when you do not want use 125Mhz | |
76 | * from PHY | |
77 | *----------------------------------------------------- | |
78 | * src | BIT(17) | BIT(16) | | |
79 | *----------------------------------------------------- | |
80 | * MII | n/a | n/a | | |
81 | *----------------------------------------------------- | |
82 | * GMII | n/a | st,eth-clk-sel | | |
83 | *----------------------------------------------------- | |
84 | * RGMII | n/a | st,eth-clk-sel | | |
85 | *----------------------------------------------------- | |
86 | * RMII | st,eth-ref-clk-sel | n/a | | |
87 | *----------------------------------------------------- | |
88 | * | |
89 | */ | |
90 | ||
c6eec6f3 AT |
91 | struct stm32_dwmac { |
92 | struct clk *clk_tx; | |
93 | struct clk *clk_rx; | |
6528e02c CR |
94 | struct clk *clk_eth_ck; |
95 | struct clk *clk_ethstp; | |
96 | struct clk *syscfg_clk; | |
22947335 CR |
97 | int eth_clk_sel_reg; |
98 | int eth_ref_clk_sel_reg; | |
634565f8 | 99 | int irq_pwr_wakeup; |
22947335 | 100 | u32 mode_reg; /* MAC glue-logic mode register */ |
c6eec6f3 AT |
101 | struct regmap *regmap; |
102 | u32 speed; | |
6528e02c CR |
103 | const struct stm32_ops *ops; |
104 | struct device *dev; | |
105 | }; | |
106 | ||
107 | struct stm32_ops { | |
108 | int (*set_mode)(struct plat_stmmacenet_data *plat_dat); | |
109 | int (*clk_prepare)(struct stm32_dwmac *dwmac, bool prepare); | |
110 | int (*suspend)(struct stm32_dwmac *dwmac); | |
111 | void (*resume)(struct stm32_dwmac *dwmac); | |
112 | int (*parse_data)(struct stm32_dwmac *dwmac, | |
113 | struct device *dev); | |
114 | u32 syscfg_eth_mask; | |
c6eec6f3 AT |
115 | }; |
116 | ||
117 | static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) | |
118 | { | |
119 | struct stm32_dwmac *dwmac = plat_dat->bsp_priv; | |
c6eec6f3 AT |
120 | int ret; |
121 | ||
6528e02c CR |
122 | if (dwmac->ops->set_mode) { |
123 | ret = dwmac->ops->set_mode(plat_dat); | |
124 | if (ret) | |
125 | return ret; | |
126 | } | |
c6eec6f3 AT |
127 | |
128 | ret = clk_prepare_enable(dwmac->clk_tx); | |
129 | if (ret) | |
130 | return ret; | |
131 | ||
6528e02c CR |
132 | if (!dwmac->dev->power.is_suspended) { |
133 | ret = clk_prepare_enable(dwmac->clk_rx); | |
134 | if (ret) { | |
135 | clk_disable_unprepare(dwmac->clk_tx); | |
136 | return ret; | |
137 | } | |
138 | } | |
139 | ||
140 | if (dwmac->ops->clk_prepare) { | |
141 | ret = dwmac->ops->clk_prepare(dwmac, true); | |
142 | if (ret) { | |
143 | clk_disable_unprepare(dwmac->clk_rx); | |
144 | clk_disable_unprepare(dwmac->clk_tx); | |
145 | } | |
146 | } | |
c6eec6f3 AT |
147 | |
148 | return ret; | |
149 | } | |
150 | ||
6528e02c CR |
151 | static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare) |
152 | { | |
153 | int ret = 0; | |
154 | ||
155 | if (prepare) { | |
156 | ret = clk_prepare_enable(dwmac->syscfg_clk); | |
157 | if (ret) | |
158 | return ret; | |
159 | ||
22947335 | 160 | if (dwmac->clk_eth_ck) { |
6528e02c CR |
161 | ret = clk_prepare_enable(dwmac->clk_eth_ck); |
162 | if (ret) { | |
163 | clk_disable_unprepare(dwmac->syscfg_clk); | |
164 | return ret; | |
165 | } | |
166 | } | |
167 | } else { | |
168 | clk_disable_unprepare(dwmac->syscfg_clk); | |
22947335 | 169 | if (dwmac->clk_eth_ck) |
6528e02c CR |
170 | clk_disable_unprepare(dwmac->clk_eth_ck); |
171 | } | |
172 | return ret; | |
173 | } | |
174 | ||
175 | static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) | |
176 | { | |
177 | struct stm32_dwmac *dwmac = plat_dat->bsp_priv; | |
178 | u32 reg = dwmac->mode_reg; | |
22947335 | 179 | int val, ret; |
6528e02c CR |
180 | |
181 | switch (plat_dat->interface) { | |
182 | case PHY_INTERFACE_MODE_MII: | |
183 | val = SYSCFG_PMCR_ETH_SEL_MII; | |
184 | pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n"); | |
185 | break; | |
186 | case PHY_INTERFACE_MODE_GMII: | |
187 | val = SYSCFG_PMCR_ETH_SEL_GMII; | |
22947335 | 188 | if (dwmac->eth_clk_sel_reg) |
6528e02c CR |
189 | val |= SYSCFG_PMCR_ETH_CLK_SEL; |
190 | pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n"); | |
191 | break; | |
192 | case PHY_INTERFACE_MODE_RMII: | |
193 | val = SYSCFG_PMCR_ETH_SEL_RMII; | |
22947335 | 194 | if (dwmac->eth_ref_clk_sel_reg) |
6528e02c CR |
195 | val |= SYSCFG_PMCR_ETH_REF_CLK_SEL; |
196 | pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n"); | |
197 | break; | |
198 | case PHY_INTERFACE_MODE_RGMII: | |
22947335 CR |
199 | case PHY_INTERFACE_MODE_RGMII_ID: |
200 | case PHY_INTERFACE_MODE_RGMII_RXID: | |
201 | case PHY_INTERFACE_MODE_RGMII_TXID: | |
6528e02c | 202 | val = SYSCFG_PMCR_ETH_SEL_RGMII; |
22947335 | 203 | if (dwmac->eth_clk_sel_reg) |
6528e02c CR |
204 | val |= SYSCFG_PMCR_ETH_CLK_SEL; |
205 | pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n"); | |
206 | break; | |
207 | default: | |
208 | pr_debug("SYSCFG init : Do not manage %d interface\n", | |
209 | plat_dat->interface); | |
210 | /* Do not manage others interfaces */ | |
211 | return -EINVAL; | |
212 | } | |
213 | ||
22947335 CR |
214 | /* Need to update PMCCLRR (clear register) */ |
215 | ret = regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET, | |
216 | dwmac->ops->syscfg_eth_mask); | |
217 | ||
218 | /* Update PMCSETR (set register) */ | |
6528e02c CR |
219 | return regmap_update_bits(dwmac->regmap, reg, |
220 | dwmac->ops->syscfg_eth_mask, val); | |
221 | } | |
222 | ||
223 | static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) | |
224 | { | |
225 | struct stm32_dwmac *dwmac = plat_dat->bsp_priv; | |
226 | u32 reg = dwmac->mode_reg; | |
227 | int val; | |
228 | ||
229 | switch (plat_dat->interface) { | |
230 | case PHY_INTERFACE_MODE_MII: | |
231 | val = SYSCFG_MCU_ETH_SEL_MII; | |
232 | pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n"); | |
233 | break; | |
234 | case PHY_INTERFACE_MODE_RMII: | |
235 | val = SYSCFG_MCU_ETH_SEL_RMII; | |
236 | pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n"); | |
237 | break; | |
238 | default: | |
239 | pr_debug("SYSCFG init : Do not manage %d interface\n", | |
240 | plat_dat->interface); | |
241 | /* Do not manage others interfaces */ | |
242 | return -EINVAL; | |
243 | } | |
244 | ||
245 | return regmap_update_bits(dwmac->regmap, reg, | |
22947335 | 246 | dwmac->ops->syscfg_eth_mask, val << 23); |
6528e02c CR |
247 | } |
248 | ||
c6eec6f3 AT |
249 | static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac) |
250 | { | |
251 | clk_disable_unprepare(dwmac->clk_tx); | |
252 | clk_disable_unprepare(dwmac->clk_rx); | |
6528e02c CR |
253 | |
254 | if (dwmac->ops->clk_prepare) | |
255 | dwmac->ops->clk_prepare(dwmac, false); | |
c6eec6f3 AT |
256 | } |
257 | ||
258 | static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac, | |
259 | struct device *dev) | |
260 | { | |
261 | struct device_node *np = dev->of_node; | |
262 | int err; | |
263 | ||
264 | /* Get TX/RX clocks */ | |
265 | dwmac->clk_tx = devm_clk_get(dev, "mac-clk-tx"); | |
266 | if (IS_ERR(dwmac->clk_tx)) { | |
6528e02c | 267 | dev_err(dev, "No ETH Tx clock provided...\n"); |
c6eec6f3 AT |
268 | return PTR_ERR(dwmac->clk_tx); |
269 | } | |
6528e02c | 270 | |
c6eec6f3 AT |
271 | dwmac->clk_rx = devm_clk_get(dev, "mac-clk-rx"); |
272 | if (IS_ERR(dwmac->clk_rx)) { | |
6528e02c | 273 | dev_err(dev, "No ETH Rx clock provided...\n"); |
c6eec6f3 AT |
274 | return PTR_ERR(dwmac->clk_rx); |
275 | } | |
276 | ||
6528e02c CR |
277 | if (dwmac->ops->parse_data) { |
278 | err = dwmac->ops->parse_data(dwmac, dev); | |
279 | if (err) | |
280 | return err; | |
281 | } | |
282 | ||
c6eec6f3 AT |
283 | /* Get mode register */ |
284 | dwmac->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon"); | |
285 | if (IS_ERR(dwmac->regmap)) | |
286 | return PTR_ERR(dwmac->regmap); | |
287 | ||
288 | err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->mode_reg); | |
289 | if (err) | |
290 | dev_err(dev, "Can't get sysconfig mode offset (%d)\n", err); | |
291 | ||
292 | return err; | |
293 | } | |
294 | ||
6528e02c CR |
295 | static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, |
296 | struct device *dev) | |
297 | { | |
634565f8 | 298 | struct platform_device *pdev = to_platform_device(dev); |
6528e02c | 299 | struct device_node *np = dev->of_node; |
634565f8 | 300 | int err = 0; |
6528e02c | 301 | |
22947335 CR |
302 | /* Gigabit Ethernet 125MHz clock selection. */ |
303 | dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel"); | |
6528e02c | 304 | |
22947335 CR |
305 | /* Ethernet 50Mhz RMII clock selection */ |
306 | dwmac->eth_ref_clk_sel_reg = | |
307 | of_property_read_bool(np, "st,eth-ref-clk-sel"); | |
308 | ||
309 | /* Get ETH_CLK clocks */ | |
310 | dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck"); | |
311 | if (IS_ERR(dwmac->clk_eth_ck)) { | |
312 | dev_warn(dev, "No phy clock provided...\n"); | |
313 | dwmac->clk_eth_ck = NULL; | |
6528e02c CR |
314 | } |
315 | ||
316 | /* Clock used for low power mode */ | |
317 | dwmac->clk_ethstp = devm_clk_get(dev, "ethstp"); | |
318 | if (IS_ERR(dwmac->clk_ethstp)) { | |
22947335 CR |
319 | dev_err(dev, |
320 | "No ETH peripheral clock provided for CStop mode ...\n"); | |
6528e02c CR |
321 | return PTR_ERR(dwmac->clk_ethstp); |
322 | } | |
323 | ||
324 | /* Clock for sysconfig */ | |
325 | dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk"); | |
326 | if (IS_ERR(dwmac->syscfg_clk)) { | |
327 | dev_err(dev, "No syscfg clock provided...\n"); | |
328 | return PTR_ERR(dwmac->syscfg_clk); | |
329 | } | |
330 | ||
634565f8 CR |
331 | /* Get IRQ information early to have an ability to ask for deferred |
332 | * probe if needed before we went too far with resource allocation. | |
333 | */ | |
334 | dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev, | |
335 | "stm32_pwr_wakeup"); | |
22947335 | 336 | if (!dwmac->clk_eth_ck && dwmac->irq_pwr_wakeup >= 0) { |
634565f8 CR |
337 | err = device_init_wakeup(&pdev->dev, true); |
338 | if (err) { | |
339 | dev_err(&pdev->dev, "Failed to init wake up irq\n"); | |
340 | return err; | |
341 | } | |
342 | err = dev_pm_set_dedicated_wake_irq(&pdev->dev, | |
343 | dwmac->irq_pwr_wakeup); | |
344 | if (err) { | |
345 | dev_err(&pdev->dev, "Failed to set wake up irq\n"); | |
346 | device_init_wakeup(&pdev->dev, false); | |
347 | } | |
348 | device_set_wakeup_enable(&pdev->dev, false); | |
349 | } | |
350 | return err; | |
6528e02c CR |
351 | } |
352 | ||
c6eec6f3 AT |
353 | static int stm32_dwmac_probe(struct platform_device *pdev) |
354 | { | |
355 | struct plat_stmmacenet_data *plat_dat; | |
356 | struct stmmac_resources stmmac_res; | |
357 | struct stm32_dwmac *dwmac; | |
6528e02c | 358 | const struct stm32_ops *data; |
c6eec6f3 AT |
359 | int ret; |
360 | ||
361 | ret = stmmac_get_platform_resources(pdev, &stmmac_res); | |
362 | if (ret) | |
363 | return ret; | |
364 | ||
365 | plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); | |
366 | if (IS_ERR(plat_dat)) | |
367 | return PTR_ERR(plat_dat); | |
368 | ||
369 | dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); | |
d2ed0a77 JH |
370 | if (!dwmac) { |
371 | ret = -ENOMEM; | |
372 | goto err_remove_config_dt; | |
373 | } | |
c6eec6f3 | 374 | |
6528e02c CR |
375 | data = of_device_get_match_data(&pdev->dev); |
376 | if (!data) { | |
377 | dev_err(&pdev->dev, "no of match data provided\n"); | |
378 | ret = -EINVAL; | |
379 | goto err_remove_config_dt; | |
380 | } | |
381 | ||
382 | dwmac->ops = data; | |
383 | dwmac->dev = &pdev->dev; | |
384 | ||
c6eec6f3 AT |
385 | ret = stm32_dwmac_parse_data(dwmac, &pdev->dev); |
386 | if (ret) { | |
387 | dev_err(&pdev->dev, "Unable to parse OF data\n"); | |
d2ed0a77 | 388 | goto err_remove_config_dt; |
c6eec6f3 AT |
389 | } |
390 | ||
391 | plat_dat->bsp_priv = dwmac; | |
392 | ||
393 | ret = stm32_dwmac_init(plat_dat); | |
394 | if (ret) | |
d2ed0a77 | 395 | goto err_remove_config_dt; |
c6eec6f3 AT |
396 | |
397 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | |
398 | if (ret) | |
d2ed0a77 JH |
399 | goto err_clk_disable; |
400 | ||
401 | return 0; | |
402 | ||
403 | err_clk_disable: | |
404 | stm32_dwmac_clk_disable(dwmac); | |
405 | err_remove_config_dt: | |
406 | stmmac_remove_config_dt(pdev, plat_dat); | |
c6eec6f3 AT |
407 | |
408 | return ret; | |
409 | } | |
410 | ||
411 | static int stm32_dwmac_remove(struct platform_device *pdev) | |
412 | { | |
413 | struct net_device *ndev = platform_get_drvdata(pdev); | |
414 | struct stmmac_priv *priv = netdev_priv(ndev); | |
415 | int ret = stmmac_dvr_remove(&pdev->dev); | |
634565f8 | 416 | struct stm32_dwmac *dwmac = priv->plat->bsp_priv; |
c6eec6f3 AT |
417 | |
418 | stm32_dwmac_clk_disable(priv->plat->bsp_priv); | |
419 | ||
634565f8 CR |
420 | if (dwmac->irq_pwr_wakeup >= 0) { |
421 | dev_pm_clear_wake_irq(&pdev->dev); | |
422 | device_init_wakeup(&pdev->dev, false); | |
423 | } | |
424 | ||
c6eec6f3 AT |
425 | return ret; |
426 | } | |
427 | ||
6528e02c CR |
428 | static int stm32mp1_suspend(struct stm32_dwmac *dwmac) |
429 | { | |
430 | int ret = 0; | |
431 | ||
432 | ret = clk_prepare_enable(dwmac->clk_ethstp); | |
433 | if (ret) | |
434 | return ret; | |
435 | ||
436 | clk_disable_unprepare(dwmac->clk_tx); | |
437 | clk_disable_unprepare(dwmac->syscfg_clk); | |
22947335 | 438 | if (dwmac->clk_eth_ck) |
6528e02c CR |
439 | clk_disable_unprepare(dwmac->clk_eth_ck); |
440 | ||
441 | return ret; | |
442 | } | |
443 | ||
444 | static void stm32mp1_resume(struct stm32_dwmac *dwmac) | |
445 | { | |
446 | clk_disable_unprepare(dwmac->clk_ethstp); | |
447 | } | |
448 | ||
449 | static int stm32mcu_suspend(struct stm32_dwmac *dwmac) | |
450 | { | |
451 | clk_disable_unprepare(dwmac->clk_tx); | |
452 | clk_disable_unprepare(dwmac->clk_rx); | |
453 | ||
454 | return 0; | |
455 | } | |
456 | ||
c6eec6f3 AT |
457 | #ifdef CONFIG_PM_SLEEP |
458 | static int stm32_dwmac_suspend(struct device *dev) | |
459 | { | |
460 | struct net_device *ndev = dev_get_drvdata(dev); | |
461 | struct stmmac_priv *priv = netdev_priv(ndev); | |
6528e02c CR |
462 | struct stm32_dwmac *dwmac = priv->plat->bsp_priv; |
463 | ||
c6eec6f3 AT |
464 | int ret; |
465 | ||
466 | ret = stmmac_suspend(dev); | |
6528e02c CR |
467 | |
468 | if (dwmac->ops->suspend) | |
469 | ret = dwmac->ops->suspend(dwmac); | |
c6eec6f3 AT |
470 | |
471 | return ret; | |
472 | } | |
473 | ||
474 | static int stm32_dwmac_resume(struct device *dev) | |
475 | { | |
476 | struct net_device *ndev = dev_get_drvdata(dev); | |
477 | struct stmmac_priv *priv = netdev_priv(ndev); | |
6528e02c | 478 | struct stm32_dwmac *dwmac = priv->plat->bsp_priv; |
c6eec6f3 AT |
479 | int ret; |
480 | ||
6528e02c CR |
481 | if (dwmac->ops->resume) |
482 | dwmac->ops->resume(dwmac); | |
483 | ||
c6eec6f3 AT |
484 | ret = stm32_dwmac_init(priv->plat); |
485 | if (ret) | |
486 | return ret; | |
487 | ||
488 | ret = stmmac_resume(dev); | |
489 | ||
490 | return ret; | |
491 | } | |
492 | #endif /* CONFIG_PM_SLEEP */ | |
493 | ||
a5f54fcc WY |
494 | static SIMPLE_DEV_PM_OPS(stm32_dwmac_pm_ops, |
495 | stm32_dwmac_suspend, stm32_dwmac_resume); | |
c6eec6f3 | 496 | |
6528e02c CR |
497 | static struct stm32_ops stm32mcu_dwmac_data = { |
498 | .set_mode = stm32mcu_set_mode, | |
499 | .suspend = stm32mcu_suspend, | |
500 | .syscfg_eth_mask = SYSCFG_MCU_ETH_MASK | |
501 | }; | |
502 | ||
503 | static struct stm32_ops stm32mp1_dwmac_data = { | |
504 | .set_mode = stm32mp1_set_mode, | |
505 | .clk_prepare = stm32mp1_clk_prepare, | |
506 | .suspend = stm32mp1_suspend, | |
507 | .resume = stm32mp1_resume, | |
508 | .parse_data = stm32mp1_parse_data, | |
509 | .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK | |
510 | }; | |
511 | ||
c6eec6f3 | 512 | static const struct of_device_id stm32_dwmac_match[] = { |
6528e02c CR |
513 | { .compatible = "st,stm32-dwmac", .data = &stm32mcu_dwmac_data}, |
514 | { .compatible = "st,stm32mp1-dwmac", .data = &stm32mp1_dwmac_data}, | |
c6eec6f3 AT |
515 | { } |
516 | }; | |
517 | MODULE_DEVICE_TABLE(of, stm32_dwmac_match); | |
518 | ||
519 | static struct platform_driver stm32_dwmac_driver = { | |
520 | .probe = stm32_dwmac_probe, | |
521 | .remove = stm32_dwmac_remove, | |
522 | .driver = { | |
523 | .name = "stm32-dwmac", | |
524 | .pm = &stm32_dwmac_pm_ops, | |
525 | .of_match_table = stm32_dwmac_match, | |
526 | }, | |
527 | }; | |
528 | module_platform_driver(stm32_dwmac_driver); | |
529 | ||
530 | MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@gmail.com>"); | |
6528e02c CR |
531 | MODULE_AUTHOR("Christophe Roullier <christophe.roullier@st.com>"); |
532 | MODULE_DESCRIPTION("STMicroelectronics STM32 DWMAC Specific Glue layer"); | |
c6eec6f3 | 533 | MODULE_LICENSE("GPL v2"); |