xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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