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