xref: /netbsd-src/sys/arch/arm/rockchip/rk_gmac.c (revision c9ba1e932e746beba3edd75eea8cc6b8111ca83c)
1*c9ba1e93Sskrll /* $NetBSD: rk_gmac.c,v 1.23 2024/08/10 12:16:46 skrll Exp $ */
26726462dSjmcneill 
36726462dSjmcneill /*-
46726462dSjmcneill  * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
56726462dSjmcneill  * All rights reserved.
66726462dSjmcneill  *
76726462dSjmcneill  * Redistribution and use in source and binary forms, with or without
86726462dSjmcneill  * modification, are permitted provided that the following conditions
96726462dSjmcneill  * are met:
106726462dSjmcneill  * 1. Redistributions of source code must retain the above copyright
116726462dSjmcneill  *    notice, this list of conditions and the following disclaimer.
126726462dSjmcneill  * 2. Redistributions in binary form must reproduce the above copyright
136726462dSjmcneill  *    notice, this list of conditions and the following disclaimer in the
146726462dSjmcneill  *    documentation and/or other materials provided with the distribution.
156726462dSjmcneill  *
166726462dSjmcneill  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
176726462dSjmcneill  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
186726462dSjmcneill  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
196726462dSjmcneill  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
206726462dSjmcneill  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
216726462dSjmcneill  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
226726462dSjmcneill  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
236726462dSjmcneill  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
246726462dSjmcneill  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
256726462dSjmcneill  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
266726462dSjmcneill  * POSSIBILITY OF SUCH DAMAGE.
276726462dSjmcneill  */
286726462dSjmcneill 
296726462dSjmcneill #include <sys/cdefs.h>
306726462dSjmcneill 
31*c9ba1e93Sskrll __KERNEL_RCSID(0, "$NetBSD: rk_gmac.c,v 1.23 2024/08/10 12:16:46 skrll Exp $");
326726462dSjmcneill 
336726462dSjmcneill #include <sys/param.h>
346726462dSjmcneill #include <sys/bus.h>
356726462dSjmcneill #include <sys/device.h>
366726462dSjmcneill #include <sys/intr.h>
376726462dSjmcneill #include <sys/systm.h>
386726462dSjmcneill #include <sys/gpio.h>
39f872a062Smsaitoh #include <sys/rndsource.h>
406726462dSjmcneill 
416726462dSjmcneill #include <net/if.h>
426726462dSjmcneill #include <net/if_ether.h>
436726462dSjmcneill #include <net/if_media.h>
446726462dSjmcneill 
456726462dSjmcneill #include <dev/mii/miivar.h>
466726462dSjmcneill 
476726462dSjmcneill #include <dev/ic/dwc_gmac_var.h>
486726462dSjmcneill #include <dev/ic/dwc_gmac_reg.h>
496726462dSjmcneill 
506726462dSjmcneill #include <dev/fdt/fdtvar.h>
51a3657ce0Sjmcneill #include <dev/fdt/syscon.h>
526726462dSjmcneill 
538c7bec30Sjmcneill #define	RK_GMAC_TXDLY_DEFAULT	0x30
548c7bec30Sjmcneill #define	RK_GMAC_RXDLY_DEFAULT	0x10
558c7bec30Sjmcneill 
568c7bec30Sjmcneill enum rk_gmac_type {
5701470923Sjmcneill 	GMAC_RK3288 = 1,
5801470923Sjmcneill 	GMAC_RK3328,
598c7bec30Sjmcneill 	GMAC_RK3399
608c7bec30Sjmcneill };
618c7bec30Sjmcneill 
62646c0f59Sthorpej static const struct device_compatible_entry compat_data[] = {
6301470923Sjmcneill 	{ .compat = "rockchip,rk3288-gmac",	.value = GMAC_RK3288 },
64646c0f59Sthorpej 	{ .compat = "rockchip,rk3328-gmac",	.value = GMAC_RK3328 },
65646c0f59Sthorpej 	{ .compat = "rockchip,rk3399-gmac",	.value = GMAC_RK3399 },
666e54367aSthorpej 	DEVICE_COMPAT_EOL
678c7bec30Sjmcneill };
688c7bec30Sjmcneill 
698c7bec30Sjmcneill struct rk_gmac_softc {
708c7bec30Sjmcneill 	struct dwc_gmac_softc	sc_base;
718c7bec30Sjmcneill 	struct syscon		*sc_syscon;
728c7bec30Sjmcneill 	enum rk_gmac_type	sc_type;
738c7bec30Sjmcneill };
748c7bec30Sjmcneill 
758c7bec30Sjmcneill /*
7601470923Sjmcneill  * RK3288 specific
7701470923Sjmcneill  */
7801470923Sjmcneill 
7901470923Sjmcneill #define	RK3288_GRF_SOC_CON1	0x0248
8001470923Sjmcneill #define	 RK3288_GRF_SOC_CON1_RMII_MODE		__BIT(14)
8101470923Sjmcneill #define	 RK3288_GRF_SOC_CON1_GMAC_CLK_SEL	__BITS(13,12)
8201470923Sjmcneill #define	  RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_125M		0
8301470923Sjmcneill #define	  RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_2_5M		2
8401470923Sjmcneill #define	  RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_25M		3
8501470923Sjmcneill #define	 RK3288_GRF_SOC_CON1_RMII_CLK_SEL	__BIT(11)
8601470923Sjmcneill #define	  RK3288_GRF_SOC_CON1_RMII_CLK_SEL_25M		1
8701470923Sjmcneill #define	  RK3288_GRF_SOC_CON1_RMII_CLK_SEL_2_5M		0
8801470923Sjmcneill #define	 RK3288_GRF_SOC_CON1_GMAC_SPEED		__BIT(10)
8901470923Sjmcneill #define	  RK3288_GRF_SOC_CON1_GMAC_SPEED_10M		0
9001470923Sjmcneill #define	  RK3288_GRF_SOC_CON1_GMAC_SPEED_100M		1
9101470923Sjmcneill #define	 RK3288_GRF_SOC_CON1_GMAC_FLOWCTRL	__BIT(9)
9201470923Sjmcneill #define	 RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL	__BITS(8,6)
9301470923Sjmcneill #define	  RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL_RGMII	1
9401470923Sjmcneill #define	  RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL_RMII	4
9501470923Sjmcneill 
9601470923Sjmcneill #define	RK3288_GRF_SOC_CON3	0x0250
9701470923Sjmcneill #define	 RK3288_GRF_SOC_CON3_RXCLK_DLY_ENA_GMAC	__BIT(15)
9801470923Sjmcneill #define	 RK3288_GRF_SOC_CON3_TXCLK_DLY_ENA_GMAC	__BIT(14)
9901470923Sjmcneill #define	 RK3288_GRF_SOC_CON3_CLK_RX_DL_CFG_GMAC	__BITS(13,7)
10001470923Sjmcneill #define	 RK3288_GRF_SOC_CON3_CLK_TX_DL_CFG_GMAC	__BITS(6,0)
10101470923Sjmcneill 
10201470923Sjmcneill static void
10301470923Sjmcneill rk3288_gmac_set_mode_rgmii(struct dwc_gmac_softc *sc, u_int tx_delay, u_int rx_delay, bool set_delay)
10401470923Sjmcneill {
10501470923Sjmcneill 	struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;
10601470923Sjmcneill 	uint32_t write_mask, write_val;
10701470923Sjmcneill 
10801470923Sjmcneill 	syscon_lock(rk_sc->sc_syscon);
10901470923Sjmcneill 
11001470923Sjmcneill 	write_mask = (RK3288_GRF_SOC_CON1_RMII_MODE |
11101470923Sjmcneill 		      RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL) << 16;
11201470923Sjmcneill 	write_val = __SHIFTIN(RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL_RGMII,
11301470923Sjmcneill 			      RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL);
11401470923Sjmcneill 	syscon_write_4(rk_sc->sc_syscon, RK3288_GRF_SOC_CON1,
11501470923Sjmcneill 	    write_mask | write_val);
11601470923Sjmcneill 
11701470923Sjmcneill 	if (set_delay) {
11801470923Sjmcneill 		write_mask = (RK3288_GRF_SOC_CON3_RXCLK_DLY_ENA_GMAC |
11901470923Sjmcneill 			      RK3288_GRF_SOC_CON3_TXCLK_DLY_ENA_GMAC |
12001470923Sjmcneill 			      RK3288_GRF_SOC_CON3_CLK_RX_DL_CFG_GMAC |
12101470923Sjmcneill 			      RK3288_GRF_SOC_CON3_CLK_TX_DL_CFG_GMAC) << 16;
12201470923Sjmcneill 		write_val = 0;
12301470923Sjmcneill 		if (tx_delay) {
12401470923Sjmcneill 			write_mask |= RK3288_GRF_SOC_CON3_TXCLK_DLY_ENA_GMAC |
12501470923Sjmcneill 				      __SHIFTIN(tx_delay,
12601470923Sjmcneill 						RK3288_GRF_SOC_CON3_CLK_TX_DL_CFG_GMAC);
12701470923Sjmcneill 		}
12801470923Sjmcneill 		if (rx_delay) {
12901470923Sjmcneill 			write_mask |= RK3288_GRF_SOC_CON3_RXCLK_DLY_ENA_GMAC |
13001470923Sjmcneill 				      __SHIFTIN(rx_delay,
13101470923Sjmcneill 						RK3288_GRF_SOC_CON3_CLK_RX_DL_CFG_GMAC);
13201470923Sjmcneill 		}
13301470923Sjmcneill 		syscon_write_4(rk_sc->sc_syscon, RK3288_GRF_SOC_CON3,
13401470923Sjmcneill 		    write_mask | write_val);
13501470923Sjmcneill 	}
13601470923Sjmcneill 
13701470923Sjmcneill 	syscon_unlock(rk_sc->sc_syscon);
13801470923Sjmcneill }
13901470923Sjmcneill 
14001470923Sjmcneill static void
14101470923Sjmcneill rk3288_gmac_set_speed_rgmii(struct dwc_gmac_softc *sc, int speed)
14201470923Sjmcneill {
14301470923Sjmcneill 	struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;
14401470923Sjmcneill 	uint32_t write_mask, write_val;
14501470923Sjmcneill 
14601470923Sjmcneill 	syscon_lock(rk_sc->sc_syscon);
14701470923Sjmcneill 
14801470923Sjmcneill 	write_mask = (RK3288_GRF_SOC_CON1_GMAC_CLK_SEL) << 16;
14901470923Sjmcneill 	switch (speed) {
15001470923Sjmcneill 	case IFM_10_T:
15101470923Sjmcneill 		write_val = RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_2_5M;
15201470923Sjmcneill 		break;
15301470923Sjmcneill 	case IFM_100_TX:
15401470923Sjmcneill 		write_val = RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_25M;
15501470923Sjmcneill 		break;
15601470923Sjmcneill 	case IFM_1000_T:
15701470923Sjmcneill 	default:
15801470923Sjmcneill 		write_val = RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_125M;
15901470923Sjmcneill 		break;
16001470923Sjmcneill 	}
16101470923Sjmcneill 	syscon_write_4(rk_sc->sc_syscon, RK3288_GRF_SOC_CON1,
16201470923Sjmcneill 	    write_mask | write_val);
16301470923Sjmcneill 
16401470923Sjmcneill 	syscon_unlock(rk_sc->sc_syscon);
16501470923Sjmcneill }
16601470923Sjmcneill 
16701470923Sjmcneill /*
1688c7bec30Sjmcneill  * RK3328 specific
1698c7bec30Sjmcneill  */
1708c7bec30Sjmcneill 
1716726462dSjmcneill #define	RK3328_GRF_MAC_CON0	0x0900
1726726462dSjmcneill #define	 RK3328_GRF_MAC_CON0_RXDLY	__BITS(13,7)
1736726462dSjmcneill #define	 RK3328_GRF_MAC_CON0_TXDLY	__BITS(6,0)
1746726462dSjmcneill 
1756726462dSjmcneill #define	RK3328_GRF_MAC_CON1	0x0904
1766726462dSjmcneill #define	 RK3328_GRF_MAC_CON1_CLKSEL	__BITS(12,11)
1776726462dSjmcneill #define	  RK3328_GRF_MAC_CON1_CLKSEL_125M	0
1786726462dSjmcneill #define	  RK3328_GRF_MAC_CON1_CLKSEL_2_5M	2
1796726462dSjmcneill #define	  RK3328_GRF_MAC_CON1_CLKSEL_25M	3
1806726462dSjmcneill #define	 RK3328_GRF_MAC_CON1_MODE	__BIT(9)
1816726462dSjmcneill #define	 RK3328_GRF_MAC_CON1_SEL	__BITS(6,4)
1826726462dSjmcneill #define	  RK3328_GRF_MAC_CON1_SEL_RGMII	1
1836726462dSjmcneill #define	 RK3328_GRF_MAC_CON1_RXDLY_EN	__BIT(1)
1846726462dSjmcneill #define	 RK3328_GRF_MAC_CON1_TXDLY_EN	__BIT(0)
1856726462dSjmcneill 
1866726462dSjmcneill static void
1877bd92a1aStnn rk3328_gmac_set_mode_rgmii(struct dwc_gmac_softc *sc, u_int tx_delay, u_int rx_delay, bool set_delay)
1886726462dSjmcneill {
1896726462dSjmcneill 	struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;
190517d79ffSjmcneill 	uint32_t write_mask, write_val;
1916726462dSjmcneill 
192a3657ce0Sjmcneill 	syscon_lock(rk_sc->sc_syscon);
193a3657ce0Sjmcneill 
194517d79ffSjmcneill 	write_mask = (RK3328_GRF_MAC_CON1_MODE | RK3328_GRF_MAC_CON1_SEL) << 16;
1957bd92a1aStnn 	write_val = __SHIFTIN(RK3328_GRF_MAC_CON1_SEL_RGMII,
1967bd92a1aStnn 	    RK3328_GRF_MAC_CON1_SEL);
1977bd92a1aStnn 	syscon_write_4(rk_sc->sc_syscon, RK3328_GRF_MAC_CON1,
1987bd92a1aStnn 	    write_mask | write_val);
1996726462dSjmcneill 
2007bd92a1aStnn 	if (set_delay) {
2017bd92a1aStnn 		write_mask = (
2027bd92a1aStnn 		    RK3328_GRF_MAC_CON0_TXDLY |
2037bd92a1aStnn 		    RK3328_GRF_MAC_CON0_RXDLY) << 16;
2047bd92a1aStnn 		write_val =
2057bd92a1aStnn 		    __SHIFTIN(tx_delay, RK3328_GRF_MAC_CON0_TXDLY) |
206517d79ffSjmcneill 		    __SHIFTIN(rx_delay, RK3328_GRF_MAC_CON0_RXDLY);
2077bd92a1aStnn 		syscon_write_4(rk_sc->sc_syscon, RK3328_GRF_MAC_CON0,
2087bd92a1aStnn 		    write_mask | write_val);
209517d79ffSjmcneill 
2107bd92a1aStnn 		write_mask = (
2117bd92a1aStnn 		    RK3328_GRF_MAC_CON1_RXDLY_EN |
2127bd92a1aStnn 		    RK3328_GRF_MAC_CON1_TXDLY_EN) << 16;
2137bd92a1aStnn 		write_val =
2147bd92a1aStnn 		    RK3328_GRF_MAC_CON1_RXDLY_EN |
2157bd92a1aStnn 		    RK3328_GRF_MAC_CON1_TXDLY_EN;
2167bd92a1aStnn 		syscon_write_4(rk_sc->sc_syscon, RK3328_GRF_MAC_CON1,
2177bd92a1aStnn 		    write_mask | write_val);
2187bd92a1aStnn 	}
219a3657ce0Sjmcneill 
220a3657ce0Sjmcneill 	syscon_unlock(rk_sc->sc_syscon);
2216726462dSjmcneill }
2226726462dSjmcneill 
2236726462dSjmcneill static void
2246726462dSjmcneill rk3328_gmac_set_speed_rgmii(struct dwc_gmac_softc *sc, int speed)
2256726462dSjmcneill {
2266726462dSjmcneill 	struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;
2272c613b24Schristos #if 0
2286726462dSjmcneill 	u_int clksel;
2296726462dSjmcneill 
2306726462dSjmcneill 	switch (speed) {
2316726462dSjmcneill 	case IFM_10_T:
2326726462dSjmcneill 		clksel = RK3328_GRF_MAC_CON1_CLKSEL_2_5M;
2336726462dSjmcneill 		break;
2346726462dSjmcneill 	case IFM_100_TX:
2356726462dSjmcneill 		clksel = RK3328_GRF_MAC_CON1_CLKSEL_25M;
2366726462dSjmcneill 		break;
2376726462dSjmcneill 	default:
2386726462dSjmcneill 		clksel = RK3328_GRF_MAC_CON1_CLKSEL_125M;
2396726462dSjmcneill 		break;
2406726462dSjmcneill 	}
2412c613b24Schristos #endif
2426726462dSjmcneill 
243a3657ce0Sjmcneill 	syscon_lock(rk_sc->sc_syscon);
244a3657ce0Sjmcneill 	syscon_write_4(rk_sc->sc_syscon, RK3328_GRF_MAC_CON1,
2456726462dSjmcneill 	    (RK3328_GRF_MAC_CON1_CLKSEL << 16) |
2466726462dSjmcneill 	    __SHIFTIN(RK3328_GRF_MAC_CON1_CLKSEL_125M, RK3328_GRF_MAC_CON1_CLKSEL));
247a3657ce0Sjmcneill 	syscon_unlock(rk_sc->sc_syscon);
2486726462dSjmcneill }
2496726462dSjmcneill 
2508c7bec30Sjmcneill /*
2518c7bec30Sjmcneill  * RK3399 specific
2528c7bec30Sjmcneill  */
2538c7bec30Sjmcneill 
2548c7bec30Sjmcneill #define	RK3399_GRF_SOC_CON5		0x0c214
2558c7bec30Sjmcneill #define	 RK3399_GRF_SOC_CON5_GMAC_PHY_INTF_SEL	__BITS(11,9)
2568c7bec30Sjmcneill #define	 RK3399_GRF_SOC_CON5_GMAC_FLOWCTRL	__BIT(8)
2578c7bec30Sjmcneill #define	 RK3399_GRF_SOC_CON5_GMAC_SPEED		__BIT(7)
2588c7bec30Sjmcneill #define	 RK3399_GRF_SOC_CON5_RMII_MODE		__BIT(6)
2598c7bec30Sjmcneill #define	 RK3399_GRF_SOC_CON5_GMAC_CLK_SEL	__BITS(5,4)
2608c7bec30Sjmcneill #define	  RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_125M	0
261bc6ba7a4Smsaitoh #define	  RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_25M	3
2628c7bec30Sjmcneill #define	  RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_2_5M	2
2638c7bec30Sjmcneill #define	 RK3399_GRF_SOC_CON5_RMII_CLK_SEL	__BIT(3)
2648c7bec30Sjmcneill #define	RK3399_GRF_SOC_CON6		0x0c218
2658c7bec30Sjmcneill #define	 RK3399_GRF_SOC_CON6_GMAC_RXCLK_DLY_ENA	__BIT(15)
2668c7bec30Sjmcneill #define	 RK3399_GRF_SOC_CON6_GMAC_CLK_RX_DL_CFG	__BITS(14,8)
2678c7bec30Sjmcneill #define	 RK3399_GRF_SOC_CON6_GMAC_TXCLK_DLY_ENA	__BIT(7)
2688c7bec30Sjmcneill #define	 RK3399_GRF_SOC_CON6_GMAC_CLK_TX_DL_CFG	__BITS(6,0)
2698c7bec30Sjmcneill 
2708c7bec30Sjmcneill static void
2717bd92a1aStnn rk3399_gmac_set_mode_rgmii(struct dwc_gmac_softc *sc, u_int tx_delay,
2727bd92a1aStnn     u_int rx_delay, bool set_delay)
2738c7bec30Sjmcneill {
2748c7bec30Sjmcneill 	struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;
2757bd92a1aStnn 	uint32_t write_mask, write_val;
2768c7bec30Sjmcneill 
2777bd92a1aStnn 	syscon_lock(rk_sc->sc_syscon);
2788c7bec30Sjmcneill 
2797bd92a1aStnn 	write_mask = (
2807bd92a1aStnn 	    RK3399_GRF_SOC_CON5_RMII_MODE |
2817bd92a1aStnn 	    RK3399_GRF_SOC_CON5_GMAC_PHY_INTF_SEL) << 16;
2827bd92a1aStnn 	write_val = __SHIFTIN(1, RK3399_GRF_SOC_CON5_GMAC_PHY_INTF_SEL);
2837bd92a1aStnn 	syscon_write_4(rk_sc->sc_syscon, RK3399_GRF_SOC_CON5,
2847bd92a1aStnn 	    write_mask | write_val);
2857bd92a1aStnn 	if (set_delay) {
2867bd92a1aStnn 		write_mask = (
287dadbc819Smsaitoh 		    RK3399_GRF_SOC_CON6_GMAC_TXCLK_DLY_ENA |
2887bd92a1aStnn 		    RK3399_GRF_SOC_CON6_GMAC_RXCLK_DLY_ENA |
289dadbc819Smsaitoh 		    RK3399_GRF_SOC_CON6_GMAC_CLK_RX_DL_CFG |
290dadbc819Smsaitoh 		    RK3399_GRF_SOC_CON6_GMAC_CLK_TX_DL_CFG) << 16;
2917bd92a1aStnn 		write_val =
292dadbc819Smsaitoh 		    (tx_delay ? RK3399_GRF_SOC_CON6_GMAC_TXCLK_DLY_ENA : 0) |
293dadbc819Smsaitoh 		    (rx_delay ? RK3399_GRF_SOC_CON6_GMAC_RXCLK_DLY_ENA : 0) |
2948c7bec30Sjmcneill 		    __SHIFTIN(rx_delay, RK3399_GRF_SOC_CON6_GMAC_CLK_RX_DL_CFG) |
2958c7bec30Sjmcneill 		    __SHIFTIN(tx_delay, RK3399_GRF_SOC_CON6_GMAC_CLK_TX_DL_CFG);
2967bd92a1aStnn 		syscon_write_4(rk_sc->sc_syscon, RK3399_GRF_SOC_CON6,
2977bd92a1aStnn 		    write_mask | write_val);
2987bd92a1aStnn 	}
2998c7bec30Sjmcneill 	syscon_unlock(rk_sc->sc_syscon);
3008c7bec30Sjmcneill }
3018c7bec30Sjmcneill 
3028c7bec30Sjmcneill static void
3038c7bec30Sjmcneill rk3399_gmac_set_speed_rgmii(struct dwc_gmac_softc *sc, int speed)
3048c7bec30Sjmcneill {
3058c7bec30Sjmcneill 	struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;
3068c7bec30Sjmcneill 	u_int clksel;
3078c7bec30Sjmcneill 
3088c7bec30Sjmcneill 	switch (speed) {
3098c7bec30Sjmcneill 	case IFM_10_T:
3108c7bec30Sjmcneill 		clksel = RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_2_5M;
3118c7bec30Sjmcneill 		break;
3128c7bec30Sjmcneill 	case IFM_100_TX:
3138c7bec30Sjmcneill 		clksel = RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_25M;
3148c7bec30Sjmcneill 		break;
3158c7bec30Sjmcneill 	default:
3168c7bec30Sjmcneill 		clksel = RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_125M;
3178c7bec30Sjmcneill 		break;
3188c7bec30Sjmcneill 	}
3198c7bec30Sjmcneill 
3208c7bec30Sjmcneill 	const uint32_t con5_mask =
3218c7bec30Sjmcneill 	    RK3399_GRF_SOC_CON5_GMAC_CLK_SEL << 16;
3228c7bec30Sjmcneill 	const uint32_t con5 =
3238c7bec30Sjmcneill 	    __SHIFTIN(clksel, RK3399_GRF_SOC_CON5_GMAC_CLK_SEL);
3248c7bec30Sjmcneill 
3258c7bec30Sjmcneill 	syscon_lock(rk_sc->sc_syscon);
3268c7bec30Sjmcneill 	syscon_write_4(rk_sc->sc_syscon, RK3399_GRF_SOC_CON5, con5 | con5_mask);
3278c7bec30Sjmcneill 	syscon_unlock(rk_sc->sc_syscon);
3288c7bec30Sjmcneill }
3298c7bec30Sjmcneill 
3308c7bec30Sjmcneill static int
3318c7bec30Sjmcneill rk_gmac_reset(const int phandle)
3328c7bec30Sjmcneill {
3338c7bec30Sjmcneill 	struct fdtbus_gpio_pin *pin_reset;
3348c7bec30Sjmcneill 	const u_int *reset_delay_us;
3358c7bec30Sjmcneill 	bool reset_active_low;
3368c7bec30Sjmcneill 	int len;
3378c7bec30Sjmcneill 
3388c7bec30Sjmcneill 	if (!of_hasprop(phandle, "snps,reset-gpio"))
3398c7bec30Sjmcneill 		return 0;
3408c7bec30Sjmcneill 
3418c7bec30Sjmcneill 	pin_reset = fdtbus_gpio_acquire(phandle, "snps,reset-gpio", GPIO_PIN_OUTPUT);
3428c7bec30Sjmcneill 	if (pin_reset == NULL)
3438c7bec30Sjmcneill 		return ENOENT;
3448c7bec30Sjmcneill 
3458c7bec30Sjmcneill 	reset_delay_us = fdtbus_get_prop(phandle, "snps,reset-delays-us", &len);
3468c7bec30Sjmcneill 	if (reset_delay_us == NULL || len != 12)
3478c7bec30Sjmcneill 		return ENXIO;
3488c7bec30Sjmcneill 
3498c7bec30Sjmcneill 	reset_active_low = of_hasprop(phandle, "snps,reset-active-low");
3508c7bec30Sjmcneill 
3518c7bec30Sjmcneill 	fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 1 : 0);
3528c7bec30Sjmcneill 	delay(be32toh(reset_delay_us[0]));
3538c7bec30Sjmcneill 	fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 0 : 1);
3548c7bec30Sjmcneill 	delay(be32toh(reset_delay_us[1]));
3558c7bec30Sjmcneill 	fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 1 : 0);
3568c7bec30Sjmcneill 	delay(be32toh(reset_delay_us[2]));
3578c7bec30Sjmcneill 
3588c7bec30Sjmcneill 	return 0;
3598c7bec30Sjmcneill }
3608c7bec30Sjmcneill 
3618c7bec30Sjmcneill static int
3628c7bec30Sjmcneill rk_gmac_intr(void *arg)
3638c7bec30Sjmcneill {
3648c7bec30Sjmcneill 	return dwc_gmac_intr(arg);
3658c7bec30Sjmcneill }
3668c7bec30Sjmcneill 
3676726462dSjmcneill static int
3686726462dSjmcneill rk_gmac_setup_clocks(int phandle)
3696726462dSjmcneill {
3706726462dSjmcneill 	static const char * const clknames[] = {
3716726462dSjmcneill #if 0
3726726462dSjmcneill 		"stmmaceth",
3736726462dSjmcneill 		"mac_clk_rx",
3746726462dSjmcneill 		"mac_clk_tx",
3756726462dSjmcneill 		"clk_mac_ref",
3766726462dSjmcneill 		"clk_mac_refout",
3776726462dSjmcneill 		"aclk_mac",
3786726462dSjmcneill 		"pclk_mac"
3796726462dSjmcneill #else
3806726462dSjmcneill 		"stmmaceth",
3816726462dSjmcneill 		"aclk_mac",
3826726462dSjmcneill 		"pclk_mac",
3836726462dSjmcneill 		"mac_clk_tx",
384517d79ffSjmcneill 		"mac_clk_rx"
3856726462dSjmcneill #endif
3866726462dSjmcneill 	};
3876726462dSjmcneill 	static const char * const rstnames[] = {
3886726462dSjmcneill 		"stmmaceth"
3896726462dSjmcneill 	};
3906726462dSjmcneill 	struct fdtbus_reset *rst;
3916726462dSjmcneill 	struct clk *clk;
3926726462dSjmcneill 	int error, n;
3936726462dSjmcneill 
3946726462dSjmcneill 	fdtbus_clock_assign(phandle);
3956726462dSjmcneill 
3966726462dSjmcneill 	for (n = 0; n < __arraycount(clknames); n++) {
3976726462dSjmcneill 		clk = fdtbus_clock_get(phandle, clknames[n]);
3986726462dSjmcneill 		if (clk == NULL) {
3996726462dSjmcneill 			aprint_error(": couldn't get %s clock\n", clknames[n]);
4006726462dSjmcneill 			return ENXIO;
4016726462dSjmcneill 		}
4026726462dSjmcneill 		error = clk_enable(clk);
4036726462dSjmcneill 		if (error != 0) {
4046726462dSjmcneill 			aprint_error(": couldn't enable %s clock: %d\n",
4056726462dSjmcneill 			    clknames[n], error);
4066726462dSjmcneill 			return error;
4076726462dSjmcneill 		}
4086726462dSjmcneill 	}
4096726462dSjmcneill 
4106726462dSjmcneill 	for (n = 0; n < __arraycount(rstnames); n++) {
4116726462dSjmcneill 		rst = fdtbus_reset_get(phandle, rstnames[n]);
4126726462dSjmcneill 		if (rst == NULL) {
4136726462dSjmcneill 			aprint_error(": couldn't get %s reset\n", rstnames[n]);
4146726462dSjmcneill 			return ENXIO;
4156726462dSjmcneill 		}
4166726462dSjmcneill 		error = fdtbus_reset_deassert(rst);
4176726462dSjmcneill 		if (error != 0) {
4186726462dSjmcneill 			aprint_error(": couldn't de-assert %s reset: %d\n",
4196726462dSjmcneill 			    rstnames[n], error);
4206726462dSjmcneill 			return error;
4216726462dSjmcneill 		}
4226726462dSjmcneill 	}
4236726462dSjmcneill 
4246726462dSjmcneill 	delay(5000);
4256726462dSjmcneill 
4266726462dSjmcneill 	return 0;
4276726462dSjmcneill }
4286726462dSjmcneill 
4296726462dSjmcneill static int
4306726462dSjmcneill rk_gmac_match(device_t parent, cfdata_t cf, void *aux)
4316726462dSjmcneill {
4326726462dSjmcneill 	struct fdt_attach_args * const faa = aux;
4336726462dSjmcneill 
4346e54367aSthorpej 	return of_compatible_match(faa->faa_phandle, compat_data);
4356726462dSjmcneill }
4366726462dSjmcneill 
4376726462dSjmcneill static void
4386726462dSjmcneill rk_gmac_attach(device_t parent, device_t self, void *aux)
4396726462dSjmcneill {
4406726462dSjmcneill 	struct rk_gmac_softc * const rk_sc = device_private(self);
4416726462dSjmcneill 	struct dwc_gmac_softc * const sc = &rk_sc->sc_base;
4426726462dSjmcneill 	struct fdt_attach_args * const faa = aux;
4436726462dSjmcneill 	const int phandle = faa->faa_phandle;
4446726462dSjmcneill 	const char *phy_mode;
4456726462dSjmcneill 	char intrstr[128];
446a3657ce0Sjmcneill 	bus_addr_t addr;
447a3657ce0Sjmcneill 	bus_size_t size;
4486726462dSjmcneill 	u_int tx_delay, rx_delay;
4497bd92a1aStnn #ifdef notyet
4507bd92a1aStnn 	bool set_delay = true;
4517bd92a1aStnn #else
4527bd92a1aStnn 	bool set_delay = false;
4537bd92a1aStnn #endif
4546726462dSjmcneill 
4556726462dSjmcneill 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
4566726462dSjmcneill 		aprint_error(": couldn't get registers\n");
4576726462dSjmcneill 		return;
4586726462dSjmcneill 	}
4596726462dSjmcneill 
4606e54367aSthorpej 	rk_sc->sc_type = of_compatible_lookup(phandle, compat_data)->value;
4618c7bec30Sjmcneill 
462a3657ce0Sjmcneill 	rk_sc->sc_syscon = fdtbus_syscon_acquire(phandle, "rockchip,grf");
463a3657ce0Sjmcneill 	if (rk_sc->sc_syscon == NULL) {
464a3657ce0Sjmcneill 		aprint_error(": couldn't get grf syscon\n");
4656726462dSjmcneill 		return;
4666726462dSjmcneill 	}
4676726462dSjmcneill 
4687bd92a1aStnn 	if (of_getprop_uint32(phandle, "tx_delay", &tx_delay) != 0) {
4696726462dSjmcneill 		tx_delay = RK_GMAC_TXDLY_DEFAULT;
4707bd92a1aStnn 		set_delay = false;
4717bd92a1aStnn 	}
4726726462dSjmcneill 
4737bd92a1aStnn 	if (of_getprop_uint32(phandle, "rx_delay", &rx_delay) != 0) {
4746726462dSjmcneill 		rx_delay = RK_GMAC_RXDLY_DEFAULT;
4757bd92a1aStnn 		set_delay = false;
4767bd92a1aStnn 	}
4776726462dSjmcneill 
4786726462dSjmcneill 	sc->sc_dev = self;
4796726462dSjmcneill 	sc->sc_bst = faa->faa_bst;
4806726462dSjmcneill 	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
4816726462dSjmcneill 		aprint_error(": couldn't map registers\n");
4826726462dSjmcneill 		return;
4836726462dSjmcneill 	}
4846726462dSjmcneill 	sc->sc_dmat = faa->faa_dmat;
4856726462dSjmcneill 
4866726462dSjmcneill 	if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
4876726462dSjmcneill 		aprint_error(": failed to decode interrupt\n");
4886726462dSjmcneill 		return;
4896726462dSjmcneill 	}
4906726462dSjmcneill 
4916726462dSjmcneill 	if (rk_gmac_setup_clocks(phandle) != 0)
4926726462dSjmcneill 		return;
4936726462dSjmcneill 
4946726462dSjmcneill 	if (rk_gmac_reset(phandle) != 0)
4956726462dSjmcneill 		aprint_error_dev(self, "PHY reset failed\n");
4966726462dSjmcneill 
4979ba9b3faSjmcneill 	/* Rock64 seems to need more time for the reset to complete */
4989ba9b3faSjmcneill 	delay(100000);
4999ba9b3faSjmcneill 
500517d79ffSjmcneill #if notyet
5016726462dSjmcneill 	if (of_hasprop(phandle, "snps,force_thresh_dma_mode"))
5026726462dSjmcneill 		sc->sc_flags |= DWC_GMAC_FORCE_THRESH_DMA_MODE;
503517d79ffSjmcneill #endif
5046726462dSjmcneill 
5056726462dSjmcneill 	phy_mode = fdtbus_get_string(phandle, "phy-mode");
5066726462dSjmcneill 	if (phy_mode == NULL) {
5076726462dSjmcneill 		aprint_error(": missing 'phy-mode' property\n");
5086726462dSjmcneill 		return;
5096726462dSjmcneill 	}
5106726462dSjmcneill 
5118c7bec30Sjmcneill 	switch (rk_sc->sc_type) {
51201470923Sjmcneill 	case GMAC_RK3288:
51301470923Sjmcneill 		if (strncmp(phy_mode, "rgmii", 5) == 0) {
51401470923Sjmcneill 			rk3288_gmac_set_mode_rgmii(sc, tx_delay, rx_delay,
51501470923Sjmcneill 			    set_delay);
51601470923Sjmcneill 
51701470923Sjmcneill 			sc->sc_set_speed = rk3288_gmac_set_speed_rgmii;
51801470923Sjmcneill 		} else {
51901470923Sjmcneill 			aprint_error(": unsupported phy-mode '%s'\n", phy_mode);
52001470923Sjmcneill 			return;
52101470923Sjmcneill 		}
52201470923Sjmcneill 		break;
5238c7bec30Sjmcneill 	case GMAC_RK3328:
524e0e63425Sjmcneill 		if (strncmp(phy_mode, "rgmii", 5) == 0) {
5257bd92a1aStnn 			rk3328_gmac_set_mode_rgmii(sc, tx_delay, rx_delay,
5267bd92a1aStnn 			    set_delay);
5276726462dSjmcneill 
5286726462dSjmcneill 			sc->sc_set_speed = rk3328_gmac_set_speed_rgmii;
5296726462dSjmcneill 		} else {
5306726462dSjmcneill 			aprint_error(": unsupported phy-mode '%s'\n", phy_mode);
5316726462dSjmcneill 			return;
5326726462dSjmcneill 		}
5338c7bec30Sjmcneill 		break;
5348c7bec30Sjmcneill 	case GMAC_RK3399:
535e0e63425Sjmcneill 		if (strncmp(phy_mode, "rgmii", 5) == 0) {
5367bd92a1aStnn 			rk3399_gmac_set_mode_rgmii(sc, tx_delay, rx_delay,
5377bd92a1aStnn 			    set_delay);
5388c7bec30Sjmcneill 
5398c7bec30Sjmcneill 			sc->sc_set_speed = rk3399_gmac_set_speed_rgmii;
5408c7bec30Sjmcneill 		} else {
5418c7bec30Sjmcneill 			aprint_error(": unsupported phy-mode '%s'\n", phy_mode);
5428c7bec30Sjmcneill 			return;
5438c7bec30Sjmcneill 		}
5448c7bec30Sjmcneill 		break;
5458c7bec30Sjmcneill 	}
5466726462dSjmcneill 
5476726462dSjmcneill 	aprint_naive("\n");
5486726462dSjmcneill 	aprint_normal(": GMAC\n");
5496726462dSjmcneill 
550d9a5cbbfSmartin 	if (dwc_gmac_attach(sc, MII_PHY_ANY, GMAC_MII_CLK_150_250M_DIV102) != 0)
55161fd5480Sjmcneill 		return;
55261fd5480Sjmcneill 
55364e248edSryo 	if (fdtbus_intr_establish_xname(phandle, 0, IPL_NET,
554*c9ba1e93Sskrll 	    FDT_INTR_MPSAFE, rk_gmac_intr, sc,
55564e248edSryo 	    device_xname(self)) == NULL) {
5566726462dSjmcneill 		aprint_error_dev(self, "failed to establish interrupt on %s\n", intrstr);
5576726462dSjmcneill 		return;
5586726462dSjmcneill 	}
5596726462dSjmcneill 	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
5606726462dSjmcneill }
5616726462dSjmcneill 
5626726462dSjmcneill CFATTACH_DECL_NEW(rk_gmac, sizeof(struct rk_gmac_softc),
5636726462dSjmcneill 	rk_gmac_match, rk_gmac_attach, NULL, NULL);
564