From 5e1c6ec49de0cd946f26488798a31f7104259aae Mon Sep 17 00:00:00 2001 From: kettenis Date: Mon, 26 Feb 2024 18:57:50 +0000 Subject: [PATCH] Add RK3588 support. Rework the RK3568 support to take advantage of the PHY mode enum like the new RK3588 code. ok jmatthew@ --- sys/dev/fdt/if_dwqe_fdt.c | 171 +++++++++++++++++++++++++++++++------- sys/dev/ic/dwqevar.h | 3 +- 2 files changed, 145 insertions(+), 29 deletions(-) diff --git a/sys/dev/fdt/if_dwqe_fdt.c b/sys/dev/fdt/if_dwqe_fdt.c index 7e6afaba34d..1bdb8e0819c 100644 --- a/sys/dev/fdt/if_dwqe_fdt.c +++ b/sys/dev/fdt/if_dwqe_fdt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_dwqe_fdt.c,v 1.17 2023/10/10 07:11:50 stsp Exp $ */ +/* $OpenBSD: if_dwqe_fdt.c,v 1.18 2024/02/26 18:57:50 kettenis Exp $ */ /* * Copyright (c) 2008, 2019 Mark Kettenis * Copyright (c) 2017, 2022 Patrick Wildt @@ -73,6 +73,7 @@ void dwqe_setup_jh7110(struct dwqe_softc *); void dwqe_mii_statchg_jh7110(struct device *); void dwqe_setup_rk3568(struct dwqe_fdt_softc *); void dwqe_mii_statchg_rk3568(struct device *); +void dwqe_setup_rk3588(struct dwqe_fdt_softc *); void dwqe_mii_statchg_rk3588(struct device *); const struct cfattach dwqe_fdt_ca = { @@ -114,10 +115,12 @@ dwqe_fdt_attach(struct device *parent, struct device *self, void *aux) /* Decide GMAC id through address */ switch (faa->fa_reg[0].addr) { case 0xfe2a0000: /* RK3568 */ + case 0xfe1b0000: /* RK3588 */ case 0x16030000: /* JH7110 */ fsc->sc_gmac_id = 0; break; case 0xfe010000: /* RK3568 */ + case 0xfe1c0000: /* RK3588 */ case 0x16040000: /* JH7110 */ fsc->sc_gmac_id = 1; break; @@ -137,6 +140,8 @@ dwqe_fdt_attach(struct device *parent, struct device *self, void *aux) sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_TXID; else if (strcmp(phy_mode, "rgmii-id") == 0) sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_ID; + else if (strcmp(phy_mode, "rmii") == 0) + sc->sc_phy_mode = DWQE_PHY_MODE_RMII; else sc->sc_phy_mode = DWQE_PHY_MODE_UNKNOWN; @@ -162,11 +167,17 @@ dwqe_fdt_attach(struct device *parent, struct device *self, void *aux) if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac")) { clock_enable(faa->fa_node, "tx"); clock_enable(faa->fa_node, "gtx"); - } else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac")) { - clock_enable(faa->fa_node, "mac_clk_rx"); - clock_enable(faa->fa_node, "mac_clk_tx"); + } else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac") || + OF_is_compatible(faa->fa_node, "rockchip,rk3588-gmac")) { clock_enable(faa->fa_node, "aclk_mac"); clock_enable(faa->fa_node, "pclk_mac"); + clock_enable(faa->fa_node, "mac_clk_tx"); + clock_enable(faa->fa_node, "clk_mac_speed"); + if (strcmp(phy_mode, "rmii") == 0) { + clock_enable(faa->fa_node, "mac_clk_rx"); + clock_enable(faa->fa_node, "clk_mac_ref"); + clock_enable(faa->fa_node, "clk_mac_refout"); + } } delay(5000); @@ -175,6 +186,8 @@ dwqe_fdt_attach(struct device *parent, struct device *self, void *aux) dwqe_setup_jh7110(sc); else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac")) dwqe_setup_rk3568(fsc); + else if (OF_is_compatible(faa->fa_node, "rockchip,rk3588-gmac")) + dwqe_setup_rk3588(fsc); /* Power up PHY. */ phy_supply = OF_getpropint(faa->fa_node, "phy-supply", 0); @@ -329,6 +342,26 @@ dwqe_reset_phy(struct dwqe_softc *sc, uint32_t phy) #define RK3568_GMAC_TXCLK_DLY_SET(_v) ((1 << 0) << 16 | ((_v) << 0)) #define RK3568_GMAC_RXCLK_DLY_SET(_v) ((1 << 1) << 16 | ((_v) << 1)) +/* RK3588 registers */ +#define RK3588_GRF_GMAC_CON7 0x031c +#define RK3588_GMACx_RXCLK_DLY_ENA(id) ((1 << (2 * (id) + 3)) << 16 | (1 << (2 * (id) + 3))) +#define RK3588_GMACx_TXCLK_DLY_ENA(id) ((1 << (2 * (id) + 2)) << 16 | (1 << (2 * (id) + 2))) +#define RK3588_GRF_GMAC_CON8 0x0320 +#define RK3588_GRF_GMAC_CON9 0x0324 +#define RK3588_GMAC_CLK_RX_DL_CFG(val) ((0x7f << 8) << 16 | ((val) << 8)) +#define RK3588_GMAC_CLK_TX_DL_CFG(val) ((0x7f << 0) << 16 | ((val) << 0)) +#define RK3588_PHP_GRF_GMAC_CON0 0x0008 +#define RK3588_GMACx_PHY_INTF_SEL_RGMII(id) ((0x7 << (6 * (id) + 3)) << 16 | (0x1 << (6 * (id) + 3))) +#define RK3588_GMACx_PHY_INTF_SEL_RMII(id) ((0x7 << (6 * (id) + 3)) << 16 | (0x4 << (6 * (id) + 3))) +#define RK3588_PHP_GRF_CLK_CON1 0x0070 +#define RK3588_RMII_MODE_GMACx_RMII(id) ((0x1 << (5 * (id))) << 16 | (0x1 << (5 * (id)))) +#define RK3588_RMII_MODE_GMACx_RGMII(id) ((0x1 << (5 * (id))) << 16 | (0x0 << (5 * (id)))) +#define RK3588_MII_TX_CLK_SEL_RMII_2_5(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x1 << (5 * (id) + 2))) +#define RK3588_MII_TX_CLK_SEL_RMII_25(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x0 << (5 * (id) + 2))) +#define RK3588_MII_TX_CLK_SEL_RGMII_2_5(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x2 << (5 * (id) + 2))) +#define RK3588_MII_TX_CLK_SEL_RGMII_25(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x3 << (5 * (id) + 2))) +#define RK3588_MII_TX_CLK_SEL_RGMII_125(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x0 << (5 * (id) + 2))) + void dwqe_mii_statchg_jh7110_task(void *); void dwqe_mii_statchg_rk3568_task(void *); @@ -410,7 +443,6 @@ void dwqe_setup_rk3568(struct dwqe_fdt_softc *fsc) { struct dwqe_softc *sc = &fsc->sc_sc; - char phy_mode[32]; struct regmap *rm; uint32_t grf; int tx_delay, rx_delay; @@ -421,30 +453,35 @@ dwqe_setup_rk3568(struct dwqe_fdt_softc *fsc) if (rm == NULL) return; - if (OF_getprop(sc->sc_node, "phy-mode", - phy_mode, sizeof(phy_mode)) <= 0) + switch (sc->sc_phy_mode) { + case DWQE_PHY_MODE_RGMII: + case DWQE_PHY_MODE_RGMII_ID: + case DWQE_PHY_MODE_RGMII_RXID: + case DWQE_PHY_MODE_RGMII_TXID: + iface = RK3568_GMAC_PHY_INTF_SEL_RGMII; + break; + case DWQE_PHY_MODE_RMII: + iface = RK3568_GMAC_PHY_INTF_SEL_RMII; + break; + default: return; + } tx_delay = OF_getpropint(sc->sc_node, "tx_delay", 0x30); rx_delay = OF_getpropint(sc->sc_node, "rx_delay", 0x10); - - if (strcmp(phy_mode, "rgmii") == 0) { - iface = RK3568_GMAC_PHY_INTF_SEL_RGMII; - } else if (strcmp(phy_mode, "rgmii-id") == 0) { - iface = RK3568_GMAC_PHY_INTF_SEL_RGMII; - /* id is "internal delay" */ + switch (sc->sc_phy_mode) { + case DWQE_PHY_MODE_RGMII_ID: tx_delay = rx_delay = 0; - } else if (strcmp(phy_mode, "rgmii-rxid") == 0) { - iface = RK3568_GMAC_PHY_INTF_SEL_RGMII; + break; + case DWQE_PHY_MODE_RGMII_RXID: rx_delay = 0; - } else if (strcmp(phy_mode, "rgmii-txid") == 0) { - iface = RK3568_GMAC_PHY_INTF_SEL_RGMII; + break; + case DWQE_PHY_MODE_RGMII_TXID: tx_delay = 0; - } else if (strcmp(phy_mode, "rmii") == 0) { - iface = RK3568_GMAC_PHY_INTF_SEL_RMII; - tx_delay = rx_delay = 0; - } else - return; + break; + default: + break; + } /* Program clock delay lines. */ regmap_write_4(rm, RK3568_GRF_GMACx_CON0(fsc->sc_gmac_id), @@ -489,20 +526,98 @@ dwqe_mii_statchg_rk3568(struct device *self) task_add(systq, &sc->sc_statchg_task); } +void +dwqe_setup_rk3588(struct dwqe_fdt_softc *fsc) +{ + struct dwqe_softc *sc = &fsc->sc_sc; + struct regmap *rm; + struct regmap *php_rm; + uint32_t grf, php_grf; + int tx_delay, rx_delay; + uint32_t iface, clk; + + grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0); + rm = regmap_byphandle(grf); + if (rm == NULL) + return; + + php_grf = OF_getpropint(sc->sc_node, "rockchip,php-grf", 0); + php_rm = regmap_byphandle(php_grf); + if (php_rm == NULL) + return; + + switch (sc->sc_phy_mode) { + case DWQE_PHY_MODE_RGMII: + case DWQE_PHY_MODE_RGMII_ID: + case DWQE_PHY_MODE_RGMII_RXID: + case DWQE_PHY_MODE_RGMII_TXID: + iface = RK3588_GMACx_PHY_INTF_SEL_RGMII(fsc->sc_gmac_id); + clk = RK3588_RMII_MODE_GMACx_RGMII(fsc->sc_gmac_id); + sc->sc_clk_sel_2_5 = + RK3588_MII_TX_CLK_SEL_RGMII_2_5(fsc->sc_gmac_id); + sc->sc_clk_sel_25 = + RK3588_MII_TX_CLK_SEL_RGMII_25(fsc->sc_gmac_id); + sc->sc_clk_sel_125 = + RK3588_MII_TX_CLK_SEL_RGMII_125(fsc->sc_gmac_id); + break; + case DWQE_PHY_MODE_RMII: + iface = RK3588_GMACx_PHY_INTF_SEL_RMII(fsc->sc_gmac_id); + clk = RK3588_RMII_MODE_GMACx_RMII(fsc->sc_gmac_id); + sc->sc_clk_sel_2_5 = + RK3588_MII_TX_CLK_SEL_RMII_2_5(fsc->sc_gmac_id); + sc->sc_clk_sel_25 = + RK3588_MII_TX_CLK_SEL_RMII_25(fsc->sc_gmac_id); + break; + default: + return; + } + + tx_delay = OF_getpropint(sc->sc_node, "tx_delay", 0x30); + rx_delay = OF_getpropint(sc->sc_node, "rx_delay", 0x10); + switch (sc->sc_phy_mode) { + case DWQE_PHY_MODE_RGMII_ID: + tx_delay = rx_delay = 0; + break; + case DWQE_PHY_MODE_RGMII_RXID: + rx_delay = 0; + break; + case DWQE_PHY_MODE_RGMII_TXID: + tx_delay = 0; + break; + default: + break; + } + + /* Set interface and clock. */ + regmap_write_4(php_rm, RK3588_PHP_GRF_GMAC_CON0, iface); + regmap_write_4(php_rm, RK3588_PHP_GRF_CLK_CON1, clk); + + /* Enable clock delay. */ + regmap_write_4(rm, RK3588_GRF_GMAC_CON7, + RK3588_GMACx_TXCLK_DLY_ENA(fsc->sc_gmac_id) | + RK3588_GMACx_RXCLK_DLY_ENA(fsc->sc_gmac_id)); + + /* Program clock delay lines. */ + regmap_write_4(rm, fsc->sc_gmac_id == 1 ? + RK3588_GRF_GMAC_CON9 : RK3588_GRF_GMAC_CON8, + RK3588_GMAC_CLK_TX_DL_CFG(tx_delay) | + RK3588_GMAC_CLK_RX_DL_CFG(rx_delay)); +} + void dwqe_mii_statchg_rk3588(struct device *self) { struct dwqe_softc *sc = (void *)self; struct ifnet *ifp = &sc->sc_ac.ac_if; - struct regmap *rm; - uint32_t grf; + struct regmap *php_rm; + uint32_t php_grf; uint32_t gmac_clk_sel = 0; dwqe_mii_statchg(self); - grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0); - rm = regmap_byphandle(grf); - if (rm == NULL) + php_grf = OF_getpropint(sc->sc_node, "rockchip,php-grf", 0); + php_rm = regmap_byphandle(php_grf); + if (php_rm == NULL) return; switch (ifp->if_baudrate) { @@ -517,5 +632,5 @@ dwqe_mii_statchg_rk3588(struct device *self) break; } - regmap_write_4(rm, sc->sc_clk_sel, gmac_clk_sel); + regmap_write_4(php_rm, RK3588_PHP_GRF_CLK_CON1, gmac_clk_sel); } diff --git a/sys/dev/ic/dwqevar.h b/sys/dev/ic/dwqevar.h index c4a8f138a05..d7d32b1c01f 100644 --- a/sys/dev/ic/dwqevar.h +++ b/sys/dev/ic/dwqevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dwqevar.h,v 1.10 2023/11/11 16:50:25 stsp Exp $ */ +/* $OpenBSD: dwqevar.h,v 1.11 2024/02/26 18:57:50 kettenis Exp $ */ /* * Copyright (c) 2008, 2019 Mark Kettenis * Copyright (c) 2017, 2022 Patrick Wildt @@ -18,6 +18,7 @@ enum dwqe_phy_mode { DWQE_PHY_MODE_UNKNOWN, + DWQE_PHY_MODE_RMII, DWQE_PHY_MODE_RGMII, DWQE_PHY_MODE_RGMII_ID, DWQE_PHY_MODE_RGMII_TXID, -- 2.20.1