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