Commit Diff


commit - 8871918f14026359808711c37392681999f46a41
commit + 354d02c5e11292ce7e503ac5dad08eef9d7d648b
blob - 1bdb8e0819cf0fdfdedddbfee22e3eb01686a699
blob + 910b3e1285e5496e2bfaff0b7f24b23813a6ffe5
--- sys/dev/fdt/if_dwqe_fdt.c
+++ sys/dev/fdt/if_dwqe_fdt.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: if_dwqe_fdt.c,v 1.18 2024/02/26 18:57:50 kettenis Exp $	*/
+/*	$OpenBSD: if_dwqe_fdt.c,v 1.19 2025/05/17 13:30:31 kettenis Exp $	*/
 /*
  * Copyright (c) 2008, 2019 Mark Kettenis <kettenis@openbsd.org>
  * Copyright (c) 2017, 2022 Patrick Wildt <patrick@blueri.se>
@@ -71,6 +71,8 @@ int	dwqe_fdt_match(struct device *, void *, void *);
 void	dwqe_fdt_attach(struct device *, struct device *, void *);
 void	dwqe_setup_jh7110(struct dwqe_softc *);
 void	dwqe_mii_statchg_jh7110(struct device *);
+void	dwqe_setup_rk3528(struct dwqe_fdt_softc *);
+void	dwqe_mii_statchg_rk3528(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 *);
@@ -114,11 +116,13 @@ dwqe_fdt_attach(struct device *parent, struct device *
 
 	/* Decide GMAC id through address */
 	switch (faa->fa_reg[0].addr) {
+	case 0xffbd0000:	/* RK3528 */
 	case 0xfe2a0000:	/* RK3568 */
 	case 0xfe1b0000:	/* RK3588 */
 	case 0x16030000:	/* JH7110 */
 		fsc->sc_gmac_id = 0;
 		break;
+	case 0xffbe0000:	/* RK3528 */
 	case 0xfe010000:	/* RK3568 */
 	case 0xfe1c0000:	/* RK3588 */
 	case 0x16040000:	/* JH7110 */
@@ -167,7 +171,8 @@ dwqe_fdt_attach(struct device *parent, struct device *
 	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") ||
+	} else if (OF_is_compatible(faa->fa_node, "rockchip,rk3528-gmac") ||
+	    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");
@@ -184,6 +189,8 @@ dwqe_fdt_attach(struct device *parent, struct device *
 	/* Do hardware specific initializations. */
 	if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac"))
 		dwqe_setup_jh7110(sc);
+	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3528-gmac"))
+		dwqe_setup_rk3528(fsc);
 	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"))
@@ -262,6 +269,8 @@ dwqe_fdt_attach(struct device *parent, struct device *
 	if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac") &&
 	    !OF_getpropbool(faa->fa_node, "starfive,tx-use-rgmii-clk"))
 		sc->sc_mii.mii_statchg = dwqe_mii_statchg_jh7110;
+	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3528-gmac"))
+		sc->sc_mii.mii_statchg = dwqe_mii_statchg_rk3528;
 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac"))
 		sc->sc_mii.mii_statchg = dwqe_mii_statchg_rk3568;
 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3588-gmac"))
@@ -332,6 +341,25 @@ dwqe_reset_phy(struct dwqe_softc *sc, uint32_t phy)
 #define JH7110_PHY_INTF_RGMII		1
 #define JH7110_PHY_INTF_RMII		4
 
+/* RK3528 registers */
+#define RK3528_VO_GRF_GMAC_CON		0x0018
+#define  RK3528_GMAC0_PHY_INTF_SEL_RMII		((1U << 1) << 16 | (1 << 1))
+#define  RK3528_GMAC0_CLK_RMII_DIV2		((1U << 3) << 16 | (1 << 3))
+#define  RK3528_GMAC0_CLK_RMII_DIV20		((1U << 3) << 16 | (0 << 3))
+#define RK3528_VPU_GRF_GMAC_CON5	0x0018
+#define  RK3528_GMAC1_PHY_INTF_SEL_RMII		((1U << 8) << 16 | (1 << 8))
+#define  RK3528_GMAC1_PHY_INTF_SEL_RGMII	((1U << 8) << 16 | (0 << 8))
+#define  RK3528_GMAC1_CLK_RMII_DIV2		((1U << 10) << 16 | (1 << 10))
+#define  RK3528_GMAC1_CLK_RMII_DIV20		((1U << 10) << 16 | (0 << 10))
+#define  RK3528_GMAC_TXCLK_DLY_SET(_v)		((1U << 14) << 16 | ((_v) << 14))
+#define  RK3528_GMAC_RXCLK_DLY_SET(_v)		((1U << 15) << 16 | ((_v) << 15))
+#define  RK3528_GMAC1_CLK_RGMII_DIV1	((0x3U << 10) << 16 | (0x0 << 10))
+#define  RK3528_GMAC1_CLK_RGMII_DIV5	((0x3U << 10) << 16 | (0x3 << 10))
+#define  RK3528_GMAC1_CLK_RGMII_DIV50	((0x3U << 10) << 16 | (0x2 << 10))
+#define RK3528_VPU_GRF_GMAC_CON6	0x001c
+#define  RK3528_GMAC_CLK_RX_DL_CFG(_v)		((0xffU << 8) << 16 | ((_v) << 8))
+#define  RK3528_GMAC_CLK_TX_DL_CFG(_v)		((0xffU << 0) << 16 | ((_v) << 0))
+
 /* RK3568 registers */
 #define RK3568_GRF_GMACx_CON0(x)	(0x0380 + (x) * 0x8)
 #define  RK3568_GMAC_CLK_RX_DL_CFG(val)		((0x7f << 8) << 16 | ((val) << 8))
@@ -440,6 +468,122 @@ dwqe_mii_statchg_jh7110(struct device *self)
 }
 
 void
+dwqe_setup_rk3528(struct dwqe_fdt_softc *fsc)
+{
+	struct dwqe_softc *sc = &fsc->sc_sc;
+	struct regmap *rm;
+	uint32_t grf;
+	int tx_delay, rx_delay;
+	uint32_t iface;
+
+	grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
+	rm = regmap_byphandle(grf);
+	if (rm == NULL)
+		return;
+
+	if (fsc->sc_gmac_id == 0) {
+		regmap_write_4(rm, RK3528_VO_GRF_GMAC_CON,
+		    RK3528_GMAC0_PHY_INTF_SEL_RMII |
+		    RK3528_GMAC0_CLK_RMII_DIV2);
+		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 = RK3528_GMAC1_PHY_INTF_SEL_RGMII;
+		break;
+	case DWQE_PHY_MODE_RMII:
+		iface = RK3528_GMAC1_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);
+	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;
+	}
+
+	/* Program clock delay lines. */
+	regmap_write_4(rm, RK3528_VPU_GRF_GMAC_CON6,
+	    RK3528_GMAC_CLK_TX_DL_CFG(tx_delay) |
+	    RK3528_GMAC_CLK_RX_DL_CFG(rx_delay));
+
+	/* Set interface and enable/disable clock delay. */
+	regmap_write_4(rm, RK3528_VPU_GRF_GMAC_CON5, iface |
+	    RK3528_GMAC_TXCLK_DLY_SET(tx_delay > 0 ? 1 : 0) |
+	    RK3528_GMAC_RXCLK_DLY_SET(rx_delay > 0 ? 1 : 0));
+}
+
+void
+dwqe_mii_statchg_rk3528(struct device *self)
+{
+	struct dwqe_fdt_softc *fsc = (void *)self;
+	struct dwqe_softc *sc = &fsc->sc_sc;
+	struct ifnet *ifp = &sc->sc_ac.ac_if;
+	struct regmap *rm;
+	uint32_t grf;
+	uint32_t reg, clk_sel = 0;
+
+	dwqe_mii_statchg(self);
+
+	grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
+	rm = regmap_byphandle(grf);
+	if (rm == NULL)
+		return;
+
+	if (fsc->sc_gmac_id == 1)
+		reg = RK3528_VPU_GRF_GMAC_CON5;
+	else
+		reg = RK3528_VO_GRF_GMAC_CON;
+
+	if (sc->sc_phy_mode == DWQE_PHY_MODE_RMII) {
+		switch (ifp->if_baudrate) {
+		case IF_Mbps(10):
+			if (fsc->sc_gmac_id == 1)
+				clk_sel = RK3528_GMAC1_CLK_RMII_DIV20;
+			else
+				clk_sel = RK3528_GMAC0_CLK_RMII_DIV20;
+			break;
+		case IF_Mbps(100):
+			if (fsc->sc_gmac_id == 1)
+				clk_sel = RK3528_GMAC1_CLK_RMII_DIV2;
+			else
+				clk_sel = RK3528_GMAC0_CLK_RMII_DIV2;
+			break;
+		}
+	} else {
+		switch (ifp->if_baudrate) {
+		case IF_Mbps(10):
+			clk_sel = RK3528_GMAC1_CLK_RGMII_DIV50;
+			break;
+		case IF_Mbps(100):
+			clk_sel = RK3528_GMAC1_CLK_RGMII_DIV5;
+			break;
+		case IF_Mbps(1000):
+			clk_sel = RK3528_GMAC1_CLK_RGMII_DIV1;
+			break;
+		}
+	}
+
+	regmap_write_4(rm, reg, clk_sel);
+}
+
+void
 dwqe_setup_rk3568(struct dwqe_fdt_softc *fsc)
 {
 	struct dwqe_softc *sc = &fsc->sc_sc;