1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Rockchip XPCS platform device driver 4 * 5 * Based on the Synopsys DesignWare XPCS platform driver. 6 * Copyright (C) 2024 Serge Semin 7 * 8 * Adapted for Rockchip SoCs, with reference to the Rockchip OEM driver. 9 * Copyright (C) 2026 Coia Prant 10 */ 11 12 #include <linux/atomic.h> 13 #include <linux/bitfield.h> 14 #include <linux/clk.h> 15 #include <linux/device.h> 16 #include <linux/io.h> 17 #include <linux/iopoll.h> 18 #include <linux/math.h> 19 #include <linux/mdio.h> 20 #include <linux/module.h> 21 #include <linux/of.h> 22 #include <linux/of_platform.h> 23 #include <linux/pcs/pcs-xpcs-rk.h> 24 #include <linux/phy.h> 25 #include <linux/phy/phy.h> 26 #include <linux/platform_device.h> 27 #include <linux/pm_domain.h> 28 #include <linux/pm_runtime.h> 29 #include <linux/property.h> 30 #include <linux/sizes.h> 31 #include <linux/time.h> 32 33 #include "pcs-xpcs.h" 34 35 struct dw_xpcs_rk { 36 struct platform_device *pdev; 37 struct mii_bus *bus; 38 void __iomem *reg_base; 39 struct phy *serdes_phy; 40 struct clk *csr_clk; 41 struct clk *eee_clk; 42 u8 eee_mult_fact; 43 }; 44 45 static ptrdiff_t xpcs_rk_addr_format(int dev, int reg) 46 { 47 return FIELD_PREP(0x70000, dev) | FIELD_PREP(0xffff, reg); 48 } 49 50 static int xpcs_rk_read_reg(struct dw_xpcs_rk *pxpcs, int dev, int reg) 51 { 52 ptrdiff_t csr; 53 int ret; 54 55 csr = xpcs_rk_addr_format(dev, reg); 56 57 ret = pm_runtime_resume_and_get(&pxpcs->pdev->dev); 58 if (ret) 59 return ret; 60 61 ret = readl(pxpcs->reg_base + (csr << 2)) & 0xffff; 62 63 pm_runtime_put(&pxpcs->pdev->dev); 64 return ret; 65 } 66 67 static int xpcs_rk_write_reg(struct dw_xpcs_rk *pxpcs, int dev, int reg, u16 val) 68 { 69 ptrdiff_t csr; 70 int ret; 71 72 csr = xpcs_rk_addr_format(dev, reg); 73 74 ret = pm_runtime_resume_and_get(&pxpcs->pdev->dev); 75 if (ret) 76 return ret; 77 78 writel(val, pxpcs->reg_base + (csr << 2)); 79 80 pm_runtime_put(&pxpcs->pdev->dev); 81 return 0; 82 } 83 84 #define ROCKCHIP_MMD_MII1 2 85 #define ROCKCHIP_MMD_MII2 3 86 #define ROCKCHIP_MMD_MII3 4 87 #define ROCKCHIP_MMD_PMAPMD 6 88 #define ROCKCHIP_MMD_MII 7 89 90 static bool xpcs_rk_mdio_addr_validate(int addr) 91 { 92 return !(addr < 0 || addr > 3); 93 } 94 95 static int xpcs_rk_mdio_read_remapping(int addr, int dev) 96 { 97 switch (dev) { 98 case MDIO_MMD_PMAPMD: 99 return ROCKCHIP_MMD_PMAPMD; 100 case MDIO_MMD_VEND2: 101 break; 102 default: 103 return -ENXIO; 104 } 105 106 /* 107 * Reads are redirected by hardware to the port's read-only mirror; 108 * only writes have to be targeted at MII (see the write path). 109 */ 110 switch (addr) { 111 case 0: 112 return ROCKCHIP_MMD_MII; 113 case 1: 114 return ROCKCHIP_MMD_MII1; 115 case 2: 116 return ROCKCHIP_MMD_MII2; 117 case 3: 118 return ROCKCHIP_MMD_MII3; 119 default: 120 return -ENODEV; 121 } 122 } 123 124 static int xpcs_rk_mdio_write_remapping(int addr, int dev, int reg) 125 { 126 switch (dev) { 127 case MDIO_MMD_PMAPMD: 128 return ROCKCHIP_MMD_PMAPMD; 129 case MDIO_MMD_VEND2: 130 break; 131 default: 132 return -ENXIO; 133 } 134 135 /* 136 * These registers physically live only in MII (the management port). 137 * Ports 1-3 expose read-only mirrors of these bits, so writes must 138 * always target MII; the read path remaps per address and the 139 * hardware redirects to the port's mirror. 140 */ 141 switch (reg) { 142 case DW_VR_MII_AN_CTRL: 143 case DW_VR_MII_AN_INTR_STS: 144 case DW_VR_MII_EEE_MCTRL0: 145 case DW_VR_MII_EEE_MCTRL1: 146 case DW_VR_MII_DIG_CTRL2: 147 return ROCKCHIP_MMD_MII; 148 default: 149 break; 150 } 151 152 switch (addr) { 153 case 0: 154 return ROCKCHIP_MMD_MII; 155 case 1: 156 return ROCKCHIP_MMD_MII1; 157 case 2: 158 return ROCKCHIP_MMD_MII2; 159 case 3: 160 return ROCKCHIP_MMD_MII3; 161 default: 162 return -ENODEV; 163 } 164 } 165 166 static int xpcs_rk_read_c22(struct mii_bus *bus, int addr, int reg) 167 { 168 struct dw_xpcs_rk *pxpcs = bus->priv; 169 int dev; 170 171 if (!xpcs_rk_mdio_addr_validate(addr)) 172 return -ENODEV; 173 174 dev = xpcs_rk_mdio_read_remapping(addr, MDIO_MMD_VEND2); 175 if (dev < 0) 176 return 0xffff; 177 178 return xpcs_rk_read_reg(pxpcs, dev, reg); 179 } 180 181 static int xpcs_rk_write_c22(struct mii_bus *bus, int addr, int reg, u16 val) 182 { 183 struct dw_xpcs_rk *pxpcs = bus->priv; 184 int dev; 185 186 if (!xpcs_rk_mdio_addr_validate(addr)) 187 return -ENODEV; 188 189 dev = xpcs_rk_mdio_write_remapping(addr, MDIO_MMD_VEND2, reg); 190 if (dev < 0) 191 return 0; 192 193 return xpcs_rk_write_reg(pxpcs, dev, reg, val); 194 } 195 196 static int xpcs_rk_read_c45(struct mii_bus *bus, int addr, int dev, int reg) 197 { 198 struct dw_xpcs_rk *pxpcs = bus->priv; 199 200 if (!xpcs_rk_mdio_addr_validate(addr)) 201 return -ENODEV; 202 203 dev = xpcs_rk_mdio_read_remapping(addr, dev); 204 if (dev < 0) 205 return 0xffff; 206 207 return xpcs_rk_read_reg(pxpcs, dev, reg); 208 } 209 210 static int xpcs_rk_write_c45(struct mii_bus *bus, int addr, int dev, int reg, u16 val) 211 { 212 struct dw_xpcs_rk *pxpcs = bus->priv; 213 214 if (!xpcs_rk_mdio_addr_validate(addr)) 215 return -ENODEV; 216 217 dev = xpcs_rk_mdio_write_remapping(addr, dev, reg); 218 if (dev < 0) 219 return 0; 220 221 return xpcs_rk_write_reg(pxpcs, dev, reg, val); 222 } 223 224 static struct dw_xpcs_rk *xpcs_rk_create_data(struct platform_device *pdev) 225 { 226 struct dw_xpcs_rk *pxpcs; 227 228 pxpcs = devm_kzalloc(&pdev->dev, sizeof(*pxpcs), GFP_KERNEL); 229 if (!pxpcs) 230 return ERR_PTR(-ENOMEM); 231 232 pxpcs->pdev = pdev; 233 234 dev_set_drvdata(&pdev->dev, pxpcs); 235 236 return pxpcs; 237 } 238 239 static int xpcs_rk_serdes_phy_init(struct dw_xpcs_rk *pxpcs) 240 { 241 struct device *dev = &pxpcs->pdev->dev; 242 243 pxpcs->serdes_phy = devm_phy_get(dev, NULL); 244 if (IS_ERR(pxpcs->serdes_phy)) 245 return dev_err_probe(dev, PTR_ERR(pxpcs->serdes_phy), 246 "Failed to get SerDes PHY\n"); 247 248 return 0; 249 } 250 251 static void xpcs_rk_serdes_phy_poweroff(void *data) 252 { 253 struct dw_xpcs_rk *pxpcs = data; 254 struct device *dev = &pxpcs->pdev->dev; 255 256 phy_power_off(pxpcs->serdes_phy); 257 phy_exit(pxpcs->serdes_phy); 258 259 dev_pm_genpd_rpm_always_on(dev, false); 260 } 261 262 static int xpcs_rk_serdes_phy_poweron(struct dw_xpcs_rk *pxpcs) 263 { 264 struct device *dev = &pxpcs->pdev->dev; 265 int ret; 266 267 /* 268 * The power domain is required and must be enabled, which allows us to 269 * dynamically turn the CSR clock on/off using PM while keeping the PCS 270 * powered on. 271 */ 272 ret = dev_pm_genpd_rpm_always_on(dev, true); 273 if (ret) { 274 dev_err(dev, "Failed to power on power-domains\n"); 275 return ret; 276 } 277 278 ret = phy_init(pxpcs->serdes_phy); 279 if (ret) { 280 dev_err(dev, "Failed to init SerDes PHY\n"); 281 goto pm_domain; 282 } 283 284 ret = phy_power_on(pxpcs->serdes_phy); 285 if (ret) { 286 dev_err(dev, "Failed to power on SerDes PHY\n"); 287 goto serdes_phy; 288 } 289 290 ret = devm_add_action_or_reset(dev, xpcs_rk_serdes_phy_poweroff, pxpcs); 291 if (ret) { 292 dev_err(dev, "Failed to register devm for SerDes PHY: %d\n", ret); 293 return ret; 294 } 295 296 return 0; 297 298 serdes_phy: 299 phy_exit(pxpcs->serdes_phy); 300 pm_domain: 301 dev_pm_genpd_rpm_always_on(dev, false); 302 return ret; 303 } 304 305 static int xpcs_rk_init_res(struct dw_xpcs_rk *pxpcs) 306 { 307 struct platform_device *pdev = pxpcs->pdev; 308 struct device *dev = &pdev->dev; 309 struct resource *res; 310 311 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 312 if (!res) { 313 dev_err(dev, "No reg-space found\n"); 314 return -EINVAL; 315 } 316 317 if (resource_size(res) < SZ_2M) { 318 dev_err(dev, "Invalid reg-space size\n"); 319 return -EINVAL; 320 } 321 322 pxpcs->reg_base = devm_ioremap_resource(dev, res); 323 if (IS_ERR(pxpcs->reg_base)) { 324 dev_err(dev, "Failed to map reg-space\n"); 325 return PTR_ERR(pxpcs->reg_base); 326 } 327 328 return 0; 329 } 330 331 static void xpcs_rk_exit_clk(void *data) 332 { 333 struct dw_xpcs_rk *pxpcs = data; 334 struct device *dev = &pxpcs->pdev->dev; 335 336 pm_runtime_force_suspend(dev); 337 clk_disable_unprepare(pxpcs->eee_clk); 338 } 339 340 static int xpcs_rk_init_clk(struct dw_xpcs_rk *pxpcs) 341 { 342 struct device *dev = &pxpcs->pdev->dev; 343 unsigned long rate; 344 u64 mult; 345 int ret; 346 347 pxpcs->csr_clk = devm_clk_get(dev, "csr"); 348 if (IS_ERR(pxpcs->csr_clk)) 349 return dev_err_probe(dev, PTR_ERR(pxpcs->csr_clk), 350 "Failed to get CSR clock\n"); 351 352 pxpcs->eee_clk = devm_clk_get(dev, "eee"); 353 if (IS_ERR(pxpcs->eee_clk)) 354 return dev_err_probe(dev, PTR_ERR(pxpcs->eee_clk), 355 "Failed to get EEE clock\n"); 356 357 ret = clk_prepare_enable(pxpcs->eee_clk); 358 if (ret) { 359 dev_err(dev, "Failed to enable EEE clock\n"); 360 return ret; 361 } 362 363 pm_runtime_set_suspended(dev); 364 pm_runtime_enable(dev); 365 366 ret = devm_add_action_or_reset(dev, xpcs_rk_exit_clk, pxpcs); 367 if (ret) { 368 dev_err(dev, "Failed to register devm for xpcs_rk_exit_clk: %d\n", ret); 369 return ret; 370 } 371 372 /* 373 * Compute the multiplier for the EEE clock so that 374 * clk_eee_period * (mult_fact + 1) falls within 80..120 ns. 375 * 376 * On RK3568, clk_xpcs_eee is muxed between gpll200 (200 MHz, 5 ns) 377 * and cpll125 (125 MHz, 8 ns), selected by CRU_CLKSEL_CON29 bit 13. 378 * The reset value is 0 (200 MHz), but derive the value at runtime to 379 * stay correct if the mux is changed by a board. 380 * 381 * Use a 64-bit intermediate: on 32-bit builds, 100 * 200000000 382 * does not fit in unsigned long. Clamp to the 4-bit 383 * DW_VR_MII_EEE_MULT_FACT_100NS field. The mux only provides 384 * 125 MHz or 200 MHz, so the rate cannot drop below the 5 MHz 385 * threshold where DIV_ROUND_CLOSEST_ULL() would return 0 and the 386 * subtraction below would underflow. 387 */ 388 rate = clk_get_rate(pxpcs->eee_clk); 389 if (!rate) 390 return dev_err_probe(dev, -EINVAL, "Invalid EEE clock rate\n"); 391 392 mult = DIV_ROUND_CLOSEST_ULL(100ULL * rate, NSEC_PER_SEC) - 1; 393 pxpcs->eee_mult_fact = min_t(u64, mult, 15); 394 return 0; 395 } 396 397 static int xpcs_rk_init_bus(struct dw_xpcs_rk *pxpcs) 398 { 399 struct device *dev = &pxpcs->pdev->dev; 400 static atomic_t id = ATOMIC_INIT(-1); 401 struct mii_bus *bus; 402 int ret; 403 404 bus = devm_mdiobus_alloc_size(dev, 0); 405 if (!bus) 406 return -ENOMEM; 407 408 bus->name = "Rockchip DW XPCS MCI/APB3"; 409 bus->read = xpcs_rk_read_c22; 410 bus->write = xpcs_rk_write_c22; 411 bus->read_c45 = xpcs_rk_read_c45; 412 bus->write_c45 = xpcs_rk_write_c45; 413 bus->phy_mask = ~0; 414 bus->parent = dev; 415 bus->priv = pxpcs; 416 417 snprintf(bus->id, MII_BUS_ID_SIZE, 418 "rockchip_dwxpcs-%x", atomic_inc_return(&id)); 419 420 /* 421 * MDIO-bus here serves as just a back-end engine abstracting out 422 * the MDIO and MCI/APB3 IO interfaces utilized for the Rockchip DWXPCS CSRs 423 * access. 424 */ 425 ret = devm_mdiobus_register(dev, bus); 426 if (ret) { 427 dev_err(dev, "Failed to create MDIO bus\n"); 428 return ret; 429 } 430 431 pxpcs->bus = bus; 432 return 0; 433 } 434 435 static int xpcs_rk_probe(struct platform_device *pdev) 436 { 437 struct dw_xpcs_rk *pxpcs; 438 int ret; 439 440 pxpcs = xpcs_rk_create_data(pdev); 441 if (IS_ERR(pxpcs)) 442 return PTR_ERR(pxpcs); 443 444 /* 445 * The XPCS lives in the PD_PIPE power domain. The domain must be 446 * powered on before any register access, otherwise the SoC will 447 * trigger a synchronous external abort (SError). 448 * 449 * Accessing the XPCS registers also requires a TX clock from the 450 * SerDes, which is needed for the soft reset. 451 */ 452 ret = xpcs_rk_serdes_phy_init(pxpcs); 453 if (ret) 454 return ret; 455 456 ret = xpcs_rk_serdes_phy_poweron(pxpcs); 457 if (ret) 458 return ret; 459 460 ret = xpcs_rk_init_res(pxpcs); 461 if (ret) 462 return ret; 463 464 ret = xpcs_rk_init_clk(pxpcs); 465 if (ret) 466 return ret; 467 468 ret = xpcs_rk_init_bus(pxpcs); 469 if (ret) 470 return ret; 471 472 return 0; 473 } 474 475 static const struct of_device_id xpcs_rk_of_ids[] = { 476 { .compatible = "rockchip,rk3568-xpcs" }, 477 { /* sentinel */ }, 478 }; 479 MODULE_DEVICE_TABLE(of, xpcs_rk_of_ids); 480 481 struct dw_xpcs *xpcs_rk_create(struct device *dev, struct device_node *pcs, int port) 482 { 483 struct platform_device *pdev; 484 struct dw_xpcs_rk *pxpcs; 485 struct dw_xpcs *xpcs; 486 487 if (!of_device_is_available(pcs)) 488 return ERR_PTR(-ENODEV); 489 490 if (!of_match_node(xpcs_rk_of_ids, pcs)) 491 return ERR_PTR(-EINVAL); 492 493 if (!xpcs_rk_mdio_addr_validate(port)) 494 return ERR_PTR(-EINVAL); 495 496 pdev = of_find_device_by_node(pcs); 497 if (!pdev) 498 return ERR_PTR(-EPROBE_DEFER); 499 500 /* 501 * Establish the device link before reading the supplier's drvdata. 502 * device_link_add() does not fail on a supplier that is unbinding; 503 * it creates the link in DL_STATE_SUPPLIER_UNBIND. 504 * 505 * The check below only confirms that the supplier is bound at this 506 * point. It does not fully protect against a concurrent unbind 507 * between here and xpcs_create_mdiodev(); closing that window would 508 * require reading a managed link's status or device_lock(), neither 509 * of which is acceptable on this path. The window is small and 510 * requires an explicit unbind from userspace. Discussed on 511 * driver-core. 512 * 513 * The link is released automatically when the consumer device is 514 * destroyed (DL_FLAG_AUTOREMOVE_CONSUMER), so no explicit 515 * device_link_remove() is needed on the failure paths. 516 */ 517 if (!device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_CONSUMER)) { 518 put_device(&pdev->dev); 519 return ERR_PTR(-EPROBE_DEFER); 520 } 521 522 if (READ_ONCE(pdev->dev.links.status) != DL_DEV_DRIVER_BOUND) { 523 put_device(&pdev->dev); 524 return ERR_PTR(-EPROBE_DEFER); 525 } 526 527 pxpcs = platform_get_drvdata(pdev); 528 if (!pxpcs || !pxpcs->bus) { 529 put_device(&pdev->dev); 530 return ERR_PTR(-EPROBE_DEFER); 531 } 532 533 xpcs = xpcs_create_mdiodev(pxpcs->bus, port); 534 if (IS_ERR(xpcs)) { 535 put_device(&pdev->dev); 536 return xpcs; 537 } 538 539 xpcs_config_eee_mult_fact(xpcs, pxpcs->eee_mult_fact); 540 put_device(&pdev->dev); 541 return xpcs; 542 } 543 EXPORT_SYMBOL_GPL(xpcs_rk_create); 544 545 static int xpcs_rk_pm_runtime_suspend(struct device *dev) 546 { 547 struct dw_xpcs_rk *pxpcs = dev_get_drvdata(dev); 548 549 clk_disable_unprepare(pxpcs->csr_clk); 550 551 return 0; 552 } 553 554 static int xpcs_rk_pm_runtime_resume(struct device *dev) 555 { 556 struct dw_xpcs_rk *pxpcs = dev_get_drvdata(dev); 557 558 return clk_prepare_enable(pxpcs->csr_clk); 559 } 560 561 static int xpcs_rk_system_suspend(struct device *dev) 562 { 563 /* 564 * Keep the PD_PIPE power domain on during system suspend. 565 * 566 * PD_PIPE is shared with SATA/PCIe and would be powered down by 567 * genpd once all its consumers are suspended, killing the SerDes 568 * and breaking MAC WoL. Mark the XPCS as part of the wakeup path 569 * so genpd keeps the domain on. Unconditional because the XPCS 570 * core has no callback to convey the MAC WoL state. 571 */ 572 device_set_wakeup_path(dev); 573 return 0; 574 } 575 576 static int xpcs_rk_system_resume(struct device *dev) 577 { 578 return 0; 579 } 580 581 static _DEFINE_DEV_PM_OPS(xpcs_rk_pm_ops, 582 xpcs_rk_system_suspend, xpcs_rk_system_resume, 583 xpcs_rk_pm_runtime_suspend, xpcs_rk_pm_runtime_resume, 584 NULL); 585 586 static struct platform_driver xpcs_rk_driver = { 587 .probe = xpcs_rk_probe, 588 .driver = { 589 .name = "rk_xpcs-dwxpcs", 590 .pm = pm_ptr(&xpcs_rk_pm_ops), 591 .of_match_table = xpcs_rk_of_ids, 592 }, 593 }; 594 module_platform_driver(xpcs_rk_driver); 595 596 MODULE_DESCRIPTION("Rockchip XPCS platform device driver"); 597 MODULE_AUTHOR("Coia Prant <coiaprant@gmail.com>"); 598 MODULE_LICENSE("GPL"); 599