xref: /freebsd/sys/dev/dwc/if_dwc_rk.c (revision cf037a17c7c81e8a2e73c89eb90877f2625749d7)
1432ae724SEmmanuel Vadot /*-
2432ae724SEmmanuel Vadot  * SPDX-License-Identifier: BSD-2-Clause
3432ae724SEmmanuel Vadot  *
4432ae724SEmmanuel Vadot  * Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
5432ae724SEmmanuel Vadot  *
6432ae724SEmmanuel Vadot  * Redistribution and use in source and binary forms, with or without
7432ae724SEmmanuel Vadot  * modification, are permitted provided that the following conditions
8432ae724SEmmanuel Vadot  * are met:
9432ae724SEmmanuel Vadot  * 1. Redistributions of source code must retain the above copyright
10432ae724SEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer.
11432ae724SEmmanuel Vadot  * 2. Redistributions in binary form must reproduce the above copyright
12432ae724SEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer in the
13432ae724SEmmanuel Vadot  *    documentation and/or other materials provided with the distribution.
14432ae724SEmmanuel Vadot  *
15432ae724SEmmanuel Vadot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16432ae724SEmmanuel Vadot  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17432ae724SEmmanuel Vadot  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18432ae724SEmmanuel Vadot  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19432ae724SEmmanuel Vadot  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20432ae724SEmmanuel Vadot  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21432ae724SEmmanuel Vadot  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22432ae724SEmmanuel Vadot  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23432ae724SEmmanuel Vadot  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24432ae724SEmmanuel Vadot  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25432ae724SEmmanuel Vadot  * SUCH DAMAGE.
26432ae724SEmmanuel Vadot */
27432ae724SEmmanuel Vadot 
28432ae724SEmmanuel Vadot #include <sys/cdefs.h>
29432ae724SEmmanuel Vadot #include <sys/param.h>
30432ae724SEmmanuel Vadot #include <sys/systm.h>
31432ae724SEmmanuel Vadot #include <sys/bus.h>
32432ae724SEmmanuel Vadot #include <sys/kernel.h>
33432ae724SEmmanuel Vadot #include <sys/module.h>
34432ae724SEmmanuel Vadot #include <sys/socket.h>
35432ae724SEmmanuel Vadot 
36432ae724SEmmanuel Vadot #include <machine/bus.h>
37432ae724SEmmanuel Vadot 
38432ae724SEmmanuel Vadot #include <net/if.h>
39432ae724SEmmanuel Vadot #include <net/if_media.h>
40432ae724SEmmanuel Vadot 
41801fb66aSEmmanuel Vadot #include <dev/mii/miivar.h>
42801fb66aSEmmanuel Vadot 
43c36125f6SEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
44c36125f6SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
45c36125f6SEmmanuel Vadot 
46432ae724SEmmanuel Vadot #include <dev/extres/clk/clk.h>
47432ae724SEmmanuel Vadot #include <dev/extres/hwreset/hwreset.h>
48432ae724SEmmanuel Vadot #include <dev/extres/regulator/regulator.h>
49432ae724SEmmanuel Vadot #include <dev/extres/syscon/syscon.h>
50432ae724SEmmanuel Vadot 
5150059a60SEmmanuel Vadot #include <dev/dwc/if_dwcvar.h>
52c36125f6SEmmanuel Vadot #include <dev/dwc/dwc1000_reg.h>
5350059a60SEmmanuel Vadot 
54432ae724SEmmanuel Vadot #include "if_dwc_if.h"
55432ae724SEmmanuel Vadot #include "syscon_if.h"
56432ae724SEmmanuel Vadot 
57432ae724SEmmanuel Vadot #define	RK3328_GRF_MAC_CON0		0x0900
58432ae724SEmmanuel Vadot #define	 MAC_CON0_GMAC2IO_TX_DL_CFG_MASK	0x7F
59432ae724SEmmanuel Vadot #define	 MAC_CON0_GMAC2IO_TX_DL_CFG_SHIFT	0
60432ae724SEmmanuel Vadot #define	 MAC_CON0_GMAC2IO_RX_DL_CFG_MASK	0x7F
61432ae724SEmmanuel Vadot #define	 MAC_CON0_GMAC2IO_RX_DL_CFG_SHIFT	7
62432ae724SEmmanuel Vadot 
63432ae724SEmmanuel Vadot #define	RK3328_GRF_MAC_CON1		0x0904
64432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_GMAC_TXCLK_DLY_ENA	(1 << 0)
65432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_GMAC_RXCLK_DLY_ENA	(1 << 1)
66432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_GMII_CLK_SEL_MASK	(3 << 11)
67432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_GMII_CLK_SEL_125	(0 << 11)
68432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_GMII_CLK_SEL_25	(3 << 11)
69432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_GMII_CLK_SEL_2_5	(2 << 11)
70432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_RMII_MODE_MASK	(1 << 9)
71432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_RMII_MODE		(1 << 9)
72432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_INTF_SEL_MASK		(7 << 4)
73432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_INTF_RMII		(4 << 4)
74432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_INTF_RGMII		(1 << 4)
75432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_RMII_CLK_SEL_MASK	(1 << 7)
76432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_RMII_CLK_SEL_25	(1 << 7)
77432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_RMII_CLK_SEL_2_5	(0 << 7)
78432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_MAC_SPEED_MASK	(1 << 2)
79432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_MAC_SPEED_100		(1 << 2)
80432ae724SEmmanuel Vadot #define	 MAC_CON1_GMAC2IO_MAC_SPEED_10		(0 << 2)
81432ae724SEmmanuel Vadot #define	RK3328_GRF_MAC_CON2		0x0908
82432ae724SEmmanuel Vadot #define	RK3328_GRF_MACPHY_CON0		0x0B00
83432ae724SEmmanuel Vadot #define	 MACPHY_CON0_CLK_50M_MASK		(1 << 14)
84432ae724SEmmanuel Vadot #define	 MACPHY_CON0_CLK_50M			(1 << 14)
85432ae724SEmmanuel Vadot #define	 MACPHY_CON0_RMII_MODE_MASK		(3 << 6)
86432ae724SEmmanuel Vadot #define	 MACPHY_CON0_RMII_MODE			(1 << 6)
87432ae724SEmmanuel Vadot #define	RK3328_GRF_MACPHY_CON1		0x0B04
88432ae724SEmmanuel Vadot #define	 MACPHY_CON1_RMII_MODE_MASK		(1 << 9)
89432ae724SEmmanuel Vadot #define	 MACPHY_CON1_RMII_MODE			(1 << 9)
90432ae724SEmmanuel Vadot #define	RK3328_GRF_MACPHY_CON2		0x0B08
91432ae724SEmmanuel Vadot #define	RK3328_GRF_MACPHY_CON3		0x0B0C
92432ae724SEmmanuel Vadot #define	RK3328_GRF_MACPHY_STATUS	0x0B10
93432ae724SEmmanuel Vadot 
94432ae724SEmmanuel Vadot #define	RK3399_GRF_SOC_CON5		0xc214
95432ae724SEmmanuel Vadot #define	 SOC_CON5_GMAC_CLK_SEL_MASK		(3 << 4)
96432ae724SEmmanuel Vadot #define	 SOC_CON5_GMAC_CLK_SEL_125		(0 << 4)
97432ae724SEmmanuel Vadot #define	 SOC_CON5_GMAC_CLK_SEL_25		(3 << 4)
98432ae724SEmmanuel Vadot #define	 SOC_CON5_GMAC_CLK_SEL_2_5		(2 << 4)
99432ae724SEmmanuel Vadot #define	RK3399_GRF_SOC_CON6		0xc218
100432ae724SEmmanuel Vadot #define	 SOC_CON6_GMAC_TXCLK_DLY_ENA		(1 << 7)
101432ae724SEmmanuel Vadot #define	 SOC_CON6_TX_DL_CFG_MASK		0x7F
102432ae724SEmmanuel Vadot #define	 SOC_CON6_TX_DL_CFG_SHIFT		0
103432ae724SEmmanuel Vadot #define	 SOC_CON6_RX_DL_CFG_MASK		0x7F
104432ae724SEmmanuel Vadot #define	 SOC_CON6_GMAC_RXCLK_DLY_ENA		(1 << 15)
105432ae724SEmmanuel Vadot #define	 SOC_CON6_RX_DL_CFG_SHIFT		8
106432ae724SEmmanuel Vadot 
107432ae724SEmmanuel Vadot struct if_dwc_rk_softc;
108432ae724SEmmanuel Vadot 
109432ae724SEmmanuel Vadot typedef void (*if_dwc_rk_set_delaysfn_t)(struct if_dwc_rk_softc *);
110432ae724SEmmanuel Vadot typedef int (*if_dwc_rk_set_speedfn_t)(struct if_dwc_rk_softc *, int);
111432ae724SEmmanuel Vadot typedef void (*if_dwc_rk_set_phy_modefn_t)(struct if_dwc_rk_softc *);
112432ae724SEmmanuel Vadot typedef void (*if_dwc_rk_phy_powerupfn_t)(struct if_dwc_rk_softc *);
113432ae724SEmmanuel Vadot 
114432ae724SEmmanuel Vadot struct if_dwc_rk_ops {
115432ae724SEmmanuel Vadot 	if_dwc_rk_set_delaysfn_t	set_delays;
116432ae724SEmmanuel Vadot 	if_dwc_rk_set_speedfn_t		set_speed;
117432ae724SEmmanuel Vadot 	if_dwc_rk_set_phy_modefn_t	set_phy_mode;
118432ae724SEmmanuel Vadot 	if_dwc_rk_phy_powerupfn_t	phy_powerup;
119432ae724SEmmanuel Vadot };
120432ae724SEmmanuel Vadot 
121432ae724SEmmanuel Vadot struct if_dwc_rk_softc {
122432ae724SEmmanuel Vadot 	struct dwc_softc	base;
123432ae724SEmmanuel Vadot 	uint32_t		tx_delay;
124432ae724SEmmanuel Vadot 	uint32_t		rx_delay;
125432ae724SEmmanuel Vadot 	bool			integrated_phy;
126432ae724SEmmanuel Vadot 	bool			clock_in;
127432ae724SEmmanuel Vadot 	phandle_t		phy_node;
128432ae724SEmmanuel Vadot 	struct syscon		*grf;
129432ae724SEmmanuel Vadot 	struct if_dwc_rk_ops	*ops;
130432ae724SEmmanuel Vadot 	/* Common clocks */
131432ae724SEmmanuel Vadot 	clk_t			mac_clk_rx;
132432ae724SEmmanuel Vadot 	clk_t			mac_clk_tx;
133432ae724SEmmanuel Vadot 	clk_t			aclk_mac;
134432ae724SEmmanuel Vadot 	clk_t			pclk_mac;
135432ae724SEmmanuel Vadot 	clk_t			clk_stmmaceth;
13650059a60SEmmanuel Vadot 	clk_t			clk_mac_speed;
137432ae724SEmmanuel Vadot 	/* RMII clocks */
138432ae724SEmmanuel Vadot 	clk_t			clk_mac_ref;
139432ae724SEmmanuel Vadot 	clk_t			clk_mac_refout;
140432ae724SEmmanuel Vadot 	/* PHY clock */
141432ae724SEmmanuel Vadot 	clk_t			clk_phy;
142432ae724SEmmanuel Vadot };
143432ae724SEmmanuel Vadot 
144432ae724SEmmanuel Vadot static void rk3328_set_delays(struct if_dwc_rk_softc *sc);
145432ae724SEmmanuel Vadot static int rk3328_set_speed(struct if_dwc_rk_softc *sc, int speed);
146432ae724SEmmanuel Vadot static void rk3328_set_phy_mode(struct if_dwc_rk_softc *sc);
147432ae724SEmmanuel Vadot static void rk3328_phy_powerup(struct if_dwc_rk_softc *sc);
148432ae724SEmmanuel Vadot 
149432ae724SEmmanuel Vadot static void rk3399_set_delays(struct if_dwc_rk_softc *sc);
150432ae724SEmmanuel Vadot static int rk3399_set_speed(struct if_dwc_rk_softc *sc, int speed);
151432ae724SEmmanuel Vadot 
152432ae724SEmmanuel Vadot static struct if_dwc_rk_ops rk3288_ops = {
153432ae724SEmmanuel Vadot };
154432ae724SEmmanuel Vadot 
155432ae724SEmmanuel Vadot static struct if_dwc_rk_ops rk3328_ops = {
156432ae724SEmmanuel Vadot 	.set_delays = rk3328_set_delays,
157432ae724SEmmanuel Vadot 	.set_speed = rk3328_set_speed,
158432ae724SEmmanuel Vadot 	.set_phy_mode = rk3328_set_phy_mode,
159432ae724SEmmanuel Vadot 	.phy_powerup = rk3328_phy_powerup,
160432ae724SEmmanuel Vadot };
161432ae724SEmmanuel Vadot 
162432ae724SEmmanuel Vadot static struct if_dwc_rk_ops rk3399_ops = {
163432ae724SEmmanuel Vadot 	.set_delays = rk3399_set_delays,
164432ae724SEmmanuel Vadot 	.set_speed = rk3399_set_speed,
165432ae724SEmmanuel Vadot };
166432ae724SEmmanuel Vadot 
167432ae724SEmmanuel Vadot static struct ofw_compat_data compat_data[] = {
168432ae724SEmmanuel Vadot 	{"rockchip,rk3288-gmac", (uintptr_t)&rk3288_ops},
169432ae724SEmmanuel Vadot 	{"rockchip,rk3328-gmac", (uintptr_t)&rk3328_ops},
170432ae724SEmmanuel Vadot 	{"rockchip,rk3399-gmac", (uintptr_t)&rk3399_ops},
171432ae724SEmmanuel Vadot 	{NULL,			 0}
172432ae724SEmmanuel Vadot };
173432ae724SEmmanuel Vadot 
174432ae724SEmmanuel Vadot static void
175432ae724SEmmanuel Vadot rk3328_set_delays(struct if_dwc_rk_softc *sc)
176432ae724SEmmanuel Vadot {
177432ae724SEmmanuel Vadot 	uint32_t reg;
178432ae724SEmmanuel Vadot 	uint32_t tx, rx;
179432ae724SEmmanuel Vadot 
180801fb66aSEmmanuel Vadot 	if (!mii_contype_is_rgmii(sc->base.phy_mode))
181432ae724SEmmanuel Vadot 		return;
182432ae724SEmmanuel Vadot 
183432ae724SEmmanuel Vadot 	reg = SYSCON_READ_4(sc->grf, RK3328_GRF_MAC_CON0);
184432ae724SEmmanuel Vadot 	tx = ((reg >> MAC_CON0_GMAC2IO_TX_DL_CFG_SHIFT) & MAC_CON0_GMAC2IO_TX_DL_CFG_MASK);
185432ae724SEmmanuel Vadot 	rx = ((reg >> MAC_CON0_GMAC2IO_RX_DL_CFG_SHIFT) & MAC_CON0_GMAC2IO_RX_DL_CFG_MASK);
186432ae724SEmmanuel Vadot 
187432ae724SEmmanuel Vadot 	reg = SYSCON_READ_4(sc->grf, RK3328_GRF_MAC_CON1);
188432ae724SEmmanuel Vadot 	if (bootverbose) {
189432ae724SEmmanuel Vadot 		device_printf(sc->base.dev, "current delays settings: tx=%u(%s) rx=%u(%s)\n",
190432ae724SEmmanuel Vadot 		    tx, ((reg & MAC_CON1_GMAC2IO_GMAC_TXCLK_DLY_ENA) ? "enabled" : "disabled"),
191432ae724SEmmanuel Vadot 		    rx, ((reg & MAC_CON1_GMAC2IO_GMAC_RXCLK_DLY_ENA) ? "enabled" : "disabled"));
192432ae724SEmmanuel Vadot 
193432ae724SEmmanuel Vadot 		device_printf(sc->base.dev, "setting new RK3328 RX/TX delays:  %d/%d\n",
194432ae724SEmmanuel Vadot 			sc->tx_delay, sc->rx_delay);
195432ae724SEmmanuel Vadot 	}
196432ae724SEmmanuel Vadot 
197432ae724SEmmanuel Vadot 	reg = (MAC_CON1_GMAC2IO_GMAC_TXCLK_DLY_ENA | MAC_CON1_GMAC2IO_GMAC_RXCLK_DLY_ENA) << 16;
198432ae724SEmmanuel Vadot 	reg |= (MAC_CON1_GMAC2IO_GMAC_TXCLK_DLY_ENA | MAC_CON1_GMAC2IO_GMAC_RXCLK_DLY_ENA);
199432ae724SEmmanuel Vadot 	SYSCON_WRITE_4(sc->grf, RK3328_GRF_MAC_CON1, reg);
200432ae724SEmmanuel Vadot 
201432ae724SEmmanuel Vadot 	reg = 0xffff << 16;
202432ae724SEmmanuel Vadot 	reg |= ((sc->tx_delay & MAC_CON0_GMAC2IO_TX_DL_CFG_MASK) <<
203432ae724SEmmanuel Vadot 	    MAC_CON0_GMAC2IO_TX_DL_CFG_SHIFT);
204432ae724SEmmanuel Vadot 	reg |= ((sc->rx_delay & MAC_CON0_GMAC2IO_TX_DL_CFG_MASK) <<
205432ae724SEmmanuel Vadot 	    MAC_CON0_GMAC2IO_RX_DL_CFG_SHIFT);
206432ae724SEmmanuel Vadot 	SYSCON_WRITE_4(sc->grf, RK3328_GRF_MAC_CON0, reg);
207432ae724SEmmanuel Vadot }
208432ae724SEmmanuel Vadot 
209432ae724SEmmanuel Vadot static int
210432ae724SEmmanuel Vadot rk3328_set_speed(struct if_dwc_rk_softc *sc, int speed)
211432ae724SEmmanuel Vadot {
212432ae724SEmmanuel Vadot 	uint32_t reg;
213432ae724SEmmanuel Vadot 
214432ae724SEmmanuel Vadot 	switch (sc->base.phy_mode) {
215801fb66aSEmmanuel Vadot 	case MII_CONTYPE_RGMII:
216801fb66aSEmmanuel Vadot 	case MII_CONTYPE_RGMII_ID:
217801fb66aSEmmanuel Vadot 	case MII_CONTYPE_RGMII_RXID:
218801fb66aSEmmanuel Vadot 	case MII_CONTYPE_RGMII_TXID:
219432ae724SEmmanuel Vadot 		switch (speed) {
220432ae724SEmmanuel Vadot 		case IFM_1000_T:
221432ae724SEmmanuel Vadot 		case IFM_1000_SX:
222432ae724SEmmanuel Vadot 			reg = MAC_CON1_GMAC2IO_GMII_CLK_SEL_125;
223432ae724SEmmanuel Vadot 			break;
224432ae724SEmmanuel Vadot 		case IFM_100_TX:
225432ae724SEmmanuel Vadot 			reg = MAC_CON1_GMAC2IO_GMII_CLK_SEL_25;
226432ae724SEmmanuel Vadot 			break;
227432ae724SEmmanuel Vadot 		case IFM_10_T:
228432ae724SEmmanuel Vadot 			reg = MAC_CON1_GMAC2IO_GMII_CLK_SEL_2_5;
229432ae724SEmmanuel Vadot 			break;
230432ae724SEmmanuel Vadot 		default:
231432ae724SEmmanuel Vadot 			device_printf(sc->base.dev, "unsupported RGMII media %u\n", speed);
232432ae724SEmmanuel Vadot 			return (-1);
233432ae724SEmmanuel Vadot 		}
234432ae724SEmmanuel Vadot 
235432ae724SEmmanuel Vadot 		SYSCON_WRITE_4(sc->grf, RK3328_GRF_MAC_CON1,
236432ae724SEmmanuel Vadot 		    ((MAC_CON1_GMAC2IO_GMII_CLK_SEL_MASK << 16) | reg));
237432ae724SEmmanuel Vadot 		break;
238801fb66aSEmmanuel Vadot 	case MII_CONTYPE_RMII:
239432ae724SEmmanuel Vadot 		switch (speed) {
240432ae724SEmmanuel Vadot 		case IFM_100_TX:
241432ae724SEmmanuel Vadot 			reg = MAC_CON1_GMAC2IO_RMII_CLK_SEL_25 |
242432ae724SEmmanuel Vadot 			    MAC_CON1_GMAC2IO_MAC_SPEED_100;
243432ae724SEmmanuel Vadot 			break;
244432ae724SEmmanuel Vadot 		case IFM_10_T:
245432ae724SEmmanuel Vadot 			reg = MAC_CON1_GMAC2IO_RMII_CLK_SEL_2_5 |
246432ae724SEmmanuel Vadot 			    MAC_CON1_GMAC2IO_MAC_SPEED_10;
247432ae724SEmmanuel Vadot 			break;
248432ae724SEmmanuel Vadot 		default:
249432ae724SEmmanuel Vadot 			device_printf(sc->base.dev, "unsupported RMII media %u\n", speed);
250432ae724SEmmanuel Vadot 			return (-1);
251432ae724SEmmanuel Vadot 		}
252432ae724SEmmanuel Vadot 
253432ae724SEmmanuel Vadot 		SYSCON_WRITE_4(sc->grf,
254432ae724SEmmanuel Vadot 		    sc->integrated_phy ? RK3328_GRF_MAC_CON2 : RK3328_GRF_MAC_CON1,
255432ae724SEmmanuel Vadot 		    reg |
256432ae724SEmmanuel Vadot 		    ((MAC_CON1_GMAC2IO_RMII_CLK_SEL_MASK | MAC_CON1_GMAC2IO_MAC_SPEED_MASK) << 16));
257432ae724SEmmanuel Vadot 		break;
258432ae724SEmmanuel Vadot 	}
259432ae724SEmmanuel Vadot 
260432ae724SEmmanuel Vadot 	return (0);
261432ae724SEmmanuel Vadot }
262432ae724SEmmanuel Vadot 
263432ae724SEmmanuel Vadot static void
264432ae724SEmmanuel Vadot rk3328_set_phy_mode(struct if_dwc_rk_softc *sc)
265432ae724SEmmanuel Vadot {
266432ae724SEmmanuel Vadot 
267432ae724SEmmanuel Vadot 	switch (sc->base.phy_mode) {
268801fb66aSEmmanuel Vadot 	case MII_CONTYPE_RGMII:
269801fb66aSEmmanuel Vadot 	case MII_CONTYPE_RGMII_ID:
270801fb66aSEmmanuel Vadot 	case MII_CONTYPE_RGMII_RXID:
271801fb66aSEmmanuel Vadot 	case MII_CONTYPE_RGMII_TXID:
272432ae724SEmmanuel Vadot 		SYSCON_WRITE_4(sc->grf, RK3328_GRF_MAC_CON1,
273432ae724SEmmanuel Vadot 		    ((MAC_CON1_GMAC2IO_INTF_SEL_MASK | MAC_CON1_GMAC2IO_RMII_MODE_MASK) << 16) |
274432ae724SEmmanuel Vadot 		    MAC_CON1_GMAC2IO_INTF_RGMII);
275432ae724SEmmanuel Vadot 		break;
276801fb66aSEmmanuel Vadot 	case MII_CONTYPE_RMII:
277432ae724SEmmanuel Vadot 		SYSCON_WRITE_4(sc->grf, sc->integrated_phy ? RK3328_GRF_MAC_CON2 : RK3328_GRF_MAC_CON1,
278432ae724SEmmanuel Vadot 		    ((MAC_CON1_GMAC2IO_INTF_SEL_MASK | MAC_CON1_GMAC2IO_RMII_MODE_MASK) << 16) |
279432ae724SEmmanuel Vadot 		    MAC_CON1_GMAC2IO_INTF_RMII | MAC_CON1_GMAC2IO_RMII_MODE);
280432ae724SEmmanuel Vadot 		break;
281432ae724SEmmanuel Vadot 	}
282432ae724SEmmanuel Vadot }
283432ae724SEmmanuel Vadot 
284432ae724SEmmanuel Vadot static void
285432ae724SEmmanuel Vadot rk3328_phy_powerup(struct if_dwc_rk_softc *sc)
286432ae724SEmmanuel Vadot {
287432ae724SEmmanuel Vadot 	SYSCON_WRITE_4(sc->grf, RK3328_GRF_MACPHY_CON1,
288432ae724SEmmanuel Vadot 	    (MACPHY_CON1_RMII_MODE_MASK << 16) |
289432ae724SEmmanuel Vadot 	    MACPHY_CON1_RMII_MODE);
290432ae724SEmmanuel Vadot }
291432ae724SEmmanuel Vadot 
292432ae724SEmmanuel Vadot static void
293432ae724SEmmanuel Vadot rk3399_set_delays(struct if_dwc_rk_softc *sc)
294432ae724SEmmanuel Vadot {
295432ae724SEmmanuel Vadot 	uint32_t reg, tx, rx;
296432ae724SEmmanuel Vadot 
297801fb66aSEmmanuel Vadot 	if (!mii_contype_is_rgmii(sc->base.phy_mode))
298432ae724SEmmanuel Vadot 		return;
299432ae724SEmmanuel Vadot 
300432ae724SEmmanuel Vadot 	reg = SYSCON_READ_4(sc->grf, RK3399_GRF_SOC_CON6);
301432ae724SEmmanuel Vadot 	tx = ((reg >> SOC_CON6_TX_DL_CFG_SHIFT) & SOC_CON6_TX_DL_CFG_MASK);
302432ae724SEmmanuel Vadot 	rx = ((reg >> SOC_CON6_RX_DL_CFG_SHIFT) & SOC_CON6_RX_DL_CFG_MASK);
303432ae724SEmmanuel Vadot 
304432ae724SEmmanuel Vadot 	if (bootverbose) {
305432ae724SEmmanuel Vadot 		device_printf(sc->base.dev, "current delays settings: tx=%u(%s) rx=%u(%s)\n",
306432ae724SEmmanuel Vadot 		    tx, ((reg & SOC_CON6_GMAC_TXCLK_DLY_ENA) ? "enabled" : "disabled"),
307432ae724SEmmanuel Vadot 		    rx, ((reg & SOC_CON6_GMAC_RXCLK_DLY_ENA) ? "enabled" : "disabled"));
308432ae724SEmmanuel Vadot 
309432ae724SEmmanuel Vadot 		device_printf(sc->base.dev, "setting new RK3399 RX/TX delays:  %d/%d\n",
310432ae724SEmmanuel Vadot 		    sc->rx_delay, sc->tx_delay);
311432ae724SEmmanuel Vadot 	}
312432ae724SEmmanuel Vadot 
313432ae724SEmmanuel Vadot 	reg = 0xFFFF << 16;
314432ae724SEmmanuel Vadot 	reg |= ((sc->tx_delay & SOC_CON6_TX_DL_CFG_MASK) <<
315432ae724SEmmanuel Vadot 	    SOC_CON6_TX_DL_CFG_SHIFT);
316432ae724SEmmanuel Vadot 	reg |= ((sc->rx_delay & SOC_CON6_RX_DL_CFG_MASK) <<
317432ae724SEmmanuel Vadot 	    SOC_CON6_RX_DL_CFG_SHIFT);
318432ae724SEmmanuel Vadot 	reg |= SOC_CON6_GMAC_TXCLK_DLY_ENA | SOC_CON6_GMAC_RXCLK_DLY_ENA;
319432ae724SEmmanuel Vadot 
320432ae724SEmmanuel Vadot 	SYSCON_WRITE_4(sc->grf, RK3399_GRF_SOC_CON6, reg);
321432ae724SEmmanuel Vadot }
322432ae724SEmmanuel Vadot 
323432ae724SEmmanuel Vadot static int
324432ae724SEmmanuel Vadot rk3399_set_speed(struct if_dwc_rk_softc *sc, int speed)
325432ae724SEmmanuel Vadot {
326432ae724SEmmanuel Vadot 	uint32_t reg;
327432ae724SEmmanuel Vadot 
328432ae724SEmmanuel Vadot 	switch (speed) {
329432ae724SEmmanuel Vadot 	case IFM_1000_T:
330432ae724SEmmanuel Vadot 	case IFM_1000_SX:
331432ae724SEmmanuel Vadot 		reg = SOC_CON5_GMAC_CLK_SEL_125;
332432ae724SEmmanuel Vadot 		break;
333432ae724SEmmanuel Vadot 	case IFM_100_TX:
334432ae724SEmmanuel Vadot 		reg = SOC_CON5_GMAC_CLK_SEL_25;
335432ae724SEmmanuel Vadot 		break;
336432ae724SEmmanuel Vadot 	case IFM_10_T:
337432ae724SEmmanuel Vadot 		reg = SOC_CON5_GMAC_CLK_SEL_2_5;
338432ae724SEmmanuel Vadot 		break;
339432ae724SEmmanuel Vadot 	default:
340432ae724SEmmanuel Vadot 		device_printf(sc->base.dev, "unsupported media %u\n", speed);
341432ae724SEmmanuel Vadot 		return (-1);
342432ae724SEmmanuel Vadot 	}
343432ae724SEmmanuel Vadot 
344432ae724SEmmanuel Vadot 	SYSCON_WRITE_4(sc->grf, RK3399_GRF_SOC_CON5,
345432ae724SEmmanuel Vadot 	    ((SOC_CON5_GMAC_CLK_SEL_MASK << 16) | reg));
346432ae724SEmmanuel Vadot 	return (0);
347432ae724SEmmanuel Vadot }
348432ae724SEmmanuel Vadot 
349432ae724SEmmanuel Vadot static int
350432ae724SEmmanuel Vadot if_dwc_rk_sysctl_delays(SYSCTL_HANDLER_ARGS)
351432ae724SEmmanuel Vadot {
352432ae724SEmmanuel Vadot 	struct if_dwc_rk_softc *sc;
353432ae724SEmmanuel Vadot 	int rv;
354432ae724SEmmanuel Vadot 	uint32_t rxtx;
355432ae724SEmmanuel Vadot 
356432ae724SEmmanuel Vadot 	sc = arg1;
357432ae724SEmmanuel Vadot 	rxtx = ((sc->rx_delay << 8) | sc->tx_delay);
358432ae724SEmmanuel Vadot 
359432ae724SEmmanuel Vadot 	rv = sysctl_handle_int(oidp, &rxtx, 0, req);
360432ae724SEmmanuel Vadot 	if (rv != 0 || req->newptr == NULL)
361432ae724SEmmanuel Vadot 		return (rv);
362432ae724SEmmanuel Vadot 	sc->tx_delay = rxtx & 0xff;
363432ae724SEmmanuel Vadot 	sc->rx_delay = (rxtx >> 8) & 0xff;
364432ae724SEmmanuel Vadot 
365432ae724SEmmanuel Vadot 	if (sc->ops->set_delays)
366432ae724SEmmanuel Vadot 	    sc->ops->set_delays(sc);
367432ae724SEmmanuel Vadot 
368432ae724SEmmanuel Vadot 	return (0);
369432ae724SEmmanuel Vadot }
370432ae724SEmmanuel Vadot 
371432ae724SEmmanuel Vadot static int
372432ae724SEmmanuel Vadot if_dwc_rk_init_sysctl(struct if_dwc_rk_softc *sc)
373432ae724SEmmanuel Vadot {
374432ae724SEmmanuel Vadot 	struct sysctl_oid *child;
375432ae724SEmmanuel Vadot 	struct sysctl_ctx_list *ctx_list;
376432ae724SEmmanuel Vadot 
377432ae724SEmmanuel Vadot 	ctx_list = device_get_sysctl_ctx(sc->base.dev);
378432ae724SEmmanuel Vadot 	child = device_get_sysctl_tree(sc->base.dev);
379432ae724SEmmanuel Vadot 	SYSCTL_ADD_PROC(ctx_list,
380432ae724SEmmanuel Vadot 	    SYSCTL_CHILDREN(child), OID_AUTO, "delays",
381432ae724SEmmanuel Vadot 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, sc, 0,
382432ae724SEmmanuel Vadot 	    if_dwc_rk_sysctl_delays, "", "RGMII RX/TX delays: ((rx << 8) | tx)");
383432ae724SEmmanuel Vadot 
384432ae724SEmmanuel Vadot 	return (0);
385432ae724SEmmanuel Vadot }
386432ae724SEmmanuel Vadot 
387432ae724SEmmanuel Vadot static int
388432ae724SEmmanuel Vadot if_dwc_rk_probe(device_t dev)
389432ae724SEmmanuel Vadot {
390432ae724SEmmanuel Vadot 
391432ae724SEmmanuel Vadot 	if (!ofw_bus_status_okay(dev))
392432ae724SEmmanuel Vadot 		return (ENXIO);
393432ae724SEmmanuel Vadot 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
394432ae724SEmmanuel Vadot 		return (ENXIO);
395432ae724SEmmanuel Vadot 	device_set_desc(dev, "Rockchip Gigabit Ethernet Controller");
396432ae724SEmmanuel Vadot 
397432ae724SEmmanuel Vadot 	return (BUS_PROBE_DEFAULT);
398432ae724SEmmanuel Vadot }
399432ae724SEmmanuel Vadot 
400432ae724SEmmanuel Vadot static int
401432ae724SEmmanuel Vadot if_dwc_rk_init_clocks(device_t dev)
402432ae724SEmmanuel Vadot {
403432ae724SEmmanuel Vadot 	struct if_dwc_rk_softc *sc;
404432ae724SEmmanuel Vadot 
405432ae724SEmmanuel Vadot 	sc = device_get_softc(dev);
406432ae724SEmmanuel Vadot 
407432ae724SEmmanuel Vadot 	/* Enable clocks */
408432ae724SEmmanuel Vadot 
409432ae724SEmmanuel Vadot 	if (clk_get_by_ofw_name(dev, 0, "mac_clk_tx", &sc->mac_clk_tx) != 0) {
410432ae724SEmmanuel Vadot 		device_printf(sc->base.dev, "could not get mac_clk_tx clock\n");
411432ae724SEmmanuel Vadot 		sc->mac_clk_tx = NULL;
412432ae724SEmmanuel Vadot 	}
413432ae724SEmmanuel Vadot 
414432ae724SEmmanuel Vadot 	if (clk_get_by_ofw_name(dev, 0, "aclk_mac", &sc->aclk_mac) != 0) {
415432ae724SEmmanuel Vadot 		device_printf(sc->base.dev, "could not get aclk_mac clock\n");
416432ae724SEmmanuel Vadot 		sc->aclk_mac = NULL;
417432ae724SEmmanuel Vadot 	}
418432ae724SEmmanuel Vadot 
419432ae724SEmmanuel Vadot 	if (clk_get_by_ofw_name(dev, 0, "pclk_mac", &sc->pclk_mac) != 0) {
420432ae724SEmmanuel Vadot 		device_printf(sc->base.dev, "could not get pclk_mac clock\n");
421432ae724SEmmanuel Vadot 		sc->pclk_mac = NULL;
422432ae724SEmmanuel Vadot 	}
423432ae724SEmmanuel Vadot 
42450059a60SEmmanuel Vadot 	/* Optional clock */
42550059a60SEmmanuel Vadot 	clk_get_by_ofw_name(dev, 0, "clk_mac_speed", &sc->clk_mac_speed);
42650059a60SEmmanuel Vadot 
427801fb66aSEmmanuel Vadot 	if (sc->base.phy_mode == MII_CONTYPE_RMII) {
42850059a60SEmmanuel Vadot 		if (clk_get_by_ofw_name(dev, 0, "mac_clk_rx", &sc->mac_clk_rx) != 0) {
42950059a60SEmmanuel Vadot 			device_printf(sc->base.dev, "could not get mac_clk_rx clock\n");
43050059a60SEmmanuel Vadot 			sc->mac_clk_rx = NULL;
43150059a60SEmmanuel Vadot 		}
43250059a60SEmmanuel Vadot 
433432ae724SEmmanuel Vadot 		if (clk_get_by_ofw_name(dev, 0, "clk_mac_ref", &sc->clk_mac_ref) != 0) {
434432ae724SEmmanuel Vadot 			device_printf(sc->base.dev, "could not get clk_mac_ref clock\n");
435432ae724SEmmanuel Vadot 			sc->clk_mac_ref = NULL;
436432ae724SEmmanuel Vadot 		}
437432ae724SEmmanuel Vadot 
438432ae724SEmmanuel Vadot 		if (!sc->clock_in) {
439432ae724SEmmanuel Vadot 			if (clk_get_by_ofw_name(dev, 0, "clk_mac_refout", &sc->clk_mac_refout) != 0) {
440432ae724SEmmanuel Vadot 				device_printf(sc->base.dev, "could not get clk_mac_refout clock\n");
441432ae724SEmmanuel Vadot 				sc->clk_mac_refout = NULL;
442432ae724SEmmanuel Vadot 			}
443432ae724SEmmanuel Vadot 
444432ae724SEmmanuel Vadot 			clk_set_freq(sc->clk_stmmaceth, 50000000, 0);
445432ae724SEmmanuel Vadot 		}
446432ae724SEmmanuel Vadot 	}
447432ae724SEmmanuel Vadot 
448432ae724SEmmanuel Vadot 	if ((sc->phy_node != 0) && sc->integrated_phy) {
449432ae724SEmmanuel Vadot 		if (clk_get_by_ofw_index(dev, sc->phy_node, 0, &sc->clk_phy) != 0) {
450432ae724SEmmanuel Vadot 			device_printf(sc->base.dev, "could not get PHY clock\n");
451432ae724SEmmanuel Vadot 			sc->clk_phy = NULL;
452432ae724SEmmanuel Vadot 		}
453432ae724SEmmanuel Vadot 
454432ae724SEmmanuel Vadot 		if (sc->clk_phy) {
455432ae724SEmmanuel Vadot 			clk_set_freq(sc->clk_phy, 50000000, 0);
456432ae724SEmmanuel Vadot 		}
457432ae724SEmmanuel Vadot 	}
458432ae724SEmmanuel Vadot 
459801fb66aSEmmanuel Vadot 	if (sc->base.phy_mode == MII_CONTYPE_RMII) {
460432ae724SEmmanuel Vadot 		if (sc->mac_clk_rx)
461432ae724SEmmanuel Vadot 			clk_enable(sc->mac_clk_rx);
462432ae724SEmmanuel Vadot 		if (sc->clk_mac_ref)
463432ae724SEmmanuel Vadot 			clk_enable(sc->clk_mac_ref);
464432ae724SEmmanuel Vadot 		if (sc->clk_mac_refout)
465432ae724SEmmanuel Vadot 			clk_enable(sc->clk_mac_refout);
466432ae724SEmmanuel Vadot 	}
467432ae724SEmmanuel Vadot 	if (sc->clk_phy)
468432ae724SEmmanuel Vadot 		clk_enable(sc->clk_phy);
469432ae724SEmmanuel Vadot 	if (sc->aclk_mac)
470432ae724SEmmanuel Vadot 		clk_enable(sc->aclk_mac);
471432ae724SEmmanuel Vadot 	if (sc->pclk_mac)
472432ae724SEmmanuel Vadot 		clk_enable(sc->pclk_mac);
473432ae724SEmmanuel Vadot 	if (sc->mac_clk_tx)
474432ae724SEmmanuel Vadot 		clk_enable(sc->mac_clk_tx);
47550059a60SEmmanuel Vadot 	if (sc->clk_mac_speed)
47650059a60SEmmanuel Vadot 		clk_enable(sc->clk_mac_speed);
477432ae724SEmmanuel Vadot 
478432ae724SEmmanuel Vadot 	DELAY(50);
479432ae724SEmmanuel Vadot 
480432ae724SEmmanuel Vadot 	return (0);
481432ae724SEmmanuel Vadot }
482432ae724SEmmanuel Vadot 
483432ae724SEmmanuel Vadot static int
484432ae724SEmmanuel Vadot if_dwc_rk_init(device_t dev)
485432ae724SEmmanuel Vadot {
486432ae724SEmmanuel Vadot 	struct if_dwc_rk_softc *sc;
487432ae724SEmmanuel Vadot 	phandle_t node;
488432ae724SEmmanuel Vadot 	uint32_t rx, tx;
489432ae724SEmmanuel Vadot 	int err;
490432ae724SEmmanuel Vadot 	pcell_t phy_handle;
491432ae724SEmmanuel Vadot 	char *clock_in_out;
492432ae724SEmmanuel Vadot 	hwreset_t phy_reset;
493432ae724SEmmanuel Vadot 	regulator_t phy_supply;
494432ae724SEmmanuel Vadot 
495432ae724SEmmanuel Vadot 	sc = device_get_softc(dev);
496432ae724SEmmanuel Vadot 	node = ofw_bus_get_node(dev);
497432ae724SEmmanuel Vadot 	sc->ops = (struct if_dwc_rk_ops *)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
498432ae724SEmmanuel Vadot 	if (OF_hasprop(node, "rockchip,grf") &&
499432ae724SEmmanuel Vadot 	    syscon_get_by_ofw_property(dev, node,
500432ae724SEmmanuel Vadot 	    "rockchip,grf", &sc->grf) != 0) {
501432ae724SEmmanuel Vadot 		device_printf(dev, "cannot get grf driver handle\n");
502432ae724SEmmanuel Vadot 		return (ENXIO);
503432ae724SEmmanuel Vadot 	}
504432ae724SEmmanuel Vadot 
505432ae724SEmmanuel Vadot 	if (OF_getencprop(node, "tx_delay", &tx, sizeof(tx)) <= 0)
506432ae724SEmmanuel Vadot 		tx = 0x30;
507432ae724SEmmanuel Vadot 	if (OF_getencprop(node, "rx_delay", &rx, sizeof(rx)) <= 0)
508432ae724SEmmanuel Vadot 		rx = 0x10;
509432ae724SEmmanuel Vadot 	sc->tx_delay = tx;
510432ae724SEmmanuel Vadot 	sc->rx_delay = rx;
511432ae724SEmmanuel Vadot 
512432ae724SEmmanuel Vadot 	sc->clock_in = true;
513432ae724SEmmanuel Vadot 	if (OF_getprop_alloc(node, "clock_in_out", (void **)&clock_in_out)) {
514432ae724SEmmanuel Vadot 		if (strcmp(clock_in_out, "input") == 0)
515432ae724SEmmanuel Vadot 			sc->clock_in = true;
516432ae724SEmmanuel Vadot 		else
517432ae724SEmmanuel Vadot 			sc->clock_in = false;
518432ae724SEmmanuel Vadot 		OF_prop_free(clock_in_out);
519432ae724SEmmanuel Vadot 	}
520432ae724SEmmanuel Vadot 
521432ae724SEmmanuel Vadot 	if (OF_getencprop(node, "phy-handle", (void *)&phy_handle,
522432ae724SEmmanuel Vadot 	    sizeof(phy_handle)) > 0)
523432ae724SEmmanuel Vadot 		sc->phy_node = OF_node_from_xref(phy_handle);
524432ae724SEmmanuel Vadot 
525432ae724SEmmanuel Vadot 	if (sc->phy_node)
526432ae724SEmmanuel Vadot 		sc->integrated_phy = OF_hasprop(sc->phy_node, "phy-is-integrated");
527432ae724SEmmanuel Vadot 
528432ae724SEmmanuel Vadot 	if (sc->integrated_phy)
529432ae724SEmmanuel Vadot 		device_printf(sc->base.dev, "PHY is integrated\n");
530432ae724SEmmanuel Vadot 
531432ae724SEmmanuel Vadot 	if_dwc_rk_init_clocks(dev);
532432ae724SEmmanuel Vadot 
533432ae724SEmmanuel Vadot 	if (sc->ops->set_phy_mode)
534432ae724SEmmanuel Vadot 	    sc->ops->set_phy_mode(sc);
535432ae724SEmmanuel Vadot 
536432ae724SEmmanuel Vadot 	if (sc->ops->set_delays)
537432ae724SEmmanuel Vadot 	    sc->ops->set_delays(sc);
538432ae724SEmmanuel Vadot 
539432ae724SEmmanuel Vadot 	/*
540432ae724SEmmanuel Vadot 	 * this also sets delays if tunable is defined
541432ae724SEmmanuel Vadot 	 */
542432ae724SEmmanuel Vadot 	err = if_dwc_rk_init_sysctl(sc);
543432ae724SEmmanuel Vadot 	if (err != 0)
544432ae724SEmmanuel Vadot 		return (err);
545432ae724SEmmanuel Vadot 
546432ae724SEmmanuel Vadot 	if (regulator_get_by_ofw_property(sc->base.dev, 0,
547432ae724SEmmanuel Vadot 		            "phy-supply", &phy_supply) == 0) {
548432ae724SEmmanuel Vadot 		if (regulator_enable(phy_supply)) {
549432ae724SEmmanuel Vadot 			device_printf(sc->base.dev,
550432ae724SEmmanuel Vadot 			    "cannot enable 'phy' regulator\n");
551432ae724SEmmanuel Vadot 		}
552432ae724SEmmanuel Vadot 	}
553432ae724SEmmanuel Vadot 	else
554432ae724SEmmanuel Vadot 		device_printf(sc->base.dev, "no phy-supply property\n");
555432ae724SEmmanuel Vadot 
556432ae724SEmmanuel Vadot 	/* Power up */
557432ae724SEmmanuel Vadot 	if (sc->integrated_phy) {
558432ae724SEmmanuel Vadot 		if (sc->ops->phy_powerup)
559432ae724SEmmanuel Vadot 			sc->ops->phy_powerup(sc);
560432ae724SEmmanuel Vadot 
561432ae724SEmmanuel Vadot 		SYSCON_WRITE_4(sc->grf, RK3328_GRF_MACPHY_CON0,
562432ae724SEmmanuel Vadot 		    (MACPHY_CON0_CLK_50M_MASK << 16) |
563432ae724SEmmanuel Vadot 		    MACPHY_CON0_CLK_50M);
564432ae724SEmmanuel Vadot 		SYSCON_WRITE_4(sc->grf, RK3328_GRF_MACPHY_CON0,
565432ae724SEmmanuel Vadot 		    (MACPHY_CON0_RMII_MODE_MASK << 16) |
566432ae724SEmmanuel Vadot 		    MACPHY_CON0_RMII_MODE);
567432ae724SEmmanuel Vadot 		SYSCON_WRITE_4(sc->grf, RK3328_GRF_MACPHY_CON2, 0xffff1234);
568432ae724SEmmanuel Vadot 		SYSCON_WRITE_4(sc->grf, RK3328_GRF_MACPHY_CON3, 0x003f0035);
569432ae724SEmmanuel Vadot 
570432ae724SEmmanuel Vadot 		if (hwreset_get_by_ofw_idx(dev, sc->phy_node, 0, &phy_reset)  == 0) {
571432ae724SEmmanuel Vadot 			hwreset_assert(phy_reset);
572432ae724SEmmanuel Vadot 			DELAY(20);
573432ae724SEmmanuel Vadot 			hwreset_deassert(phy_reset);
574432ae724SEmmanuel Vadot 			DELAY(20);
575432ae724SEmmanuel Vadot 		}
576432ae724SEmmanuel Vadot 	}
577432ae724SEmmanuel Vadot 
578432ae724SEmmanuel Vadot 	return (0);
579432ae724SEmmanuel Vadot }
580432ae724SEmmanuel Vadot 
581432ae724SEmmanuel Vadot static int
582432ae724SEmmanuel Vadot if_dwc_rk_mii_clk(device_t dev)
583432ae724SEmmanuel Vadot {
584*cf037a17SEmmanuel Vadot 	struct if_dwc_rk_softc *sc;
585*cf037a17SEmmanuel Vadot 	uint64_t freq;
586*cf037a17SEmmanuel Vadot 	int rv;
587432ae724SEmmanuel Vadot 
588*cf037a17SEmmanuel Vadot 	sc = device_get_softc(dev);
589*cf037a17SEmmanuel Vadot 	if ((rv = clk_get_freq(sc->pclk_mac, &freq)) != 0)
590*cf037a17SEmmanuel Vadot 		return (-rv);
591*cf037a17SEmmanuel Vadot 	freq = freq / 1000 / 1000;
592*cf037a17SEmmanuel Vadot 
593*cf037a17SEmmanuel Vadot 	if (freq >= 60 && freq <= 100)
594*cf037a17SEmmanuel Vadot 		return (GMAC_MII_CLK_60_100M_DIV42);
595*cf037a17SEmmanuel Vadot 	else if (freq >= 100 && freq <= 150)
596*cf037a17SEmmanuel Vadot 		return (GMAC_MII_CLK_100_150M_DIV62);
597*cf037a17SEmmanuel Vadot 	else if (freq >= 20 && freq <= 35)
598*cf037a17SEmmanuel Vadot 		return (GMAC_MII_CLK_25_35M_DIV16);
599*cf037a17SEmmanuel Vadot 	else if (freq >= 35 && freq <= 60)
600*cf037a17SEmmanuel Vadot 		return (GMAC_MII_CLK_35_60M_DIV26);
601*cf037a17SEmmanuel Vadot 	else if (freq >= 150 && freq <= 250)
602432ae724SEmmanuel Vadot 		return (GMAC_MII_CLK_150_250M_DIV102);
603*cf037a17SEmmanuel Vadot 	else if (freq >= 250 && freq <= 300)
604*cf037a17SEmmanuel Vadot 		return (GMAC_MII_CLK_250_300M_DIV124);
605*cf037a17SEmmanuel Vadot 
606*cf037a17SEmmanuel Vadot 	return (-ERANGE);
607432ae724SEmmanuel Vadot }
608432ae724SEmmanuel Vadot 
609432ae724SEmmanuel Vadot static int
610432ae724SEmmanuel Vadot if_dwc_rk_set_speed(device_t dev, int speed)
611432ae724SEmmanuel Vadot {
612432ae724SEmmanuel Vadot 	struct if_dwc_rk_softc *sc;
613432ae724SEmmanuel Vadot 
614432ae724SEmmanuel Vadot 	sc = device_get_softc(dev);
615432ae724SEmmanuel Vadot 
616432ae724SEmmanuel Vadot 	if (sc->ops->set_speed)
617432ae724SEmmanuel Vadot 	    return sc->ops->set_speed(sc, speed);
618432ae724SEmmanuel Vadot 
619432ae724SEmmanuel Vadot 	return (0);
620432ae724SEmmanuel Vadot }
621432ae724SEmmanuel Vadot 
622432ae724SEmmanuel Vadot static device_method_t if_dwc_rk_methods[] = {
623432ae724SEmmanuel Vadot 	DEVMETHOD(device_probe,		if_dwc_rk_probe),
624432ae724SEmmanuel Vadot 
625432ae724SEmmanuel Vadot 	DEVMETHOD(if_dwc_init,		if_dwc_rk_init),
626432ae724SEmmanuel Vadot 	DEVMETHOD(if_dwc_mii_clk,	if_dwc_rk_mii_clk),
627432ae724SEmmanuel Vadot 	DEVMETHOD(if_dwc_set_speed,	if_dwc_rk_set_speed),
628432ae724SEmmanuel Vadot 
629432ae724SEmmanuel Vadot 	DEVMETHOD_END
630432ae724SEmmanuel Vadot };
631432ae724SEmmanuel Vadot 
632432ae724SEmmanuel Vadot extern driver_t dwc_driver;
633432ae724SEmmanuel Vadot 
634432ae724SEmmanuel Vadot DEFINE_CLASS_1(dwc, dwc_rk_driver, if_dwc_rk_methods,
635432ae724SEmmanuel Vadot     sizeof(struct if_dwc_rk_softc), dwc_driver);
636432ae724SEmmanuel Vadot DRIVER_MODULE(dwc_rk, simplebus, dwc_rk_driver, 0, 0);
637432ae724SEmmanuel Vadot MODULE_DEPEND(dwc_rk, dwc, 1, 1, 1);
638