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