1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
6*4882a593Smuzhiyun * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
7*4882a593Smuzhiyun * Contributors: Giuseppe Cavallaro <peppe.cavallaro@st.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/platform_device.h>
13*4882a593Smuzhiyun #include <linux/stmmac.h>
14*4882a593Smuzhiyun #include <linux/phy.h>
15*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
16*4882a593Smuzhiyun #include <linux/module.h>
17*4882a593Smuzhiyun #include <linux/regmap.h>
18*4882a593Smuzhiyun #include <linux/clk.h>
19*4882a593Smuzhiyun #include <linux/of.h>
20*4882a593Smuzhiyun #include <linux/of_device.h>
21*4882a593Smuzhiyun #include <linux/of_net.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include "stmmac_platform.h"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #define DWMAC_125MHZ 125000000
26*4882a593Smuzhiyun #define DWMAC_50MHZ 50000000
27*4882a593Smuzhiyun #define DWMAC_25MHZ 25000000
28*4882a593Smuzhiyun #define DWMAC_2_5MHZ 2500000
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #define IS_PHY_IF_MODE_RGMII(iface) (iface == PHY_INTERFACE_MODE_RGMII || \
31*4882a593Smuzhiyun iface == PHY_INTERFACE_MODE_RGMII_ID || \
32*4882a593Smuzhiyun iface == PHY_INTERFACE_MODE_RGMII_RXID || \
33*4882a593Smuzhiyun iface == PHY_INTERFACE_MODE_RGMII_TXID)
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define IS_PHY_IF_MODE_GBIT(iface) (IS_PHY_IF_MODE_RGMII(iface) || \
36*4882a593Smuzhiyun iface == PHY_INTERFACE_MODE_GMII)
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun /* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families)
39*4882a593Smuzhiyun *
40*4882a593Smuzhiyun * Below table summarizes the clock requirement and clock sources for
41*4882a593Smuzhiyun * supported phy interface modes with link speeds.
42*4882a593Smuzhiyun * ________________________________________________
43*4882a593Smuzhiyun *| PHY_MODE | 1000 Mbit Link | 100 Mbit Link |
44*4882a593Smuzhiyun * ------------------------------------------------
45*4882a593Smuzhiyun *| MII | n/a | 25Mhz |
46*4882a593Smuzhiyun *| | | txclk |
47*4882a593Smuzhiyun * ------------------------------------------------
48*4882a593Smuzhiyun *| GMII | 125Mhz | 25Mhz |
49*4882a593Smuzhiyun *| | clk-125/txclk | txclk |
50*4882a593Smuzhiyun * ------------------------------------------------
51*4882a593Smuzhiyun *| RGMII | 125Mhz | 25Mhz |
52*4882a593Smuzhiyun *| | clk-125/txclk | clkgen |
53*4882a593Smuzhiyun *| | clkgen | |
54*4882a593Smuzhiyun * ------------------------------------------------
55*4882a593Smuzhiyun *| RMII | n/a | 25Mhz |
56*4882a593Smuzhiyun *| | |clkgen/phyclk-in |
57*4882a593Smuzhiyun * ------------------------------------------------
58*4882a593Smuzhiyun *
59*4882a593Smuzhiyun * Register Configuration
60*4882a593Smuzhiyun *-------------------------------
61*4882a593Smuzhiyun * src |BIT(8)| BIT(7)| BIT(6)|
62*4882a593Smuzhiyun *-------------------------------
63*4882a593Smuzhiyun * txclk | 0 | n/a | 1 |
64*4882a593Smuzhiyun *-------------------------------
65*4882a593Smuzhiyun * ck_125| 0 | n/a | 0 |
66*4882a593Smuzhiyun *-------------------------------
67*4882a593Smuzhiyun * phyclk| 1 | 0 | n/a |
68*4882a593Smuzhiyun *-------------------------------
69*4882a593Smuzhiyun * clkgen| 1 | 1 | n/a |
70*4882a593Smuzhiyun *-------------------------------
71*4882a593Smuzhiyun */
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun #define STIH4XX_RETIME_SRC_MASK GENMASK(8, 6)
74*4882a593Smuzhiyun #define STIH4XX_ETH_SEL_TX_RETIME_CLK BIT(8)
75*4882a593Smuzhiyun #define STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7)
76*4882a593Smuzhiyun #define STIH4XX_ETH_SEL_TXCLK_NOT_CLK125 BIT(6)
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /* STiD127 register definitions
79*4882a593Smuzhiyun *-----------------------
80*4882a593Smuzhiyun * src |BIT(6)| BIT(7)|
81*4882a593Smuzhiyun *-----------------------
82*4882a593Smuzhiyun * MII | 1 | n/a |
83*4882a593Smuzhiyun *-----------------------
84*4882a593Smuzhiyun * RMII | n/a | 1 |
85*4882a593Smuzhiyun * clkgen| | |
86*4882a593Smuzhiyun *-----------------------
87*4882a593Smuzhiyun * RMII | n/a | 0 |
88*4882a593Smuzhiyun * phyclk| | |
89*4882a593Smuzhiyun *-----------------------
90*4882a593Smuzhiyun * RGMII | 1 | n/a |
91*4882a593Smuzhiyun * clkgen| | |
92*4882a593Smuzhiyun *-----------------------
93*4882a593Smuzhiyun */
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun #define STID127_RETIME_SRC_MASK GENMASK(7, 6)
96*4882a593Smuzhiyun #define STID127_ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7)
97*4882a593Smuzhiyun #define STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK BIT(6)
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun #define ENMII_MASK GENMASK(5, 5)
100*4882a593Smuzhiyun #define ENMII BIT(5)
101*4882a593Smuzhiyun #define EN_MASK GENMASK(1, 1)
102*4882a593Smuzhiyun #define EN BIT(1)
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /*
105*4882a593Smuzhiyun * 3 bits [4:2]
106*4882a593Smuzhiyun * 000-GMII/MII
107*4882a593Smuzhiyun * 001-RGMII
108*4882a593Smuzhiyun * 010-SGMII
109*4882a593Smuzhiyun * 100-RMII
110*4882a593Smuzhiyun */
111*4882a593Smuzhiyun #define MII_PHY_SEL_MASK GENMASK(4, 2)
112*4882a593Smuzhiyun #define ETH_PHY_SEL_RMII BIT(4)
113*4882a593Smuzhiyun #define ETH_PHY_SEL_SGMII BIT(3)
114*4882a593Smuzhiyun #define ETH_PHY_SEL_RGMII BIT(2)
115*4882a593Smuzhiyun #define ETH_PHY_SEL_GMII 0x0
116*4882a593Smuzhiyun #define ETH_PHY_SEL_MII 0x0
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun struct sti_dwmac {
119*4882a593Smuzhiyun phy_interface_t interface; /* MII interface */
120*4882a593Smuzhiyun bool ext_phyclk; /* Clock from external PHY */
121*4882a593Smuzhiyun u32 tx_retime_src; /* TXCLK Retiming*/
122*4882a593Smuzhiyun struct clk *clk; /* PHY clock */
123*4882a593Smuzhiyun u32 ctrl_reg; /* GMAC glue-logic control register */
124*4882a593Smuzhiyun int clk_sel_reg; /* GMAC ext clk selection register */
125*4882a593Smuzhiyun struct regmap *regmap;
126*4882a593Smuzhiyun bool gmac_en;
127*4882a593Smuzhiyun u32 speed;
128*4882a593Smuzhiyun void (*fix_retime_src)(void *priv, unsigned int speed);
129*4882a593Smuzhiyun };
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun struct sti_dwmac_of_data {
132*4882a593Smuzhiyun void (*fix_retime_src)(void *priv, unsigned int speed);
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun static u32 phy_intf_sels[] = {
136*4882a593Smuzhiyun [PHY_INTERFACE_MODE_MII] = ETH_PHY_SEL_MII,
137*4882a593Smuzhiyun [PHY_INTERFACE_MODE_GMII] = ETH_PHY_SEL_GMII,
138*4882a593Smuzhiyun [PHY_INTERFACE_MODE_RGMII] = ETH_PHY_SEL_RGMII,
139*4882a593Smuzhiyun [PHY_INTERFACE_MODE_RGMII_ID] = ETH_PHY_SEL_RGMII,
140*4882a593Smuzhiyun [PHY_INTERFACE_MODE_SGMII] = ETH_PHY_SEL_SGMII,
141*4882a593Smuzhiyun [PHY_INTERFACE_MODE_RMII] = ETH_PHY_SEL_RMII,
142*4882a593Smuzhiyun };
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun enum {
145*4882a593Smuzhiyun TX_RETIME_SRC_NA = 0,
146*4882a593Smuzhiyun TX_RETIME_SRC_TXCLK = 1,
147*4882a593Smuzhiyun TX_RETIME_SRC_CLK_125,
148*4882a593Smuzhiyun TX_RETIME_SRC_PHYCLK,
149*4882a593Smuzhiyun TX_RETIME_SRC_CLKGEN,
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun static u32 stih4xx_tx_retime_val[] = {
153*4882a593Smuzhiyun [TX_RETIME_SRC_TXCLK] = STIH4XX_ETH_SEL_TXCLK_NOT_CLK125,
154*4882a593Smuzhiyun [TX_RETIME_SRC_CLK_125] = 0x0,
155*4882a593Smuzhiyun [TX_RETIME_SRC_PHYCLK] = STIH4XX_ETH_SEL_TX_RETIME_CLK,
156*4882a593Smuzhiyun [TX_RETIME_SRC_CLKGEN] = STIH4XX_ETH_SEL_TX_RETIME_CLK
157*4882a593Smuzhiyun | STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
158*4882a593Smuzhiyun };
159*4882a593Smuzhiyun
stih4xx_fix_retime_src(void * priv,u32 spd)160*4882a593Smuzhiyun static void stih4xx_fix_retime_src(void *priv, u32 spd)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun struct sti_dwmac *dwmac = priv;
163*4882a593Smuzhiyun u32 src = dwmac->tx_retime_src;
164*4882a593Smuzhiyun u32 reg = dwmac->ctrl_reg;
165*4882a593Smuzhiyun u32 freq = 0;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
168*4882a593Smuzhiyun src = TX_RETIME_SRC_TXCLK;
169*4882a593Smuzhiyun } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
170*4882a593Smuzhiyun if (dwmac->ext_phyclk) {
171*4882a593Smuzhiyun src = TX_RETIME_SRC_PHYCLK;
172*4882a593Smuzhiyun } else {
173*4882a593Smuzhiyun src = TX_RETIME_SRC_CLKGEN;
174*4882a593Smuzhiyun freq = DWMAC_50MHZ;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
177*4882a593Smuzhiyun /* On GiGa clk source can be either ext or from clkgen */
178*4882a593Smuzhiyun if (spd == SPEED_1000) {
179*4882a593Smuzhiyun freq = DWMAC_125MHZ;
180*4882a593Smuzhiyun } else {
181*4882a593Smuzhiyun /* Switch to clkgen for these speeds */
182*4882a593Smuzhiyun src = TX_RETIME_SRC_CLKGEN;
183*4882a593Smuzhiyun if (spd == SPEED_100)
184*4882a593Smuzhiyun freq = DWMAC_25MHZ;
185*4882a593Smuzhiyun else if (spd == SPEED_10)
186*4882a593Smuzhiyun freq = DWMAC_2_5MHZ;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun if (src == TX_RETIME_SRC_CLKGEN && freq)
191*4882a593Smuzhiyun clk_set_rate(dwmac->clk, freq);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun regmap_update_bits(dwmac->regmap, reg, STIH4XX_RETIME_SRC_MASK,
194*4882a593Smuzhiyun stih4xx_tx_retime_val[src]);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
stid127_fix_retime_src(void * priv,u32 spd)197*4882a593Smuzhiyun static void stid127_fix_retime_src(void *priv, u32 spd)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun struct sti_dwmac *dwmac = priv;
200*4882a593Smuzhiyun u32 reg = dwmac->ctrl_reg;
201*4882a593Smuzhiyun u32 freq = 0;
202*4882a593Smuzhiyun u32 val = 0;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
205*4882a593Smuzhiyun val = STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK;
206*4882a593Smuzhiyun } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
207*4882a593Smuzhiyun if (!dwmac->ext_phyclk) {
208*4882a593Smuzhiyun val = STID127_ETH_SEL_INTERNAL_NOTEXT_PHYCLK;
209*4882a593Smuzhiyun freq = DWMAC_50MHZ;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
212*4882a593Smuzhiyun val = STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK;
213*4882a593Smuzhiyun if (spd == SPEED_1000)
214*4882a593Smuzhiyun freq = DWMAC_125MHZ;
215*4882a593Smuzhiyun else if (spd == SPEED_100)
216*4882a593Smuzhiyun freq = DWMAC_25MHZ;
217*4882a593Smuzhiyun else if (spd == SPEED_10)
218*4882a593Smuzhiyun freq = DWMAC_2_5MHZ;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun if (freq)
222*4882a593Smuzhiyun clk_set_rate(dwmac->clk, freq);
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
sti_dwmac_set_mode(struct sti_dwmac * dwmac)227*4882a593Smuzhiyun static int sti_dwmac_set_mode(struct sti_dwmac *dwmac)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun struct regmap *regmap = dwmac->regmap;
230*4882a593Smuzhiyun int iface = dwmac->interface;
231*4882a593Smuzhiyun u32 reg = dwmac->ctrl_reg;
232*4882a593Smuzhiyun u32 val;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun if (dwmac->gmac_en)
235*4882a593Smuzhiyun regmap_update_bits(regmap, reg, EN_MASK, EN);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
240*4882a593Smuzhiyun regmap_update_bits(regmap, reg, ENMII_MASK, val);
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun dwmac->fix_retime_src(dwmac, dwmac->speed);
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun return 0;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
sti_dwmac_parse_data(struct sti_dwmac * dwmac,struct platform_device * pdev)247*4882a593Smuzhiyun static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
248*4882a593Smuzhiyun struct platform_device *pdev)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun struct resource *res;
251*4882a593Smuzhiyun struct device *dev = &pdev->dev;
252*4882a593Smuzhiyun struct device_node *np = dev->of_node;
253*4882a593Smuzhiyun struct regmap *regmap;
254*4882a593Smuzhiyun int err;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /* clk selection from extra syscfg register */
257*4882a593Smuzhiyun dwmac->clk_sel_reg = -ENXIO;
258*4882a593Smuzhiyun res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-clkconf");
259*4882a593Smuzhiyun if (res)
260*4882a593Smuzhiyun dwmac->clk_sel_reg = res->start;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
263*4882a593Smuzhiyun if (IS_ERR(regmap))
264*4882a593Smuzhiyun return PTR_ERR(regmap);
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->ctrl_reg);
267*4882a593Smuzhiyun if (err) {
268*4882a593Smuzhiyun dev_err(dev, "Can't get sysconfig ctrl offset (%d)\n", err);
269*4882a593Smuzhiyun return err;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun err = of_get_phy_mode(np, &dwmac->interface);
273*4882a593Smuzhiyun if (err && err != -ENODEV) {
274*4882a593Smuzhiyun dev_err(dev, "Can't get phy-mode\n");
275*4882a593Smuzhiyun return err;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun dwmac->regmap = regmap;
279*4882a593Smuzhiyun dwmac->gmac_en = of_property_read_bool(np, "st,gmac_en");
280*4882a593Smuzhiyun dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
281*4882a593Smuzhiyun dwmac->tx_retime_src = TX_RETIME_SRC_NA;
282*4882a593Smuzhiyun dwmac->speed = SPEED_100;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
285*4882a593Smuzhiyun const char *rs;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun dwmac->tx_retime_src = TX_RETIME_SRC_CLKGEN;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun err = of_property_read_string(np, "st,tx-retime-src", &rs);
290*4882a593Smuzhiyun if (err < 0) {
291*4882a593Smuzhiyun dev_warn(dev, "Use internal clock source\n");
292*4882a593Smuzhiyun } else {
293*4882a593Smuzhiyun if (!strcasecmp(rs, "clk_125"))
294*4882a593Smuzhiyun dwmac->tx_retime_src = TX_RETIME_SRC_CLK_125;
295*4882a593Smuzhiyun else if (!strcasecmp(rs, "txclk"))
296*4882a593Smuzhiyun dwmac->tx_retime_src = TX_RETIME_SRC_TXCLK;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun dwmac->speed = SPEED_1000;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun dwmac->clk = devm_clk_get(dev, "sti-ethclk");
302*4882a593Smuzhiyun if (IS_ERR(dwmac->clk)) {
303*4882a593Smuzhiyun dev_warn(dev, "No phy clock provided...\n");
304*4882a593Smuzhiyun dwmac->clk = NULL;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun return 0;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
sti_dwmac_probe(struct platform_device * pdev)310*4882a593Smuzhiyun static int sti_dwmac_probe(struct platform_device *pdev)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun struct plat_stmmacenet_data *plat_dat;
313*4882a593Smuzhiyun const struct sti_dwmac_of_data *data;
314*4882a593Smuzhiyun struct stmmac_resources stmmac_res;
315*4882a593Smuzhiyun struct sti_dwmac *dwmac;
316*4882a593Smuzhiyun int ret;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun data = of_device_get_match_data(&pdev->dev);
319*4882a593Smuzhiyun if (!data) {
320*4882a593Smuzhiyun dev_err(&pdev->dev, "No OF match data provided\n");
321*4882a593Smuzhiyun return -EINVAL;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun ret = stmmac_get_platform_resources(pdev, &stmmac_res);
325*4882a593Smuzhiyun if (ret)
326*4882a593Smuzhiyun return ret;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
329*4882a593Smuzhiyun if (IS_ERR(plat_dat))
330*4882a593Smuzhiyun return PTR_ERR(plat_dat);
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
333*4882a593Smuzhiyun if (!dwmac) {
334*4882a593Smuzhiyun ret = -ENOMEM;
335*4882a593Smuzhiyun goto err_remove_config_dt;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun ret = sti_dwmac_parse_data(dwmac, pdev);
339*4882a593Smuzhiyun if (ret) {
340*4882a593Smuzhiyun dev_err(&pdev->dev, "Unable to parse OF data\n");
341*4882a593Smuzhiyun goto err_remove_config_dt;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun dwmac->fix_retime_src = data->fix_retime_src;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun plat_dat->bsp_priv = dwmac;
347*4882a593Smuzhiyun plat_dat->fix_mac_speed = data->fix_retime_src;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun ret = clk_prepare_enable(dwmac->clk);
350*4882a593Smuzhiyun if (ret)
351*4882a593Smuzhiyun goto err_remove_config_dt;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun ret = sti_dwmac_set_mode(dwmac);
354*4882a593Smuzhiyun if (ret)
355*4882a593Smuzhiyun goto disable_clk;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
358*4882a593Smuzhiyun if (ret)
359*4882a593Smuzhiyun goto disable_clk;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun return 0;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun disable_clk:
364*4882a593Smuzhiyun clk_disable_unprepare(dwmac->clk);
365*4882a593Smuzhiyun err_remove_config_dt:
366*4882a593Smuzhiyun stmmac_remove_config_dt(pdev, plat_dat);
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun return ret;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
sti_dwmac_remove(struct platform_device * pdev)371*4882a593Smuzhiyun static int sti_dwmac_remove(struct platform_device *pdev)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun struct sti_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
374*4882a593Smuzhiyun int ret = stmmac_dvr_remove(&pdev->dev);
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun clk_disable_unprepare(dwmac->clk);
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun return ret;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
sti_dwmac_suspend(struct device * dev)382*4882a593Smuzhiyun static int sti_dwmac_suspend(struct device *dev)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev);
385*4882a593Smuzhiyun int ret = stmmac_suspend(dev);
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun clk_disable_unprepare(dwmac->clk);
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun return ret;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
sti_dwmac_resume(struct device * dev)392*4882a593Smuzhiyun static int sti_dwmac_resume(struct device *dev)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun clk_prepare_enable(dwmac->clk);
397*4882a593Smuzhiyun sti_dwmac_set_mode(dwmac);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun return stmmac_resume(dev);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun #endif /* CONFIG_PM_SLEEP */
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(sti_dwmac_pm_ops, sti_dwmac_suspend,
404*4882a593Smuzhiyun sti_dwmac_resume);
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun static const struct sti_dwmac_of_data stih4xx_dwmac_data = {
407*4882a593Smuzhiyun .fix_retime_src = stih4xx_fix_retime_src,
408*4882a593Smuzhiyun };
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun static const struct sti_dwmac_of_data stid127_dwmac_data = {
411*4882a593Smuzhiyun .fix_retime_src = stid127_fix_retime_src,
412*4882a593Smuzhiyun };
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun static const struct of_device_id sti_dwmac_match[] = {
415*4882a593Smuzhiyun { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data},
416*4882a593Smuzhiyun { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data},
417*4882a593Smuzhiyun { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
418*4882a593Smuzhiyun { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
419*4882a593Smuzhiyun { }
420*4882a593Smuzhiyun };
421*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, sti_dwmac_match);
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun static struct platform_driver sti_dwmac_driver = {
424*4882a593Smuzhiyun .probe = sti_dwmac_probe,
425*4882a593Smuzhiyun .remove = sti_dwmac_remove,
426*4882a593Smuzhiyun .driver = {
427*4882a593Smuzhiyun .name = "sti-dwmac",
428*4882a593Smuzhiyun .pm = &sti_dwmac_pm_ops,
429*4882a593Smuzhiyun .of_match_table = sti_dwmac_match,
430*4882a593Smuzhiyun },
431*4882a593Smuzhiyun };
432*4882a593Smuzhiyun module_platform_driver(sti_dwmac_driver);
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@st.com>");
435*4882a593Smuzhiyun MODULE_DESCRIPTION("STMicroelectronics DWMAC Specific Glue layer");
436*4882a593Smuzhiyun MODULE_LICENSE("GPL");
437