]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/rockchip/if_dwc_rk.c
Move SYSCTL_ADD_PROC() to unlocked context in if_ure to avoid lock order reversal.
[FreeBSD/FreeBSD.git] / sys / arm64 / rockchip / if_dwc_rk.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/socket.h>
37
38 #include <machine/bus.h>
39
40 #include <net/if.h>
41 #include <net/if_media.h>
42
43 #include <dev/dwc/if_dwc.h>
44 #include <dev/dwc/if_dwcvar.h>
45 #include <dev/ofw/ofw_bus.h>
46 #include <dev/ofw/ofw_bus_subr.h>
47
48 #include <dev/extres/clk/clk.h>
49 #include <dev/extres/hwreset/hwreset.h>
50 #include <dev/extres/regulator/regulator.h>
51 #include <dev/extres/syscon/syscon.h>
52
53 #include "if_dwc_if.h"
54 #include "syscon_if.h"
55
56 #define RK3328_GRF_MAC_CON0             0x0900
57 #define  MAC_CON0_GMAC2IO_TX_DL_CFG_MASK        0x7F
58 #define  MAC_CON0_GMAC2IO_TX_DL_CFG_SHIFT       0
59 #define  MAC_CON0_GMAC2IO_RX_DL_CFG_MASK        0x7F
60 #define  MAC_CON0_GMAC2IO_RX_DL_CFG_SHIFT       7
61
62 #define RK3328_GRF_MAC_CON1             0x0904
63 #define  MAC_CON1_GMAC2IO_GMAC_TXCLK_DLY_ENA    (1 << 0)
64 #define  MAC_CON1_GMAC2IO_GMAC_RXCLK_DLY_ENA    (1 << 1)
65 #define  MAC_CON1_GMAC2IO_GMII_CLK_SEL_MASK     (3 << 11)
66 #define  MAC_CON1_GMAC2IO_GMII_CLK_SEL_125      (0 << 11)
67 #define  MAC_CON1_GMAC2IO_GMII_CLK_SEL_25       (3 << 11)
68 #define  MAC_CON1_GMAC2IO_GMII_CLK_SEL_2_5      (2 << 11)
69 #define  MAC_CON1_GMAC2IO_RMII_MODE_MASK        (1 << 9)
70 #define  MAC_CON1_GMAC2IO_RMII_MODE             (1 << 9)
71 #define  MAC_CON1_GMAC2IO_INTF_SEL_MASK         (7 << 4)
72 #define  MAC_CON1_GMAC2IO_INTF_RMII             (4 << 4)
73 #define  MAC_CON1_GMAC2IO_INTF_RGMII            (1 << 4)
74 #define  MAC_CON1_GMAC2IO_RMII_CLK_SEL_MASK     (1 << 7)
75 #define  MAC_CON1_GMAC2IO_RMII_CLK_SEL_25       (1 << 7)
76 #define  MAC_CON1_GMAC2IO_RMII_CLK_SEL_2_5      (0 << 7)
77 #define  MAC_CON1_GMAC2IO_MAC_SPEED_MASK        (1 << 2)
78 #define  MAC_CON1_GMAC2IO_MAC_SPEED_100         (1 << 2)
79 #define  MAC_CON1_GMAC2IO_MAC_SPEED_10          (0 << 2)
80 #define RK3328_GRF_MAC_CON2             0x0908
81 #define RK3328_GRF_MACPHY_CON0          0x0B00
82 #define  MACPHY_CON0_CLK_50M_MASK               (1 << 14)
83 #define  MACPHY_CON0_CLK_50M                    (1 << 14)
84 #define  MACPHY_CON0_RMII_MODE_MASK             (3 << 6)
85 #define  MACPHY_CON0_RMII_MODE                  (1 << 6)
86 #define RK3328_GRF_MACPHY_CON1          0x0B04
87 #define  MACPHY_CON1_RMII_MODE_MASK             (1 << 9)
88 #define  MACPHY_CON1_RMII_MODE                  (1 << 9)
89 #define RK3328_GRF_MACPHY_CON2          0x0B08
90 #define RK3328_GRF_MACPHY_CON3          0x0B0C
91 #define RK3328_GRF_MACPHY_STATUS        0x0B10
92
93 #define RK3399_GRF_SOC_CON5             0xc214
94 #define  SOC_CON5_GMAC_CLK_SEL_MASK             (3 << 4)
95 #define  SOC_CON5_GMAC_CLK_SEL_125              (0 << 4)
96 #define  SOC_CON5_GMAC_CLK_SEL_25               (3 << 4)
97 #define  SOC_CON5_GMAC_CLK_SEL_2_5              (2 << 4)
98 #define RK3399_GRF_SOC_CON6             0xc218
99 #define  SOC_CON6_GMAC_TXCLK_DLY_ENA            (1 << 7)
100 #define  SOC_CON6_TX_DL_CFG_MASK                0x7F
101 #define  SOC_CON6_TX_DL_CFG_SHIFT               0
102 #define  SOC_CON6_RX_DL_CFG_MASK                0x7F
103 #define  SOC_CON6_GMAC_RXCLK_DLY_ENA            (1 << 15)
104 #define  SOC_CON6_RX_DL_CFG_SHIFT               8
105
106 struct if_dwc_rk_softc;
107
108 typedef void (*if_dwc_rk_set_delaysfn_t)(struct if_dwc_rk_softc *);
109 typedef int (*if_dwc_rk_set_speedfn_t)(struct if_dwc_rk_softc *, int);
110 typedef void (*if_dwc_rk_set_phy_modefn_t)(struct if_dwc_rk_softc *);
111 typedef void (*if_dwc_rk_phy_powerupfn_t)(struct if_dwc_rk_softc *);
112
113 struct if_dwc_rk_ops {
114         if_dwc_rk_set_delaysfn_t        set_delays;
115         if_dwc_rk_set_speedfn_t         set_speed;
116         if_dwc_rk_set_phy_modefn_t      set_phy_mode;
117         if_dwc_rk_phy_powerupfn_t       phy_powerup;
118 };
119
120 struct if_dwc_rk_softc {
121         struct dwc_softc        base;
122         uint32_t                tx_delay;
123         uint32_t                rx_delay;
124         bool                    integrated_phy;
125         bool                    clock_in;
126         phandle_t               phy_node;
127         struct syscon           *grf;
128         struct if_dwc_rk_ops    *ops;
129         /* Common clocks */
130         clk_t                   mac_clk_rx;
131         clk_t                   mac_clk_tx;
132         clk_t                   aclk_mac;
133         clk_t                   pclk_mac;
134         clk_t                   clk_stmmaceth;
135         /* RMII clocks */
136         clk_t                   clk_mac_ref;
137         clk_t                   clk_mac_refout;
138         /* PHY clock */
139         clk_t                   clk_phy;
140 };
141
142 static void rk3328_set_delays(struct if_dwc_rk_softc *sc);
143 static int rk3328_set_speed(struct if_dwc_rk_softc *sc, int speed);
144 static void rk3328_set_phy_mode(struct if_dwc_rk_softc *sc);
145 static void rk3328_phy_powerup(struct if_dwc_rk_softc *sc);
146
147 static void rk3399_set_delays(struct if_dwc_rk_softc *sc);
148 static int rk3399_set_speed(struct if_dwc_rk_softc *sc, int speed);
149
150 static struct if_dwc_rk_ops rk3288_ops = {
151 };
152
153 static struct if_dwc_rk_ops rk3328_ops = {
154         .set_delays = rk3328_set_delays,
155         .set_speed = rk3328_set_speed,
156         .set_phy_mode = rk3328_set_phy_mode,
157         .phy_powerup = rk3328_phy_powerup,
158 };
159
160 static struct if_dwc_rk_ops rk3399_ops = {
161         .set_delays = rk3399_set_delays,
162         .set_speed = rk3399_set_speed,
163 };
164
165 static struct ofw_compat_data compat_data[] = {
166         {"rockchip,rk3288-gmac", (uintptr_t)&rk3288_ops},
167         {"rockchip,rk3328-gmac", (uintptr_t)&rk3328_ops},
168         {"rockchip,rk3399-gmac", (uintptr_t)&rk3399_ops},
169         {NULL,                   0}
170 };
171
172 static void
173 rk3328_set_delays(struct if_dwc_rk_softc *sc)
174 {
175         uint32_t reg;
176         uint32_t tx, rx;
177
178         if (sc->base.phy_mode != PHY_MODE_RGMII)
179                 return;
180
181         reg = SYSCON_READ_4(sc->grf, RK3328_GRF_MAC_CON0);
182         tx = ((reg >> MAC_CON0_GMAC2IO_TX_DL_CFG_SHIFT) & MAC_CON0_GMAC2IO_TX_DL_CFG_MASK);
183         rx = ((reg >> MAC_CON0_GMAC2IO_RX_DL_CFG_SHIFT) & MAC_CON0_GMAC2IO_RX_DL_CFG_MASK);
184
185         reg = SYSCON_READ_4(sc->grf, RK3328_GRF_MAC_CON1);
186         if (bootverbose) {
187                 device_printf(sc->base.dev, "current delays settings: tx=%u(%s) rx=%u(%s)\n",
188                     tx, ((reg & MAC_CON1_GMAC2IO_GMAC_TXCLK_DLY_ENA) ? "enabled" : "disabled"),
189                     rx, ((reg & MAC_CON1_GMAC2IO_GMAC_RXCLK_DLY_ENA) ? "enabled" : "disabled"));
190
191                 device_printf(sc->base.dev, "setting new RK3328 RX/TX delays:  %d/%d\n",
192                         sc->tx_delay, sc->rx_delay);
193         }
194
195         reg = (MAC_CON1_GMAC2IO_GMAC_TXCLK_DLY_ENA | MAC_CON1_GMAC2IO_GMAC_RXCLK_DLY_ENA) << 16;
196         reg |= (MAC_CON1_GMAC2IO_GMAC_TXCLK_DLY_ENA | MAC_CON1_GMAC2IO_GMAC_RXCLK_DLY_ENA);
197         SYSCON_WRITE_4(sc->grf, RK3328_GRF_MAC_CON1, reg);
198
199         reg = 0xffff << 16;
200         reg |= ((sc->tx_delay & MAC_CON0_GMAC2IO_TX_DL_CFG_MASK) <<
201             MAC_CON0_GMAC2IO_TX_DL_CFG_SHIFT);
202         reg |= ((sc->rx_delay & MAC_CON0_GMAC2IO_TX_DL_CFG_MASK) <<
203             MAC_CON0_GMAC2IO_RX_DL_CFG_SHIFT);
204         SYSCON_WRITE_4(sc->grf, RK3328_GRF_MAC_CON0, reg);
205 }
206
207 static int
208 rk3328_set_speed(struct if_dwc_rk_softc *sc, int speed)
209 {
210         uint32_t reg;
211
212         switch (sc->base.phy_mode) {
213         case PHY_MODE_RGMII:
214                 switch (speed) {
215                 case IFM_1000_T:
216                 case IFM_1000_SX:
217                         reg = MAC_CON1_GMAC2IO_GMII_CLK_SEL_125;
218                         break;
219                 case IFM_100_TX:
220                         reg = MAC_CON1_GMAC2IO_GMII_CLK_SEL_25;
221                         break;
222                 case IFM_10_T:
223                         reg = MAC_CON1_GMAC2IO_GMII_CLK_SEL_2_5;
224                         break;
225                 default:
226                         device_printf(sc->base.dev, "unsupported RGMII media %u\n", speed);
227                         return (-1);
228                 }
229
230                 SYSCON_WRITE_4(sc->grf, RK3328_GRF_MAC_CON1,
231                     ((MAC_CON1_GMAC2IO_GMII_CLK_SEL_MASK << 16) | reg));
232                 break;
233         case PHY_MODE_RMII:
234                 switch (speed) {
235                 case IFM_100_TX:
236                         reg = MAC_CON1_GMAC2IO_RMII_CLK_SEL_25 |
237                             MAC_CON1_GMAC2IO_MAC_SPEED_100;
238                         break;
239                 case IFM_10_T:
240                         reg = MAC_CON1_GMAC2IO_RMII_CLK_SEL_2_5 |
241                             MAC_CON1_GMAC2IO_MAC_SPEED_10;
242                         break;
243                 default:
244                         device_printf(sc->base.dev, "unsupported RMII media %u\n", speed);
245                         return (-1);
246                 }
247
248                 SYSCON_WRITE_4(sc->grf,
249                     sc->integrated_phy ? RK3328_GRF_MAC_CON2 : RK3328_GRF_MAC_CON1,
250                     reg |
251                     ((MAC_CON1_GMAC2IO_RMII_CLK_SEL_MASK | MAC_CON1_GMAC2IO_MAC_SPEED_MASK) << 16));
252                 break;
253         }
254
255         return (0);
256 }
257
258 static void
259 rk3328_set_phy_mode(struct if_dwc_rk_softc *sc)
260 {
261
262         switch (sc->base.phy_mode) {
263         case PHY_MODE_RGMII:
264                 SYSCON_WRITE_4(sc->grf, RK3328_GRF_MAC_CON1,
265                     ((MAC_CON1_GMAC2IO_INTF_SEL_MASK | MAC_CON1_GMAC2IO_RMII_MODE_MASK) << 16) |
266                     MAC_CON1_GMAC2IO_INTF_RGMII);
267                 break;
268         case PHY_MODE_RMII:
269                 SYSCON_WRITE_4(sc->grf, sc->integrated_phy ? RK3328_GRF_MAC_CON2 : RK3328_GRF_MAC_CON1,
270                     ((MAC_CON1_GMAC2IO_INTF_SEL_MASK | MAC_CON1_GMAC2IO_RMII_MODE_MASK) << 16) |
271                     MAC_CON1_GMAC2IO_INTF_RMII | MAC_CON1_GMAC2IO_RMII_MODE);
272                 break;
273         }
274 }
275
276 static void
277 rk3328_phy_powerup(struct if_dwc_rk_softc *sc)
278 {
279         SYSCON_WRITE_4(sc->grf, RK3328_GRF_MACPHY_CON1,
280             (MACPHY_CON1_RMII_MODE_MASK << 16) |
281             MACPHY_CON1_RMII_MODE);
282 }
283
284 static void
285 rk3399_set_delays(struct if_dwc_rk_softc *sc)
286 {
287         uint32_t reg, tx, rx;
288
289         if (sc->base.phy_mode != PHY_MODE_RGMII)
290                 return;
291
292         reg = SYSCON_READ_4(sc->grf, RK3399_GRF_SOC_CON6);
293         tx = ((reg >> SOC_CON6_TX_DL_CFG_SHIFT) & SOC_CON6_TX_DL_CFG_MASK);
294         rx = ((reg >> SOC_CON6_RX_DL_CFG_SHIFT) & SOC_CON6_RX_DL_CFG_MASK);
295
296         if (bootverbose) {
297                 device_printf(sc->base.dev, "current delays settings: tx=%u(%s) rx=%u(%s)\n",
298                     tx, ((reg & SOC_CON6_GMAC_TXCLK_DLY_ENA) ? "enabled" : "disabled"),
299                     rx, ((reg & SOC_CON6_GMAC_RXCLK_DLY_ENA) ? "enabled" : "disabled"));
300
301                 device_printf(sc->base.dev, "setting new RK3399 RX/TX delays:  %d/%d\n",
302                     sc->rx_delay, sc->tx_delay);
303         }
304
305         reg = 0xFFFF << 16;
306         reg |= ((sc->tx_delay & SOC_CON6_TX_DL_CFG_MASK) <<
307             SOC_CON6_TX_DL_CFG_SHIFT);
308         reg |= ((sc->rx_delay & SOC_CON6_RX_DL_CFG_MASK) <<
309             SOC_CON6_RX_DL_CFG_SHIFT);
310         reg |= SOC_CON6_GMAC_TXCLK_DLY_ENA | SOC_CON6_GMAC_RXCLK_DLY_ENA;
311
312         SYSCON_WRITE_4(sc->grf, RK3399_GRF_SOC_CON6, reg);
313 }
314
315 static int
316 rk3399_set_speed(struct if_dwc_rk_softc *sc, int speed)
317 {
318         uint32_t reg;
319
320         switch (speed) {
321         case IFM_1000_T:
322         case IFM_1000_SX:
323                 reg = SOC_CON5_GMAC_CLK_SEL_125;
324                 break;
325         case IFM_100_TX:
326                 reg = SOC_CON5_GMAC_CLK_SEL_25;
327                 break;
328         case IFM_10_T:
329                 reg = SOC_CON5_GMAC_CLK_SEL_2_5;
330                 break;
331         default:
332                 device_printf(sc->base.dev, "unsupported media %u\n", speed);
333                 return (-1);
334         }
335
336         SYSCON_WRITE_4(sc->grf, RK3399_GRF_SOC_CON5,
337             ((SOC_CON5_GMAC_CLK_SEL_MASK << 16) | reg));
338         return (0);
339 }
340
341 static int
342 if_dwc_rk_sysctl_delays(SYSCTL_HANDLER_ARGS)
343 {
344         struct if_dwc_rk_softc *sc;
345         int rv;
346         uint32_t rxtx;
347
348         sc = arg1;
349         rxtx = ((sc->rx_delay << 8) | sc->tx_delay);
350
351         rv = sysctl_handle_int(oidp, &rxtx, 0, req);
352         if (rv != 0 || req->newptr == NULL)
353                 return (rv);
354         sc->tx_delay = rxtx & 0xff;
355         sc->rx_delay = (rxtx >> 8) & 0xff;
356
357         if (sc->ops->set_delays)
358             sc->ops->set_delays(sc);
359
360         return (0);
361 }
362
363 static int
364 if_dwc_rk_init_sysctl(struct if_dwc_rk_softc *sc)
365 {
366         struct sysctl_oid *child;
367         struct sysctl_ctx_list *ctx_list;
368
369         ctx_list = device_get_sysctl_ctx(sc->base.dev);
370         child = device_get_sysctl_tree(sc->base.dev);
371         SYSCTL_ADD_PROC(ctx_list,
372             SYSCTL_CHILDREN(child), OID_AUTO, "delays",
373             CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, sc, 0,
374             if_dwc_rk_sysctl_delays, "", "RGMII RX/TX delays: ((rx << 8) | tx)");
375
376         return (0);
377 }
378
379 static int
380 if_dwc_rk_probe(device_t dev)
381 {
382
383         if (!ofw_bus_status_okay(dev))
384                 return (ENXIO);
385         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
386                 return (ENXIO);
387         device_set_desc(dev, "Rockchip Gigabit Ethernet Controller");
388
389         return (BUS_PROBE_DEFAULT);
390 }
391
392 static int
393 if_dwc_rk_init_clocks(device_t dev)
394 {
395         struct if_dwc_rk_softc *sc;
396         int error;
397
398         sc = device_get_softc(dev);
399         error = clk_set_assigned(dev, ofw_bus_get_node(dev));
400         if (error != 0) {
401                 device_printf(dev, "clk_set_assigned failed\n");
402                 return (error);
403         }
404
405         /* Enable clocks */
406         error = clk_get_by_ofw_name(dev, 0, "stmmaceth", &sc->clk_stmmaceth);
407         if (error != 0) {
408                 device_printf(dev, "could not find clock stmmaceth\n");
409                 return (error);
410         }
411
412         if (clk_get_by_ofw_name(dev, 0, "mac_clk_rx", &sc->mac_clk_rx) != 0) {
413                 device_printf(sc->base.dev, "could not get mac_clk_rx clock\n");
414                 sc->mac_clk_rx = NULL;
415         }
416
417         if (clk_get_by_ofw_name(dev, 0, "mac_clk_tx", &sc->mac_clk_tx) != 0) {
418                 device_printf(sc->base.dev, "could not get mac_clk_tx clock\n");
419                 sc->mac_clk_tx = NULL;
420         }
421
422         if (clk_get_by_ofw_name(dev, 0, "aclk_mac", &sc->aclk_mac) != 0) {
423                 device_printf(sc->base.dev, "could not get aclk_mac clock\n");
424                 sc->aclk_mac = NULL;
425         }
426
427         if (clk_get_by_ofw_name(dev, 0, "pclk_mac", &sc->pclk_mac) != 0) {
428                 device_printf(sc->base.dev, "could not get pclk_mac clock\n");
429                 sc->pclk_mac = NULL;
430         }
431
432         if (sc->base.phy_mode == PHY_MODE_RGMII) {
433                 if (clk_get_by_ofw_name(dev, 0, "clk_mac_ref", &sc->clk_mac_ref) != 0) {
434                         device_printf(sc->base.dev, "could not get clk_mac_ref clock\n");
435                         sc->clk_mac_ref = NULL;
436                 }
437
438                 if (!sc->clock_in) {
439                         if (clk_get_by_ofw_name(dev, 0, "clk_mac_refout", &sc->clk_mac_refout) != 0) {
440                                 device_printf(sc->base.dev, "could not get clk_mac_refout clock\n");
441                                 sc->clk_mac_refout = NULL;
442                         }
443
444                         clk_set_freq(sc->clk_stmmaceth, 50000000, 0);
445                 }
446         }
447
448         if ((sc->phy_node != 0) && sc->integrated_phy) {
449                 if (clk_get_by_ofw_index(dev, sc->phy_node, 0, &sc->clk_phy) != 0) {
450                         device_printf(sc->base.dev, "could not get PHY clock\n");
451                         sc->clk_phy = NULL;
452                 }
453
454                 if (sc->clk_phy) {
455                         clk_set_freq(sc->clk_phy, 50000000, 0);
456                 }
457         }
458
459         if (sc->base.phy_mode == PHY_MODE_RMII) {
460                 if (sc->mac_clk_rx)
461                         clk_enable(sc->mac_clk_rx);
462                 if (sc->clk_mac_ref)
463                         clk_enable(sc->clk_mac_ref);
464                 if (sc->clk_mac_refout)
465                         clk_enable(sc->clk_mac_refout);
466         }
467         if (sc->clk_phy)
468                 clk_enable(sc->clk_phy);
469         if (sc->aclk_mac)
470                 clk_enable(sc->aclk_mac);
471         if (sc->pclk_mac)
472                 clk_enable(sc->pclk_mac);
473         if (sc->mac_clk_tx)
474                 clk_enable(sc->mac_clk_tx);
475
476         DELAY(50);
477
478         return (0);
479 }
480
481 static int
482 if_dwc_rk_init(device_t dev)
483 {
484         struct if_dwc_rk_softc *sc;
485         phandle_t node;
486         uint32_t rx, tx;
487         int err;
488         pcell_t phy_handle;
489         char *clock_in_out;
490         hwreset_t phy_reset;
491         regulator_t phy_supply;
492
493         sc = device_get_softc(dev);
494         node = ofw_bus_get_node(dev);
495         sc->ops = (struct if_dwc_rk_ops *)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
496         if (OF_hasprop(node, "rockchip,grf") &&
497             syscon_get_by_ofw_property(dev, node,
498             "rockchip,grf", &sc->grf) != 0) {
499                 device_printf(dev, "cannot get grf driver handle\n");
500                 return (ENXIO);
501         }
502
503         if (OF_getencprop(node, "tx_delay", &tx, sizeof(tx)) <= 0)
504                 tx = 0x30;
505         if (OF_getencprop(node, "rx_delay", &rx, sizeof(rx)) <= 0)
506                 rx = 0x10;
507         sc->tx_delay = tx;
508         sc->rx_delay = rx;
509
510         sc->clock_in = true;
511         if (OF_getprop_alloc(node, "clock_in_out", (void **)&clock_in_out)) {
512                 if (strcmp(clock_in_out, "input") == 0)
513                         sc->clock_in = true;
514                 else
515                         sc->clock_in = false;
516                 OF_prop_free(clock_in_out);
517         }
518
519         if (OF_getencprop(node, "phy-handle", (void *)&phy_handle,
520             sizeof(phy_handle)) > 0)
521                 sc->phy_node = OF_node_from_xref(phy_handle);
522
523         if (sc->phy_node)
524                 sc->integrated_phy = OF_hasprop(sc->phy_node, "phy-is-integrated");
525
526         if (sc->integrated_phy)
527                 device_printf(sc->base.dev, "PHY is integrated\n");
528
529         if_dwc_rk_init_clocks(dev);
530
531         if (sc->ops->set_phy_mode)
532             sc->ops->set_phy_mode(sc);
533
534         if (sc->ops->set_delays)
535             sc->ops->set_delays(sc);
536
537         /*
538          * this also sets delays if tunable is defined
539          */
540         err = if_dwc_rk_init_sysctl(sc);
541         if (err != 0)
542                 return (err);
543
544         if (regulator_get_by_ofw_property(sc->base.dev, 0,
545                             "phy-supply", &phy_supply) == 0) {
546                 if (regulator_enable(phy_supply)) {
547                         device_printf(sc->base.dev,
548                             "cannot enable 'phy' regulator\n");
549                 }
550         }
551         else
552                 device_printf(sc->base.dev, "no phy-supply property\n");
553
554         /* Power up */
555         if (sc->integrated_phy) {
556                 if (sc->ops->phy_powerup)
557                         sc->ops->phy_powerup(sc);
558
559                 SYSCON_WRITE_4(sc->grf, RK3328_GRF_MACPHY_CON0,
560                     (MACPHY_CON0_CLK_50M_MASK << 16) |
561                     MACPHY_CON0_CLK_50M);
562                 SYSCON_WRITE_4(sc->grf, RK3328_GRF_MACPHY_CON0,
563                     (MACPHY_CON0_RMII_MODE_MASK << 16) |
564                     MACPHY_CON0_RMII_MODE);
565                 SYSCON_WRITE_4(sc->grf, RK3328_GRF_MACPHY_CON2, 0xffff1234);
566                 SYSCON_WRITE_4(sc->grf, RK3328_GRF_MACPHY_CON3, 0x003f0035);
567
568                 if (hwreset_get_by_ofw_idx(dev, sc->phy_node, 0, &phy_reset)  == 0) {
569                         hwreset_assert(phy_reset);
570                         DELAY(20);
571                         hwreset_deassert(phy_reset);
572                         DELAY(20);
573                 }
574         }
575
576         return (0);
577 }
578
579 static int
580 if_dwc_rk_mac_type(device_t dev)
581 {
582
583         return (DWC_GMAC_NORMAL_DESC);
584 }
585
586 static int
587 if_dwc_rk_mii_clk(device_t dev)
588 {
589
590         /* Should be calculated from the clock */
591         return (GMAC_MII_CLK_150_250M_DIV102);
592 }
593
594 static int
595 if_dwc_rk_set_speed(device_t dev, int speed)
596 {
597         struct if_dwc_rk_softc *sc;
598
599         sc = device_get_softc(dev);
600
601         if (sc->ops->set_speed)
602             return sc->ops->set_speed(sc, speed);
603
604         return (0);
605 }
606
607 static device_method_t if_dwc_rk_methods[] = {
608         DEVMETHOD(device_probe,         if_dwc_rk_probe),
609
610         DEVMETHOD(if_dwc_init,          if_dwc_rk_init),
611         DEVMETHOD(if_dwc_mac_type,      if_dwc_rk_mac_type),
612         DEVMETHOD(if_dwc_mii_clk,       if_dwc_rk_mii_clk),
613         DEVMETHOD(if_dwc_set_speed,     if_dwc_rk_set_speed),
614
615         DEVMETHOD_END
616 };
617
618 static devclass_t dwc_rk_devclass;
619
620 extern driver_t dwc_driver;
621
622 DEFINE_CLASS_1(dwc, dwc_rk_driver, if_dwc_rk_methods,
623     sizeof(struct if_dwc_rk_softc), dwc_driver);
624 DRIVER_MODULE(dwc_rk, simplebus, dwc_rk_driver, dwc_rk_devclass, 0, 0);
625 MODULE_DEPEND(dwc_rk, dwc, 1, 1, 1);