xref: /openbsd/sys/dev/fdt/if_dwqe_fdt.c (revision 414d371c)
1 /*	$OpenBSD: if_dwqe_fdt.c,v 1.17 2023/10/10 07:11:50 stsp 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_mii_statchg_rk3588(struct device *);
77 
78 const struct cfattach dwqe_fdt_ca = {
79 	sizeof(struct dwqe_fdt_softc), dwqe_fdt_match, dwqe_fdt_attach
80 };
81 
82 void	dwqe_reset_phy(struct dwqe_softc *, uint32_t);
83 
84 int
85 dwqe_fdt_match(struct device *parent, void *cfdata, void *aux)
86 {
87 	struct fdt_attach_args *faa = aux;
88 
89 	return OF_is_compatible(faa->fa_node, "snps,dwmac-4.20a") ||
90 	    OF_is_compatible(faa->fa_node, "snps,dwmac-5.20");
91 }
92 
93 void
94 dwqe_fdt_attach(struct device *parent, struct device *self, void *aux)
95 {
96 	struct dwqe_fdt_softc *fsc = (void *)self;
97 	struct dwqe_softc *sc = &fsc->sc_sc;
98 	struct fdt_attach_args *faa = aux;
99 	char phy_mode[16] = { 0 };
100 	uint32_t phy, phy_supply;
101 	uint32_t axi_config;
102 	struct ifnet *ifp = &sc->sc_ac.ac_if;
103 	int i, node;
104 
105 	sc->sc_node = faa->fa_node;
106 	sc->sc_iot = faa->fa_iot;
107 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
108 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
109 		printf(": cannot map registers\n");
110 		return;
111 	}
112 	sc->sc_dmat = faa->fa_dmat;
113 
114 	/* Decide GMAC id through address */
115 	switch (faa->fa_reg[0].addr) {
116 	case 0xfe2a0000:	/* RK3568 */
117 	case 0x16030000:	/* JH7110 */
118 		fsc->sc_gmac_id = 0;
119 		break;
120 	case 0xfe010000:	/* RK3568 */
121 	case 0x16040000:	/* JH7110 */
122 		fsc->sc_gmac_id = 1;
123 		break;
124 	default:
125 		printf(": unknown controller at 0x%llx\n", faa->fa_reg[0].addr);
126 		return;
127 	}
128 
129 	printf(" gmac %d", fsc->sc_gmac_id);
130 
131 	OF_getprop(faa->fa_node, "phy-mode", phy_mode, sizeof(phy_mode));
132 	if (strcmp(phy_mode, "rgmii") == 0)
133 		sc->sc_phy_mode = DWQE_PHY_MODE_RGMII;
134 	else if (strcmp(phy_mode, "rgmii-rxid") == 0)
135 		sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_RXID;
136 	else if (strcmp(phy_mode, "rgmii-txid") == 0)
137 		sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_TXID;
138 	else if (strcmp(phy_mode, "rgmii-id") == 0)
139 		sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_ID;
140 	else
141 		sc->sc_phy_mode = DWQE_PHY_MODE_UNKNOWN;
142 
143 	/* Lookup PHY. */
144 	phy = OF_getpropint(faa->fa_node, "phy", 0);
145 	if (phy == 0)
146 		phy = OF_getpropint(faa->fa_node, "phy-handle", 0);
147 	node = OF_getnodebyphandle(phy);
148 	if (node)
149 		sc->sc_phyloc = OF_getpropint(node, "reg", MII_PHY_ANY);
150 	else
151 		sc->sc_phyloc = MII_PHY_ANY;
152 	sc->sc_mii.mii_node = node;
153 
154 	pinctrl_byname(faa->fa_node, "default");
155 
156 	/* Enable clocks. */
157 	clock_set_assigned(faa->fa_node);
158 	clock_enable(faa->fa_node, "stmmaceth");
159 	clock_enable(faa->fa_node, "pclk");
160 	reset_deassert(faa->fa_node, "stmmaceth");
161 	reset_deassert(faa->fa_node, "ahb");
162 	if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac")) {
163 		clock_enable(faa->fa_node, "tx");
164 		clock_enable(faa->fa_node, "gtx");
165 	} else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac")) {
166 		clock_enable(faa->fa_node, "mac_clk_rx");
167 		clock_enable(faa->fa_node, "mac_clk_tx");
168 		clock_enable(faa->fa_node, "aclk_mac");
169 		clock_enable(faa->fa_node, "pclk_mac");
170 	}
171 	delay(5000);
172 
173 	/* Do hardware specific initializations. */
174 	if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac"))
175 		dwqe_setup_jh7110(sc);
176 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac"))
177 		dwqe_setup_rk3568(fsc);
178 
179 	/* Power up PHY. */
180 	phy_supply = OF_getpropint(faa->fa_node, "phy-supply", 0);
181 	if (phy_supply)
182 		regulator_enable(phy_supply);
183 
184 	/* Reset PHY */
185 	dwqe_reset_phy(sc, phy);
186 
187 	node = OF_getnodebyname(sc->sc_node, "fixed-link");
188 	if (node) {
189 		sc->sc_fixed_link = 1;
190 
191 		ifp->if_baudrate = IF_Mbps(OF_getpropint(node, "speed", 0));
192 		ifp->if_link_state = OF_getpropbool(node, "full-duplex") ?
193 		    LINK_STATE_FULL_DUPLEX : LINK_STATE_HALF_DUPLEX;
194 	}
195 
196 	sc->sc_clkrate = clock_get_frequency(faa->fa_node, "stmmaceth");
197 	if (sc->sc_clkrate > 500000000)
198 		sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_500_800;
199 	else if (sc->sc_clkrate > 300000000)
200 		sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_300_500;
201 	else if (sc->sc_clkrate > 150000000)
202 		sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_150_250;
203 	else if (sc->sc_clkrate > 100000000)
204 		sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_100_150;
205 	else if (sc->sc_clkrate > 60000000)
206 		sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_60_100;
207 	else if (sc->sc_clkrate > 35000000)
208 		sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_35_60;
209 	else
210 		sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_20_35;
211 
212 	for (i = 0; i < 4; i++)
213 		sc->sc_hw_feature[i] = dwqe_read(sc, GMAC_MAC_HW_FEATURE(i));
214 
215 	if (OF_getprop(faa->fa_node, "local-mac-address",
216 	    &sc->sc_lladdr, ETHER_ADDR_LEN) != ETHER_ADDR_LEN)
217 		dwqe_lladdr_read(sc, sc->sc_lladdr);
218 
219 	sc->sc_force_thresh_dma_mode =
220 	    OF_getpropbool(faa->fa_node, "snps,force_thresh_dma_mode");
221 
222 	dwqe_reset(sc);
223 
224 	sc->sc_fixed_burst = OF_getpropbool(faa->fa_node, "snps,fixed-burst");
225 	sc->sc_mixed_burst = OF_getpropbool(faa->fa_node, "snps,mixed-burst");
226 	sc->sc_aal = OF_getpropbool(faa->fa_node, "snps,aal");
227 	sc->sc_8xpbl = !OF_getpropbool(faa->fa_node, "snps,no-pbl-x8");
228 	sc->sc_pbl = OF_getpropint(faa->fa_node, "snps,pbl", 8);
229 	sc->sc_txpbl = OF_getpropint(faa->fa_node, "snps,txpbl", sc->sc_pbl);
230 	sc->sc_rxpbl = OF_getpropint(faa->fa_node, "snps,rxpbl", sc->sc_pbl);
231 
232 	/* Configure AXI master. */
233 	axi_config = OF_getpropint(faa->fa_node, "snps,axi-config", 0);
234 	node = OF_getnodebyphandle(axi_config);
235 	if (node) {
236 		sc->sc_axi_config = 1;
237 		sc->sc_lpi_en = OF_getpropbool(node, "snps,lpi_en");
238 		sc->sc_xit_frm = OF_getpropbool(node, "snps,xit_frm");
239 
240 		sc->sc_wr_osr_lmt = OF_getpropint(node, "snps,wr_osr_lmt", 1);
241 		sc->sc_rd_osr_lmt = OF_getpropint(node, "snps,rd_osr_lmt", 1);
242 
243 		OF_getpropintarray(node, "snps,blen", sc->sc_blen, sizeof(sc->sc_blen));
244 	}
245 
246 	if (dwqe_attach(sc) != 0)
247 		return;
248 
249 	if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac") &&
250 	    !OF_getpropbool(faa->fa_node, "starfive,tx-use-rgmii-clk"))
251 		sc->sc_mii.mii_statchg = dwqe_mii_statchg_jh7110;
252 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac"))
253 		sc->sc_mii.mii_statchg = dwqe_mii_statchg_rk3568;
254 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3588-gmac"))
255 		sc->sc_mii.mii_statchg = dwqe_mii_statchg_rk3588;
256 
257 	sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_NET | IPL_MPSAFE,
258 	    dwqe_intr, sc, sc->sc_dev.dv_xname);
259 	if (sc->sc_ih == NULL)
260 		printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname);
261 
262 	fsc->sc_ifd.if_node = faa->fa_node;
263 	fsc->sc_ifd.if_ifp = ifp;
264 	if_register(&fsc->sc_ifd);
265 
266 	/* force a configuration of the clocks/mac */
267 	if (sc->sc_fixed_link)
268 		sc->sc_mii.mii_statchg(self);
269 }
270 
271 void
272 dwqe_reset_phy(struct dwqe_softc *sc, uint32_t phy)
273 {
274 	uint32_t *gpio;
275 	uint32_t delays[3];
276 	int active = 1;
277 	int node, len;
278 
279 	node = OF_getnodebyphandle(phy);
280 	if (node && OF_getproplen(node, "reset-gpios") > 0) {
281 		len = OF_getproplen(node, "reset-gpios");
282 
283 		gpio = malloc(len, M_TEMP, M_WAITOK);
284 
285 		/* Gather information. */
286 		OF_getpropintarray(node, "reset-gpios", gpio, len);
287 		delays[0] = OF_getpropint(node, "reset-deassert-us", 0);
288 		delays[1] = OF_getpropint(node, "reset-assert-us", 0);
289 		delays[2] = OF_getpropint(node, "reset-deassert-us", 0);
290 	} else {
291 		len = OF_getproplen(sc->sc_node, "snps,reset-gpio");
292 		if (len <= 0)
293 			return;
294 
295 		gpio = malloc(len, M_TEMP, M_WAITOK);
296 
297 		/* Gather information. */
298 		OF_getpropintarray(sc->sc_node, "snps,reset-gpio", gpio, len);
299 		if (OF_getpropbool(sc->sc_node, "snps-reset-active-low"))
300 			active = 0;
301 		delays[0] = delays[1] = delays[2] = 0;
302 		OF_getpropintarray(sc->sc_node, "snps,reset-delays-us", delays,
303 		    sizeof(delays));
304 	}
305 
306 	/* Perform reset sequence. */
307 	gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT);
308 	gpio_controller_set_pin(gpio, !active);
309 	delay(delays[0]);
310 	gpio_controller_set_pin(gpio, active);
311 	delay(delays[1]);
312 	gpio_controller_set_pin(gpio, !active);
313 	delay(delays[2]);
314 
315 	free(gpio, M_TEMP, len);
316 }
317 
318 /* JH7110 registers */
319 #define JH7110_PHY_INTF_RGMII		1
320 #define JH7110_PHY_INTF_RMII		4
321 
322 /* RK3568 registers */
323 #define RK3568_GRF_GMACx_CON0(x)	(0x0380 + (x) * 0x8)
324 #define  RK3568_GMAC_CLK_RX_DL_CFG(val)		((0x7f << 8) << 16 | ((val) << 8))
325 #define  RK3568_GMAC_CLK_TX_DL_CFG(val)		((0x7f << 0) << 16 | ((val) << 0))
326 #define RK3568_GRF_GMACx_CON1(x)	(0x0384 + (x) * 0x8)
327 #define  RK3568_GMAC_PHY_INTF_SEL_RGMII		((0x7 << 4) << 16 | (0x1 << 4))
328 #define  RK3568_GMAC_PHY_INTF_SEL_RMII		((0x7 << 4) << 16 | (0x4 << 4))
329 #define  RK3568_GMAC_TXCLK_DLY_SET(_v)		((1 << 0) << 16 | ((_v) << 0))
330 #define  RK3568_GMAC_RXCLK_DLY_SET(_v)		((1 << 1) << 16 | ((_v) << 1))
331 
332 void	dwqe_mii_statchg_jh7110_task(void *);
333 void	dwqe_mii_statchg_rk3568_task(void *);
334 
335 void
336 dwqe_setup_jh7110(struct dwqe_softc *sc)
337 {
338 	struct regmap *rm;
339 	uint32_t cells[3];
340 	uint32_t phandle, offset, reg, shift;
341 	char phy_mode[32];
342 	uint32_t iface;
343 
344 	if (OF_getpropintarray(sc->sc_node, "starfive,syscon", cells,
345 	    sizeof(cells)) != sizeof(cells)) {
346 		printf("%s: failed to get starfive,syscon\n", __func__);
347 		return;
348 	}
349 	phandle = cells[0];
350 	offset = cells[1];
351 	shift = cells[2];
352 
353 	rm = regmap_byphandle(phandle);
354 	if (rm == NULL) {
355 		printf("%s: failed to get regmap\n", __func__);
356 		return;
357 	}
358 
359 	if (OF_getprop(sc->sc_node, "phy-mode", phy_mode,
360 	    sizeof(phy_mode)) <= 0)
361 		return;
362 
363 	if (strcmp(phy_mode, "rgmii") == 0 ||
364 	    strcmp(phy_mode, "rgmii-id") == 0) {
365 		iface = JH7110_PHY_INTF_RGMII;
366 	} else if (strcmp(phy_mode, "rmii") == 0) {
367 		iface = JH7110_PHY_INTF_RMII;
368 	} else
369 		return;
370 
371 	reg = regmap_read_4(rm, offset);
372 	reg &= ~(((1U << 3) - 1) << shift);
373 	reg |= iface << shift;
374 	regmap_write_4(rm, offset, reg);
375 
376 	task_set(&sc->sc_statchg_task,
377 	    dwqe_mii_statchg_jh7110_task, sc);
378 }
379 
380 void
381 dwqe_mii_statchg_jh7110_task(void *arg)
382 {
383 	struct dwqe_softc *sc = arg;
384 	struct ifnet *ifp = &sc->sc_ac.ac_if;
385 
386 	dwqe_mii_statchg(&sc->sc_dev);
387 
388 	switch (ifp->if_baudrate) {
389 	case IF_Mbps(10):
390 		clock_set_frequency(sc->sc_node, "tx", 2500000);
391 		break;
392 	case IF_Mbps(100):
393 		clock_set_frequency(sc->sc_node, "tx", 25000000);
394 		break;
395 	case IF_Mbps(1000):
396 		clock_set_frequency(sc->sc_node, "tx", 125000000);
397 		break;
398 	}
399 }
400 
401 void
402 dwqe_mii_statchg_jh7110(struct device *self)
403 {
404 	struct dwqe_softc *sc = (void *)self;
405 
406 	task_add(systq, &sc->sc_statchg_task);
407 }
408 
409 void
410 dwqe_setup_rk3568(struct dwqe_fdt_softc *fsc)
411 {
412 	struct dwqe_softc *sc = &fsc->sc_sc;
413 	char phy_mode[32];
414 	struct regmap *rm;
415 	uint32_t grf;
416 	int tx_delay, rx_delay;
417 	uint32_t iface;
418 
419 	grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
420 	rm = regmap_byphandle(grf);
421 	if (rm == NULL)
422 		return;
423 
424 	if (OF_getprop(sc->sc_node, "phy-mode",
425 	    phy_mode, sizeof(phy_mode)) <= 0)
426 		return;
427 
428 	tx_delay = OF_getpropint(sc->sc_node, "tx_delay", 0x30);
429 	rx_delay = OF_getpropint(sc->sc_node, "rx_delay", 0x10);
430 
431 	if (strcmp(phy_mode, "rgmii") == 0) {
432 		iface = RK3568_GMAC_PHY_INTF_SEL_RGMII;
433 	} else if (strcmp(phy_mode, "rgmii-id") == 0) {
434 		iface = RK3568_GMAC_PHY_INTF_SEL_RGMII;
435 		/* id is "internal delay" */
436 		tx_delay = rx_delay = 0;
437 	} else if (strcmp(phy_mode, "rgmii-rxid") == 0) {
438 		iface = RK3568_GMAC_PHY_INTF_SEL_RGMII;
439 		rx_delay = 0;
440 	} else if (strcmp(phy_mode, "rgmii-txid") == 0) {
441 		iface = RK3568_GMAC_PHY_INTF_SEL_RGMII;
442 		tx_delay = 0;
443 	} else if (strcmp(phy_mode, "rmii") == 0) {
444 		iface = RK3568_GMAC_PHY_INTF_SEL_RMII;
445 		tx_delay = rx_delay = 0;
446 	} else
447 		return;
448 
449 	/* Program clock delay lines. */
450 	regmap_write_4(rm, RK3568_GRF_GMACx_CON0(fsc->sc_gmac_id),
451 	    RK3568_GMAC_CLK_TX_DL_CFG(tx_delay) |
452 	    RK3568_GMAC_CLK_RX_DL_CFG(rx_delay));
453 
454 	/* Set interface and enable/disable clock delay. */
455 	regmap_write_4(rm, RK3568_GRF_GMACx_CON1(fsc->sc_gmac_id), iface |
456 	    RK3568_GMAC_TXCLK_DLY_SET(tx_delay > 0 ? 1 : 0) |
457 	    RK3568_GMAC_RXCLK_DLY_SET(rx_delay > 0 ? 1 : 0));
458 
459 	task_set(&sc->sc_statchg_task,
460 	    dwqe_mii_statchg_rk3568_task, sc);
461 }
462 
463 void
464 dwqe_mii_statchg_rk3568_task(void *arg)
465 {
466 	struct dwqe_softc *sc = arg;
467 	struct ifnet *ifp = &sc->sc_ac.ac_if;
468 
469 	dwqe_mii_statchg(&sc->sc_dev);
470 
471 	switch (ifp->if_baudrate) {
472 	case IF_Mbps(10):
473 		clock_set_frequency(sc->sc_node, "clk_mac_speed", 2500000);
474 		break;
475 	case IF_Mbps(100):
476 		clock_set_frequency(sc->sc_node, "clk_mac_speed", 25000000);
477 		break;
478 	case IF_Mbps(1000):
479 		clock_set_frequency(sc->sc_node, "clk_mac_speed", 125000000);
480 		break;
481 	}
482 }
483 
484 void
485 dwqe_mii_statchg_rk3568(struct device *self)
486 {
487 	struct dwqe_softc *sc = (void *)self;
488 
489 	task_add(systq, &sc->sc_statchg_task);
490 }
491 
492 void
493 dwqe_mii_statchg_rk3588(struct device *self)
494 {
495 	struct dwqe_softc *sc = (void *)self;
496 	struct ifnet *ifp = &sc->sc_ac.ac_if;
497 	struct regmap *rm;
498 	uint32_t grf;
499 	uint32_t gmac_clk_sel = 0;
500 
501 	dwqe_mii_statchg(self);
502 
503 	grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
504 	rm = regmap_byphandle(grf);
505 	if (rm == NULL)
506 		return;
507 
508 	switch (ifp->if_baudrate) {
509 	case IF_Mbps(10):
510 		gmac_clk_sel = sc->sc_clk_sel_2_5;
511 		break;
512 	case IF_Mbps(100):
513 		gmac_clk_sel = sc->sc_clk_sel_25;
514 		break;
515 	case IF_Mbps(1000):
516 		gmac_clk_sel = sc->sc_clk_sel_125;
517 		break;
518 	}
519 
520 	regmap_write_4(rm, sc->sc_clk_sel, gmac_clk_sel);
521 }
522