1 /* $OpenBSD: if_dwqe_fdt.c,v 1.18 2024/02/26 18:57:50 kettenis Exp $ */
2 /*
3 * Copyright (c) 2008, 2019 Mark Kettenis <kettenis@openbsd.org>
4 * Copyright (c) 2017, 2022 Patrick Wildt <patrick@blueri.se>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /*
20 * Driver for the Synopsys Designware ethernet controller.
21 */
22
23 #include "bpfilter.h"
24
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/device.h>
28 #include <sys/kernel.h>
29 #include <sys/malloc.h>
30 #include <sys/mbuf.h>
31 #include <sys/queue.h>
32 #include <sys/socket.h>
33 #include <sys/sockio.h>
34 #include <sys/timeout.h>
35 #include <sys/task.h>
36
37 #include <machine/bus.h>
38 #include <machine/fdt.h>
39
40 #include <net/if.h>
41 #include <net/if_media.h>
42
43 #include <dev/ofw/openfirm.h>
44 #include <dev/ofw/ofw_clock.h>
45 #include <dev/ofw/ofw_gpio.h>
46 #include <dev/ofw/ofw_misc.h>
47 #include <dev/ofw/ofw_pinctrl.h>
48 #include <dev/ofw/ofw_regulator.h>
49 #include <dev/ofw/fdt.h>
50
51 #include <dev/mii/mii.h>
52 #include <dev/mii/miivar.h>
53
54 #if NBPFILTER > 0
55 #include <net/bpf.h>
56 #endif
57
58 #include <netinet/in.h>
59 #include <netinet/if_ether.h>
60
61 #include <dev/ic/dwqevar.h>
62 #include <dev/ic/dwqereg.h>
63
64 struct dwqe_fdt_softc {
65 struct dwqe_softc sc_sc;
66 struct if_device sc_ifd;
67 int sc_gmac_id;
68 };
69
70 int dwqe_fdt_match(struct device *, void *, void *);
71 void dwqe_fdt_attach(struct device *, struct device *, void *);
72 void dwqe_setup_jh7110(struct dwqe_softc *);
73 void dwqe_mii_statchg_jh7110(struct device *);
74 void dwqe_setup_rk3568(struct dwqe_fdt_softc *);
75 void dwqe_mii_statchg_rk3568(struct device *);
76 void dwqe_setup_rk3588(struct dwqe_fdt_softc *);
77 void dwqe_mii_statchg_rk3588(struct device *);
78
79 const struct cfattach dwqe_fdt_ca = {
80 sizeof(struct dwqe_fdt_softc), dwqe_fdt_match, dwqe_fdt_attach
81 };
82
83 void dwqe_reset_phy(struct dwqe_softc *, uint32_t);
84
85 int
dwqe_fdt_match(struct device * parent,void * cfdata,void * aux)86 dwqe_fdt_match(struct device *parent, void *cfdata, void *aux)
87 {
88 struct fdt_attach_args *faa = aux;
89
90 return OF_is_compatible(faa->fa_node, "snps,dwmac-4.20a") ||
91 OF_is_compatible(faa->fa_node, "snps,dwmac-5.20");
92 }
93
94 void
dwqe_fdt_attach(struct device * parent,struct device * self,void * aux)95 dwqe_fdt_attach(struct device *parent, struct device *self, void *aux)
96 {
97 struct dwqe_fdt_softc *fsc = (void *)self;
98 struct dwqe_softc *sc = &fsc->sc_sc;
99 struct fdt_attach_args *faa = aux;
100 char phy_mode[16] = { 0 };
101 uint32_t phy, phy_supply;
102 uint32_t axi_config;
103 struct ifnet *ifp = &sc->sc_ac.ac_if;
104 int i, node;
105
106 sc->sc_node = faa->fa_node;
107 sc->sc_iot = faa->fa_iot;
108 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
109 faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
110 printf(": cannot map registers\n");
111 return;
112 }
113 sc->sc_dmat = faa->fa_dmat;
114
115 /* Decide GMAC id through address */
116 switch (faa->fa_reg[0].addr) {
117 case 0xfe2a0000: /* RK3568 */
118 case 0xfe1b0000: /* RK3588 */
119 case 0x16030000: /* JH7110 */
120 fsc->sc_gmac_id = 0;
121 break;
122 case 0xfe010000: /* RK3568 */
123 case 0xfe1c0000: /* RK3588 */
124 case 0x16040000: /* JH7110 */
125 fsc->sc_gmac_id = 1;
126 break;
127 default:
128 printf(": unknown controller at 0x%llx\n", faa->fa_reg[0].addr);
129 return;
130 }
131
132 printf(" gmac %d", fsc->sc_gmac_id);
133
134 OF_getprop(faa->fa_node, "phy-mode", phy_mode, sizeof(phy_mode));
135 if (strcmp(phy_mode, "rgmii") == 0)
136 sc->sc_phy_mode = DWQE_PHY_MODE_RGMII;
137 else if (strcmp(phy_mode, "rgmii-rxid") == 0)
138 sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_RXID;
139 else if (strcmp(phy_mode, "rgmii-txid") == 0)
140 sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_TXID;
141 else if (strcmp(phy_mode, "rgmii-id") == 0)
142 sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_ID;
143 else if (strcmp(phy_mode, "rmii") == 0)
144 sc->sc_phy_mode = DWQE_PHY_MODE_RMII;
145 else
146 sc->sc_phy_mode = DWQE_PHY_MODE_UNKNOWN;
147
148 /* Lookup PHY. */
149 phy = OF_getpropint(faa->fa_node, "phy", 0);
150 if (phy == 0)
151 phy = OF_getpropint(faa->fa_node, "phy-handle", 0);
152 node = OF_getnodebyphandle(phy);
153 if (node)
154 sc->sc_phyloc = OF_getpropint(node, "reg", MII_PHY_ANY);
155 else
156 sc->sc_phyloc = MII_PHY_ANY;
157 sc->sc_mii.mii_node = node;
158
159 pinctrl_byname(faa->fa_node, "default");
160
161 /* Enable clocks. */
162 clock_set_assigned(faa->fa_node);
163 clock_enable(faa->fa_node, "stmmaceth");
164 clock_enable(faa->fa_node, "pclk");
165 reset_deassert(faa->fa_node, "stmmaceth");
166 reset_deassert(faa->fa_node, "ahb");
167 if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac")) {
168 clock_enable(faa->fa_node, "tx");
169 clock_enable(faa->fa_node, "gtx");
170 } else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac") ||
171 OF_is_compatible(faa->fa_node, "rockchip,rk3588-gmac")) {
172 clock_enable(faa->fa_node, "aclk_mac");
173 clock_enable(faa->fa_node, "pclk_mac");
174 clock_enable(faa->fa_node, "mac_clk_tx");
175 clock_enable(faa->fa_node, "clk_mac_speed");
176 if (strcmp(phy_mode, "rmii") == 0) {
177 clock_enable(faa->fa_node, "mac_clk_rx");
178 clock_enable(faa->fa_node, "clk_mac_ref");
179 clock_enable(faa->fa_node, "clk_mac_refout");
180 }
181 }
182 delay(5000);
183
184 /* Do hardware specific initializations. */
185 if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac"))
186 dwqe_setup_jh7110(sc);
187 else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac"))
188 dwqe_setup_rk3568(fsc);
189 else if (OF_is_compatible(faa->fa_node, "rockchip,rk3588-gmac"))
190 dwqe_setup_rk3588(fsc);
191
192 /* Power up PHY. */
193 phy_supply = OF_getpropint(faa->fa_node, "phy-supply", 0);
194 if (phy_supply)
195 regulator_enable(phy_supply);
196
197 /* Reset PHY */
198 dwqe_reset_phy(sc, phy);
199
200 node = OF_getnodebyname(sc->sc_node, "fixed-link");
201 if (node) {
202 sc->sc_fixed_link = 1;
203
204 ifp->if_baudrate = IF_Mbps(OF_getpropint(node, "speed", 0));
205 ifp->if_link_state = OF_getpropbool(node, "full-duplex") ?
206 LINK_STATE_FULL_DUPLEX : LINK_STATE_HALF_DUPLEX;
207 }
208
209 sc->sc_clkrate = clock_get_frequency(faa->fa_node, "stmmaceth");
210 if (sc->sc_clkrate > 500000000)
211 sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_500_800;
212 else if (sc->sc_clkrate > 300000000)
213 sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_300_500;
214 else if (sc->sc_clkrate > 150000000)
215 sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_150_250;
216 else if (sc->sc_clkrate > 100000000)
217 sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_100_150;
218 else if (sc->sc_clkrate > 60000000)
219 sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_60_100;
220 else if (sc->sc_clkrate > 35000000)
221 sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_35_60;
222 else
223 sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_20_35;
224
225 for (i = 0; i < 4; i++)
226 sc->sc_hw_feature[i] = dwqe_read(sc, GMAC_MAC_HW_FEATURE(i));
227
228 if (OF_getprop(faa->fa_node, "local-mac-address",
229 &sc->sc_lladdr, ETHER_ADDR_LEN) != ETHER_ADDR_LEN)
230 dwqe_lladdr_read(sc, sc->sc_lladdr);
231
232 sc->sc_force_thresh_dma_mode =
233 OF_getpropbool(faa->fa_node, "snps,force_thresh_dma_mode");
234
235 dwqe_reset(sc);
236
237 sc->sc_fixed_burst = OF_getpropbool(faa->fa_node, "snps,fixed-burst");
238 sc->sc_mixed_burst = OF_getpropbool(faa->fa_node, "snps,mixed-burst");
239 sc->sc_aal = OF_getpropbool(faa->fa_node, "snps,aal");
240 sc->sc_8xpbl = !OF_getpropbool(faa->fa_node, "snps,no-pbl-x8");
241 sc->sc_pbl = OF_getpropint(faa->fa_node, "snps,pbl", 8);
242 sc->sc_txpbl = OF_getpropint(faa->fa_node, "snps,txpbl", sc->sc_pbl);
243 sc->sc_rxpbl = OF_getpropint(faa->fa_node, "snps,rxpbl", sc->sc_pbl);
244
245 /* Configure AXI master. */
246 axi_config = OF_getpropint(faa->fa_node, "snps,axi-config", 0);
247 node = OF_getnodebyphandle(axi_config);
248 if (node) {
249 sc->sc_axi_config = 1;
250 sc->sc_lpi_en = OF_getpropbool(node, "snps,lpi_en");
251 sc->sc_xit_frm = OF_getpropbool(node, "snps,xit_frm");
252
253 sc->sc_wr_osr_lmt = OF_getpropint(node, "snps,wr_osr_lmt", 1);
254 sc->sc_rd_osr_lmt = OF_getpropint(node, "snps,rd_osr_lmt", 1);
255
256 OF_getpropintarray(node, "snps,blen", sc->sc_blen, sizeof(sc->sc_blen));
257 }
258
259 if (dwqe_attach(sc) != 0)
260 return;
261
262 if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac") &&
263 !OF_getpropbool(faa->fa_node, "starfive,tx-use-rgmii-clk"))
264 sc->sc_mii.mii_statchg = dwqe_mii_statchg_jh7110;
265 else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac"))
266 sc->sc_mii.mii_statchg = dwqe_mii_statchg_rk3568;
267 else if (OF_is_compatible(faa->fa_node, "rockchip,rk3588-gmac"))
268 sc->sc_mii.mii_statchg = dwqe_mii_statchg_rk3588;
269
270 sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_NET | IPL_MPSAFE,
271 dwqe_intr, sc, sc->sc_dev.dv_xname);
272 if (sc->sc_ih == NULL)
273 printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname);
274
275 fsc->sc_ifd.if_node = faa->fa_node;
276 fsc->sc_ifd.if_ifp = ifp;
277 if_register(&fsc->sc_ifd);
278
279 /* force a configuration of the clocks/mac */
280 if (sc->sc_fixed_link)
281 sc->sc_mii.mii_statchg(self);
282 }
283
284 void
dwqe_reset_phy(struct dwqe_softc * sc,uint32_t phy)285 dwqe_reset_phy(struct dwqe_softc *sc, uint32_t phy)
286 {
287 uint32_t *gpio;
288 uint32_t delays[3];
289 int active = 1;
290 int node, len;
291
292 node = OF_getnodebyphandle(phy);
293 if (node && OF_getproplen(node, "reset-gpios") > 0) {
294 len = OF_getproplen(node, "reset-gpios");
295
296 gpio = malloc(len, M_TEMP, M_WAITOK);
297
298 /* Gather information. */
299 OF_getpropintarray(node, "reset-gpios", gpio, len);
300 delays[0] = OF_getpropint(node, "reset-deassert-us", 0);
301 delays[1] = OF_getpropint(node, "reset-assert-us", 0);
302 delays[2] = OF_getpropint(node, "reset-deassert-us", 0);
303 } else {
304 len = OF_getproplen(sc->sc_node, "snps,reset-gpio");
305 if (len <= 0)
306 return;
307
308 gpio = malloc(len, M_TEMP, M_WAITOK);
309
310 /* Gather information. */
311 OF_getpropintarray(sc->sc_node, "snps,reset-gpio", gpio, len);
312 if (OF_getpropbool(sc->sc_node, "snps-reset-active-low"))
313 active = 0;
314 delays[0] = delays[1] = delays[2] = 0;
315 OF_getpropintarray(sc->sc_node, "snps,reset-delays-us", delays,
316 sizeof(delays));
317 }
318
319 /* Perform reset sequence. */
320 gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT);
321 gpio_controller_set_pin(gpio, !active);
322 delay(delays[0]);
323 gpio_controller_set_pin(gpio, active);
324 delay(delays[1]);
325 gpio_controller_set_pin(gpio, !active);
326 delay(delays[2]);
327
328 free(gpio, M_TEMP, len);
329 }
330
331 /* JH7110 registers */
332 #define JH7110_PHY_INTF_RGMII 1
333 #define JH7110_PHY_INTF_RMII 4
334
335 /* RK3568 registers */
336 #define RK3568_GRF_GMACx_CON0(x) (0x0380 + (x) * 0x8)
337 #define RK3568_GMAC_CLK_RX_DL_CFG(val) ((0x7f << 8) << 16 | ((val) << 8))
338 #define RK3568_GMAC_CLK_TX_DL_CFG(val) ((0x7f << 0) << 16 | ((val) << 0))
339 #define RK3568_GRF_GMACx_CON1(x) (0x0384 + (x) * 0x8)
340 #define RK3568_GMAC_PHY_INTF_SEL_RGMII ((0x7 << 4) << 16 | (0x1 << 4))
341 #define RK3568_GMAC_PHY_INTF_SEL_RMII ((0x7 << 4) << 16 | (0x4 << 4))
342 #define RK3568_GMAC_TXCLK_DLY_SET(_v) ((1 << 0) << 16 | ((_v) << 0))
343 #define RK3568_GMAC_RXCLK_DLY_SET(_v) ((1 << 1) << 16 | ((_v) << 1))
344
345 /* RK3588 registers */
346 #define RK3588_GRF_GMAC_CON7 0x031c
347 #define RK3588_GMACx_RXCLK_DLY_ENA(id) ((1 << (2 * (id) + 3)) << 16 | (1 << (2 * (id) + 3)))
348 #define RK3588_GMACx_TXCLK_DLY_ENA(id) ((1 << (2 * (id) + 2)) << 16 | (1 << (2 * (id) + 2)))
349 #define RK3588_GRF_GMAC_CON8 0x0320
350 #define RK3588_GRF_GMAC_CON9 0x0324
351 #define RK3588_GMAC_CLK_RX_DL_CFG(val) ((0x7f << 8) << 16 | ((val) << 8))
352 #define RK3588_GMAC_CLK_TX_DL_CFG(val) ((0x7f << 0) << 16 | ((val) << 0))
353 #define RK3588_PHP_GRF_GMAC_CON0 0x0008
354 #define RK3588_GMACx_PHY_INTF_SEL_RGMII(id) ((0x7 << (6 * (id) + 3)) << 16 | (0x1 << (6 * (id) + 3)))
355 #define RK3588_GMACx_PHY_INTF_SEL_RMII(id) ((0x7 << (6 * (id) + 3)) << 16 | (0x4 << (6 * (id) + 3)))
356 #define RK3588_PHP_GRF_CLK_CON1 0x0070
357 #define RK3588_RMII_MODE_GMACx_RMII(id) ((0x1 << (5 * (id))) << 16 | (0x1 << (5 * (id))))
358 #define RK3588_RMII_MODE_GMACx_RGMII(id) ((0x1 << (5 * (id))) << 16 | (0x0 << (5 * (id))))
359 #define RK3588_MII_TX_CLK_SEL_RMII_2_5(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x1 << (5 * (id) + 2)))
360 #define RK3588_MII_TX_CLK_SEL_RMII_25(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x0 << (5 * (id) + 2)))
361 #define RK3588_MII_TX_CLK_SEL_RGMII_2_5(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x2 << (5 * (id) + 2)))
362 #define RK3588_MII_TX_CLK_SEL_RGMII_25(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x3 << (5 * (id) + 2)))
363 #define RK3588_MII_TX_CLK_SEL_RGMII_125(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x0 << (5 * (id) + 2)))
364
365 void dwqe_mii_statchg_jh7110_task(void *);
366 void dwqe_mii_statchg_rk3568_task(void *);
367
368 void
dwqe_setup_jh7110(struct dwqe_softc * sc)369 dwqe_setup_jh7110(struct dwqe_softc *sc)
370 {
371 struct regmap *rm;
372 uint32_t cells[3];
373 uint32_t phandle, offset, reg, shift;
374 char phy_mode[32];
375 uint32_t iface;
376
377 if (OF_getpropintarray(sc->sc_node, "starfive,syscon", cells,
378 sizeof(cells)) != sizeof(cells)) {
379 printf("%s: failed to get starfive,syscon\n", __func__);
380 return;
381 }
382 phandle = cells[0];
383 offset = cells[1];
384 shift = cells[2];
385
386 rm = regmap_byphandle(phandle);
387 if (rm == NULL) {
388 printf("%s: failed to get regmap\n", __func__);
389 return;
390 }
391
392 if (OF_getprop(sc->sc_node, "phy-mode", phy_mode,
393 sizeof(phy_mode)) <= 0)
394 return;
395
396 if (strcmp(phy_mode, "rgmii") == 0 ||
397 strcmp(phy_mode, "rgmii-id") == 0) {
398 iface = JH7110_PHY_INTF_RGMII;
399 } else if (strcmp(phy_mode, "rmii") == 0) {
400 iface = JH7110_PHY_INTF_RMII;
401 } else
402 return;
403
404 reg = regmap_read_4(rm, offset);
405 reg &= ~(((1U << 3) - 1) << shift);
406 reg |= iface << shift;
407 regmap_write_4(rm, offset, reg);
408
409 task_set(&sc->sc_statchg_task,
410 dwqe_mii_statchg_jh7110_task, sc);
411 }
412
413 void
dwqe_mii_statchg_jh7110_task(void * arg)414 dwqe_mii_statchg_jh7110_task(void *arg)
415 {
416 struct dwqe_softc *sc = arg;
417 struct ifnet *ifp = &sc->sc_ac.ac_if;
418
419 dwqe_mii_statchg(&sc->sc_dev);
420
421 switch (ifp->if_baudrate) {
422 case IF_Mbps(10):
423 clock_set_frequency(sc->sc_node, "tx", 2500000);
424 break;
425 case IF_Mbps(100):
426 clock_set_frequency(sc->sc_node, "tx", 25000000);
427 break;
428 case IF_Mbps(1000):
429 clock_set_frequency(sc->sc_node, "tx", 125000000);
430 break;
431 }
432 }
433
434 void
dwqe_mii_statchg_jh7110(struct device * self)435 dwqe_mii_statchg_jh7110(struct device *self)
436 {
437 struct dwqe_softc *sc = (void *)self;
438
439 task_add(systq, &sc->sc_statchg_task);
440 }
441
442 void
dwqe_setup_rk3568(struct dwqe_fdt_softc * fsc)443 dwqe_setup_rk3568(struct dwqe_fdt_softc *fsc)
444 {
445 struct dwqe_softc *sc = &fsc->sc_sc;
446 struct regmap *rm;
447 uint32_t grf;
448 int tx_delay, rx_delay;
449 uint32_t iface;
450
451 grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
452 rm = regmap_byphandle(grf);
453 if (rm == NULL)
454 return;
455
456 switch (sc->sc_phy_mode) {
457 case DWQE_PHY_MODE_RGMII:
458 case DWQE_PHY_MODE_RGMII_ID:
459 case DWQE_PHY_MODE_RGMII_RXID:
460 case DWQE_PHY_MODE_RGMII_TXID:
461 iface = RK3568_GMAC_PHY_INTF_SEL_RGMII;
462 break;
463 case DWQE_PHY_MODE_RMII:
464 iface = RK3568_GMAC_PHY_INTF_SEL_RMII;
465 break;
466 default:
467 return;
468 }
469
470 tx_delay = OF_getpropint(sc->sc_node, "tx_delay", 0x30);
471 rx_delay = OF_getpropint(sc->sc_node, "rx_delay", 0x10);
472 switch (sc->sc_phy_mode) {
473 case DWQE_PHY_MODE_RGMII_ID:
474 tx_delay = rx_delay = 0;
475 break;
476 case DWQE_PHY_MODE_RGMII_RXID:
477 rx_delay = 0;
478 break;
479 case DWQE_PHY_MODE_RGMII_TXID:
480 tx_delay = 0;
481 break;
482 default:
483 break;
484 }
485
486 /* Program clock delay lines. */
487 regmap_write_4(rm, RK3568_GRF_GMACx_CON0(fsc->sc_gmac_id),
488 RK3568_GMAC_CLK_TX_DL_CFG(tx_delay) |
489 RK3568_GMAC_CLK_RX_DL_CFG(rx_delay));
490
491 /* Set interface and enable/disable clock delay. */
492 regmap_write_4(rm, RK3568_GRF_GMACx_CON1(fsc->sc_gmac_id), iface |
493 RK3568_GMAC_TXCLK_DLY_SET(tx_delay > 0 ? 1 : 0) |
494 RK3568_GMAC_RXCLK_DLY_SET(rx_delay > 0 ? 1 : 0));
495
496 task_set(&sc->sc_statchg_task,
497 dwqe_mii_statchg_rk3568_task, sc);
498 }
499
500 void
dwqe_mii_statchg_rk3568_task(void * arg)501 dwqe_mii_statchg_rk3568_task(void *arg)
502 {
503 struct dwqe_softc *sc = arg;
504 struct ifnet *ifp = &sc->sc_ac.ac_if;
505
506 dwqe_mii_statchg(&sc->sc_dev);
507
508 switch (ifp->if_baudrate) {
509 case IF_Mbps(10):
510 clock_set_frequency(sc->sc_node, "clk_mac_speed", 2500000);
511 break;
512 case IF_Mbps(100):
513 clock_set_frequency(sc->sc_node, "clk_mac_speed", 25000000);
514 break;
515 case IF_Mbps(1000):
516 clock_set_frequency(sc->sc_node, "clk_mac_speed", 125000000);
517 break;
518 }
519 }
520
521 void
dwqe_mii_statchg_rk3568(struct device * self)522 dwqe_mii_statchg_rk3568(struct device *self)
523 {
524 struct dwqe_softc *sc = (void *)self;
525
526 task_add(systq, &sc->sc_statchg_task);
527 }
528
529 void
dwqe_setup_rk3588(struct dwqe_fdt_softc * fsc)530 dwqe_setup_rk3588(struct dwqe_fdt_softc *fsc)
531 {
532 struct dwqe_softc *sc = &fsc->sc_sc;
533 struct regmap *rm;
534 struct regmap *php_rm;
535 uint32_t grf, php_grf;
536 int tx_delay, rx_delay;
537 uint32_t iface, clk;
538
539 grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
540 rm = regmap_byphandle(grf);
541 if (rm == NULL)
542 return;
543
544 php_grf = OF_getpropint(sc->sc_node, "rockchip,php-grf", 0);
545 php_rm = regmap_byphandle(php_grf);
546 if (php_rm == NULL)
547 return;
548
549 switch (sc->sc_phy_mode) {
550 case DWQE_PHY_MODE_RGMII:
551 case DWQE_PHY_MODE_RGMII_ID:
552 case DWQE_PHY_MODE_RGMII_RXID:
553 case DWQE_PHY_MODE_RGMII_TXID:
554 iface = RK3588_GMACx_PHY_INTF_SEL_RGMII(fsc->sc_gmac_id);
555 clk = RK3588_RMII_MODE_GMACx_RGMII(fsc->sc_gmac_id);
556 sc->sc_clk_sel_2_5 =
557 RK3588_MII_TX_CLK_SEL_RGMII_2_5(fsc->sc_gmac_id);
558 sc->sc_clk_sel_25 =
559 RK3588_MII_TX_CLK_SEL_RGMII_25(fsc->sc_gmac_id);
560 sc->sc_clk_sel_125 =
561 RK3588_MII_TX_CLK_SEL_RGMII_125(fsc->sc_gmac_id);
562 break;
563 case DWQE_PHY_MODE_RMII:
564 iface = RK3588_GMACx_PHY_INTF_SEL_RMII(fsc->sc_gmac_id);
565 clk = RK3588_RMII_MODE_GMACx_RMII(fsc->sc_gmac_id);
566 sc->sc_clk_sel_2_5 =
567 RK3588_MII_TX_CLK_SEL_RMII_2_5(fsc->sc_gmac_id);
568 sc->sc_clk_sel_25 =
569 RK3588_MII_TX_CLK_SEL_RMII_25(fsc->sc_gmac_id);
570 break;
571 default:
572 return;
573 }
574
575 tx_delay = OF_getpropint(sc->sc_node, "tx_delay", 0x30);
576 rx_delay = OF_getpropint(sc->sc_node, "rx_delay", 0x10);
577 switch (sc->sc_phy_mode) {
578 case DWQE_PHY_MODE_RGMII_ID:
579 tx_delay = rx_delay = 0;
580 break;
581 case DWQE_PHY_MODE_RGMII_RXID:
582 rx_delay = 0;
583 break;
584 case DWQE_PHY_MODE_RGMII_TXID:
585 tx_delay = 0;
586 break;
587 default:
588 break;
589 }
590
591 /* Set interface and clock. */
592 regmap_write_4(php_rm, RK3588_PHP_GRF_GMAC_CON0, iface);
593 regmap_write_4(php_rm, RK3588_PHP_GRF_CLK_CON1, clk);
594
595 /* Enable clock delay. */
596 regmap_write_4(rm, RK3588_GRF_GMAC_CON7,
597 RK3588_GMACx_TXCLK_DLY_ENA(fsc->sc_gmac_id) |
598 RK3588_GMACx_RXCLK_DLY_ENA(fsc->sc_gmac_id));
599
600 /* Program clock delay lines. */
601 regmap_write_4(rm, fsc->sc_gmac_id == 1 ?
602 RK3588_GRF_GMAC_CON9 : RK3588_GRF_GMAC_CON8,
603 RK3588_GMAC_CLK_TX_DL_CFG(tx_delay) |
604 RK3588_GMAC_CLK_RX_DL_CFG(rx_delay));
605 }
606
607 void
dwqe_mii_statchg_rk3588(struct device * self)608 dwqe_mii_statchg_rk3588(struct device *self)
609 {
610 struct dwqe_softc *sc = (void *)self;
611 struct ifnet *ifp = &sc->sc_ac.ac_if;
612 struct regmap *php_rm;
613 uint32_t php_grf;
614 uint32_t gmac_clk_sel = 0;
615
616 dwqe_mii_statchg(self);
617
618 php_grf = OF_getpropint(sc->sc_node, "rockchip,php-grf", 0);
619 php_rm = regmap_byphandle(php_grf);
620 if (php_rm == NULL)
621 return;
622
623 switch (ifp->if_baudrate) {
624 case IF_Mbps(10):
625 gmac_clk_sel = sc->sc_clk_sel_2_5;
626 break;
627 case IF_Mbps(100):
628 gmac_clk_sel = sc->sc_clk_sel_25;
629 break;
630 case IF_Mbps(1000):
631 gmac_clk_sel = sc->sc_clk_sel_125;
632 break;
633 }
634
635 regmap_write_4(php_rm, RK3588_PHP_GRF_CLK_CON1, gmac_clk_sel);
636 }
637