dwmac-socfpga.c (15315B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* Copyright Altera Corporation (C) 2014. All rights reserved. 3 * 4 * Adopted from dwmac-sti.c 5 */ 6 7#include <linux/mfd/altera-sysmgr.h> 8#include <linux/of.h> 9#include <linux/of_address.h> 10#include <linux/of_net.h> 11#include <linux/phy.h> 12#include <linux/regmap.h> 13#include <linux/reset.h> 14#include <linux/stmmac.h> 15 16#include "stmmac.h" 17#include "stmmac_platform.h" 18 19#include "altr_tse_pcs.h" 20 21#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0 22#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1 23#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2 24#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2 25#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003 26#define SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000010 27#define SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000100 28 29#define SYSMGR_FPGAGRP_MODULE_REG 0x00000028 30#define SYSMGR_FPGAGRP_MODULE_EMAC 0x00000004 31#define SYSMGR_FPGAINTF_EMAC_REG 0x00000070 32#define SYSMGR_FPGAINTF_EMAC_BIT 0x1 33 34#define EMAC_SPLITTER_CTRL_REG 0x0 35#define EMAC_SPLITTER_CTRL_SPEED_MASK 0x3 36#define EMAC_SPLITTER_CTRL_SPEED_10 0x2 37#define EMAC_SPLITTER_CTRL_SPEED_100 0x3 38#define EMAC_SPLITTER_CTRL_SPEED_1000 0x0 39 40struct socfpga_dwmac; 41struct socfpga_dwmac_ops { 42 int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv); 43}; 44 45struct socfpga_dwmac { 46 u32 reg_offset; 47 u32 reg_shift; 48 struct device *dev; 49 struct regmap *sys_mgr_base_addr; 50 struct reset_control *stmmac_rst; 51 struct reset_control *stmmac_ocp_rst; 52 void __iomem *splitter_base; 53 bool f2h_ptp_ref_clk; 54 struct tse_pcs pcs; 55 const struct socfpga_dwmac_ops *ops; 56}; 57 58static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) 59{ 60 struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv; 61 void __iomem *splitter_base = dwmac->splitter_base; 62 void __iomem *sgmii_adapter_base = dwmac->pcs.sgmii_adapter_base; 63 struct device *dev = dwmac->dev; 64 struct net_device *ndev = dev_get_drvdata(dev); 65 struct phy_device *phy_dev = ndev->phydev; 66 u32 val; 67 68 if (sgmii_adapter_base) 69 writew(SGMII_ADAPTER_DISABLE, 70 sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); 71 72 if (splitter_base) { 73 val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG); 74 val &= ~EMAC_SPLITTER_CTRL_SPEED_MASK; 75 76 switch (speed) { 77 case 1000: 78 val |= EMAC_SPLITTER_CTRL_SPEED_1000; 79 break; 80 case 100: 81 val |= EMAC_SPLITTER_CTRL_SPEED_100; 82 break; 83 case 10: 84 val |= EMAC_SPLITTER_CTRL_SPEED_10; 85 break; 86 default: 87 return; 88 } 89 writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); 90 } 91 92 if (phy_dev && sgmii_adapter_base) { 93 writew(SGMII_ADAPTER_ENABLE, 94 sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); 95 tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed); 96 } 97} 98 99static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) 100{ 101 struct device_node *np = dev->of_node; 102 struct regmap *sys_mgr_base_addr; 103 u32 reg_offset, reg_shift; 104 int ret, index; 105 struct device_node *np_splitter = NULL; 106 struct device_node *np_sgmii_adapter = NULL; 107 struct resource res_splitter; 108 struct resource res_tse_pcs; 109 struct resource res_sgmii_adapter; 110 111 sys_mgr_base_addr = 112 altr_sysmgr_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon"); 113 if (IS_ERR(sys_mgr_base_addr)) { 114 dev_info(dev, "No sysmgr-syscon node found\n"); 115 return PTR_ERR(sys_mgr_base_addr); 116 } 117 118 ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 1, ®_offset); 119 if (ret) { 120 dev_info(dev, "Could not read reg_offset from sysmgr-syscon!\n"); 121 return -EINVAL; 122 } 123 124 ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 2, ®_shift); 125 if (ret) { 126 dev_info(dev, "Could not read reg_shift from sysmgr-syscon!\n"); 127 return -EINVAL; 128 } 129 130 dwmac->f2h_ptp_ref_clk = of_property_read_bool(np, "altr,f2h_ptp_ref_clk"); 131 132 np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0); 133 if (np_splitter) { 134 ret = of_address_to_resource(np_splitter, 0, &res_splitter); 135 of_node_put(np_splitter); 136 if (ret) { 137 dev_info(dev, "Missing emac splitter address\n"); 138 return -EINVAL; 139 } 140 141 dwmac->splitter_base = devm_ioremap_resource(dev, &res_splitter); 142 if (IS_ERR(dwmac->splitter_base)) { 143 dev_info(dev, "Failed to mapping emac splitter\n"); 144 return PTR_ERR(dwmac->splitter_base); 145 } 146 } 147 148 np_sgmii_adapter = of_parse_phandle(np, 149 "altr,gmii-to-sgmii-converter", 0); 150 if (np_sgmii_adapter) { 151 index = of_property_match_string(np_sgmii_adapter, "reg-names", 152 "hps_emac_interface_splitter_avalon_slave"); 153 154 if (index >= 0) { 155 if (of_address_to_resource(np_sgmii_adapter, index, 156 &res_splitter)) { 157 dev_err(dev, 158 "%s: ERROR: missing emac splitter address\n", 159 __func__); 160 ret = -EINVAL; 161 goto err_node_put; 162 } 163 164 dwmac->splitter_base = 165 devm_ioremap_resource(dev, &res_splitter); 166 167 if (IS_ERR(dwmac->splitter_base)) { 168 ret = PTR_ERR(dwmac->splitter_base); 169 goto err_node_put; 170 } 171 } 172 173 index = of_property_match_string(np_sgmii_adapter, "reg-names", 174 "gmii_to_sgmii_adapter_avalon_slave"); 175 176 if (index >= 0) { 177 if (of_address_to_resource(np_sgmii_adapter, index, 178 &res_sgmii_adapter)) { 179 dev_err(dev, 180 "%s: ERROR: failed mapping adapter\n", 181 __func__); 182 ret = -EINVAL; 183 goto err_node_put; 184 } 185 186 dwmac->pcs.sgmii_adapter_base = 187 devm_ioremap_resource(dev, &res_sgmii_adapter); 188 189 if (IS_ERR(dwmac->pcs.sgmii_adapter_base)) { 190 ret = PTR_ERR(dwmac->pcs.sgmii_adapter_base); 191 goto err_node_put; 192 } 193 } 194 195 index = of_property_match_string(np_sgmii_adapter, "reg-names", 196 "eth_tse_control_port"); 197 198 if (index >= 0) { 199 if (of_address_to_resource(np_sgmii_adapter, index, 200 &res_tse_pcs)) { 201 dev_err(dev, 202 "%s: ERROR: failed mapping tse control port\n", 203 __func__); 204 ret = -EINVAL; 205 goto err_node_put; 206 } 207 208 dwmac->pcs.tse_pcs_base = 209 devm_ioremap_resource(dev, &res_tse_pcs); 210 211 if (IS_ERR(dwmac->pcs.tse_pcs_base)) { 212 ret = PTR_ERR(dwmac->pcs.tse_pcs_base); 213 goto err_node_put; 214 } 215 } 216 } 217 dwmac->reg_offset = reg_offset; 218 dwmac->reg_shift = reg_shift; 219 dwmac->sys_mgr_base_addr = sys_mgr_base_addr; 220 dwmac->dev = dev; 221 of_node_put(np_sgmii_adapter); 222 223 return 0; 224 225err_node_put: 226 of_node_put(np_sgmii_adapter); 227 return ret; 228} 229 230static int socfpga_get_plat_phymode(struct socfpga_dwmac *dwmac) 231{ 232 struct net_device *ndev = dev_get_drvdata(dwmac->dev); 233 struct stmmac_priv *priv = netdev_priv(ndev); 234 235 return priv->plat->interface; 236} 237 238static int socfpga_set_phy_mode_common(int phymode, u32 *val) 239{ 240 switch (phymode) { 241 case PHY_INTERFACE_MODE_RGMII: 242 case PHY_INTERFACE_MODE_RGMII_ID: 243 case PHY_INTERFACE_MODE_RGMII_RXID: 244 case PHY_INTERFACE_MODE_RGMII_TXID: 245 *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; 246 break; 247 case PHY_INTERFACE_MODE_MII: 248 case PHY_INTERFACE_MODE_GMII: 249 case PHY_INTERFACE_MODE_SGMII: 250 *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; 251 break; 252 case PHY_INTERFACE_MODE_RMII: 253 *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII; 254 break; 255 default: 256 return -EINVAL; 257 } 258 return 0; 259} 260 261static int socfpga_gen5_set_phy_mode(struct socfpga_dwmac *dwmac) 262{ 263 struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr; 264 int phymode = socfpga_get_plat_phymode(dwmac); 265 u32 reg_offset = dwmac->reg_offset; 266 u32 reg_shift = dwmac->reg_shift; 267 u32 ctrl, val, module; 268 269 if (socfpga_set_phy_mode_common(phymode, &val)) { 270 dev_err(dwmac->dev, "bad phy mode %d\n", phymode); 271 return -EINVAL; 272 } 273 274 /* Overwrite val to GMII if splitter core is enabled. The phymode here 275 * is the actual phy mode on phy hardware, but phy interface from 276 * EMAC core is GMII. 277 */ 278 if (dwmac->splitter_base) 279 val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; 280 281 /* Assert reset to the enet controller before changing the phy mode */ 282 reset_control_assert(dwmac->stmmac_ocp_rst); 283 reset_control_assert(dwmac->stmmac_rst); 284 285 regmap_read(sys_mgr_base_addr, reg_offset, &ctrl); 286 ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); 287 ctrl |= val << reg_shift; 288 289 if (dwmac->f2h_ptp_ref_clk || 290 phymode == PHY_INTERFACE_MODE_MII || 291 phymode == PHY_INTERFACE_MODE_GMII || 292 phymode == PHY_INTERFACE_MODE_SGMII) { 293 regmap_read(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG, 294 &module); 295 module |= (SYSMGR_FPGAGRP_MODULE_EMAC << (reg_shift / 2)); 296 regmap_write(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG, 297 module); 298 } 299 300 if (dwmac->f2h_ptp_ref_clk) 301 ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2); 302 else 303 ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << 304 (reg_shift / 2)); 305 306 regmap_write(sys_mgr_base_addr, reg_offset, ctrl); 307 308 /* Deassert reset for the phy configuration to be sampled by 309 * the enet controller, and operation to start in requested mode 310 */ 311 reset_control_deassert(dwmac->stmmac_ocp_rst); 312 reset_control_deassert(dwmac->stmmac_rst); 313 if (phymode == PHY_INTERFACE_MODE_SGMII) { 314 if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) { 315 dev_err(dwmac->dev, "Unable to initialize TSE PCS"); 316 return -EINVAL; 317 } 318 } 319 320 return 0; 321} 322 323static int socfpga_gen10_set_phy_mode(struct socfpga_dwmac *dwmac) 324{ 325 struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr; 326 int phymode = socfpga_get_plat_phymode(dwmac); 327 u32 reg_offset = dwmac->reg_offset; 328 u32 reg_shift = dwmac->reg_shift; 329 u32 ctrl, val, module; 330 331 if (socfpga_set_phy_mode_common(phymode, &val)) 332 return -EINVAL; 333 334 /* Overwrite val to GMII if splitter core is enabled. The phymode here 335 * is the actual phy mode on phy hardware, but phy interface from 336 * EMAC core is GMII. 337 */ 338 if (dwmac->splitter_base) 339 val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; 340 341 /* Assert reset to the enet controller before changing the phy mode */ 342 reset_control_assert(dwmac->stmmac_ocp_rst); 343 reset_control_assert(dwmac->stmmac_rst); 344 345 regmap_read(sys_mgr_base_addr, reg_offset, &ctrl); 346 ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK); 347 ctrl |= val; 348 349 if (dwmac->f2h_ptp_ref_clk || 350 phymode == PHY_INTERFACE_MODE_MII || 351 phymode == PHY_INTERFACE_MODE_GMII || 352 phymode == PHY_INTERFACE_MODE_SGMII) { 353 ctrl |= SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK; 354 regmap_read(sys_mgr_base_addr, SYSMGR_FPGAINTF_EMAC_REG, 355 &module); 356 module |= (SYSMGR_FPGAINTF_EMAC_BIT << reg_shift); 357 regmap_write(sys_mgr_base_addr, SYSMGR_FPGAINTF_EMAC_REG, 358 module); 359 } else { 360 ctrl &= ~SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK; 361 } 362 363 regmap_write(sys_mgr_base_addr, reg_offset, ctrl); 364 365 /* Deassert reset for the phy configuration to be sampled by 366 * the enet controller, and operation to start in requested mode 367 */ 368 reset_control_deassert(dwmac->stmmac_ocp_rst); 369 reset_control_deassert(dwmac->stmmac_rst); 370 if (phymode == PHY_INTERFACE_MODE_SGMII) { 371 if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) { 372 dev_err(dwmac->dev, "Unable to initialize TSE PCS"); 373 return -EINVAL; 374 } 375 } 376 return 0; 377} 378 379static int socfpga_dwmac_probe(struct platform_device *pdev) 380{ 381 struct plat_stmmacenet_data *plat_dat; 382 struct stmmac_resources stmmac_res; 383 struct device *dev = &pdev->dev; 384 int ret; 385 struct socfpga_dwmac *dwmac; 386 struct net_device *ndev; 387 struct stmmac_priv *stpriv; 388 const struct socfpga_dwmac_ops *ops; 389 390 ops = device_get_match_data(&pdev->dev); 391 if (!ops) { 392 dev_err(&pdev->dev, "no of match data provided\n"); 393 return -EINVAL; 394 } 395 396 ret = stmmac_get_platform_resources(pdev, &stmmac_res); 397 if (ret) 398 return ret; 399 400 plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); 401 if (IS_ERR(plat_dat)) 402 return PTR_ERR(plat_dat); 403 404 dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL); 405 if (!dwmac) { 406 ret = -ENOMEM; 407 goto err_remove_config_dt; 408 } 409 410 dwmac->stmmac_ocp_rst = devm_reset_control_get_optional(dev, "stmmaceth-ocp"); 411 if (IS_ERR(dwmac->stmmac_ocp_rst)) { 412 ret = PTR_ERR(dwmac->stmmac_ocp_rst); 413 dev_err(dev, "error getting reset control of ocp %d\n", ret); 414 goto err_remove_config_dt; 415 } 416 417 reset_control_deassert(dwmac->stmmac_ocp_rst); 418 419 ret = socfpga_dwmac_parse_data(dwmac, dev); 420 if (ret) { 421 dev_err(dev, "Unable to parse OF data\n"); 422 goto err_remove_config_dt; 423 } 424 425 dwmac->ops = ops; 426 plat_dat->bsp_priv = dwmac; 427 plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed; 428 429 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 430 if (ret) 431 goto err_remove_config_dt; 432 433 ndev = platform_get_drvdata(pdev); 434 stpriv = netdev_priv(ndev); 435 436 /* The socfpga driver needs to control the stmmac reset to set the phy 437 * mode. Create a copy of the core reset handle so it can be used by 438 * the driver later. 439 */ 440 dwmac->stmmac_rst = stpriv->plat->stmmac_rst; 441 442 ret = ops->set_phy_mode(dwmac); 443 if (ret) 444 goto err_dvr_remove; 445 446 return 0; 447 448err_dvr_remove: 449 stmmac_dvr_remove(&pdev->dev); 450err_remove_config_dt: 451 stmmac_remove_config_dt(pdev, plat_dat); 452 453 return ret; 454} 455 456#ifdef CONFIG_PM_SLEEP 457static int socfpga_dwmac_resume(struct device *dev) 458{ 459 struct net_device *ndev = dev_get_drvdata(dev); 460 struct stmmac_priv *priv = netdev_priv(ndev); 461 struct socfpga_dwmac *dwmac_priv = get_stmmac_bsp_priv(dev); 462 463 dwmac_priv->ops->set_phy_mode(priv->plat->bsp_priv); 464 465 /* Before the enet controller is suspended, the phy is suspended. 466 * This causes the phy clock to be gated. The enet controller is 467 * resumed before the phy, so the clock is still gated "off" when 468 * the enet controller is resumed. This code makes sure the phy 469 * is "resumed" before reinitializing the enet controller since 470 * the enet controller depends on an active phy clock to complete 471 * a DMA reset. A DMA reset will "time out" if executed 472 * with no phy clock input on the Synopsys enet controller. 473 * Verified through Synopsys Case #8000711656. 474 * 475 * Note that the phy clock is also gated when the phy is isolated. 476 * Phy "suspend" and "isolate" controls are located in phy basic 477 * control register 0, and can be modified by the phy driver 478 * framework. 479 */ 480 if (ndev->phydev) 481 phy_resume(ndev->phydev); 482 483 return stmmac_resume(dev); 484} 485#endif /* CONFIG_PM_SLEEP */ 486 487static int __maybe_unused socfpga_dwmac_runtime_suspend(struct device *dev) 488{ 489 struct net_device *ndev = dev_get_drvdata(dev); 490 struct stmmac_priv *priv = netdev_priv(ndev); 491 492 stmmac_bus_clks_config(priv, false); 493 494 return 0; 495} 496 497static int __maybe_unused socfpga_dwmac_runtime_resume(struct device *dev) 498{ 499 struct net_device *ndev = dev_get_drvdata(dev); 500 struct stmmac_priv *priv = netdev_priv(ndev); 501 502 return stmmac_bus_clks_config(priv, true); 503} 504 505static const struct dev_pm_ops socfpga_dwmac_pm_ops = { 506 SET_SYSTEM_SLEEP_PM_OPS(stmmac_suspend, socfpga_dwmac_resume) 507 SET_RUNTIME_PM_OPS(socfpga_dwmac_runtime_suspend, socfpga_dwmac_runtime_resume, NULL) 508}; 509 510static const struct socfpga_dwmac_ops socfpga_gen5_ops = { 511 .set_phy_mode = socfpga_gen5_set_phy_mode, 512}; 513 514static const struct socfpga_dwmac_ops socfpga_gen10_ops = { 515 .set_phy_mode = socfpga_gen10_set_phy_mode, 516}; 517 518static const struct of_device_id socfpga_dwmac_match[] = { 519 { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gen5_ops }, 520 { .compatible = "altr,socfpga-stmmac-a10-s10", .data = &socfpga_gen10_ops }, 521 { } 522}; 523MODULE_DEVICE_TABLE(of, socfpga_dwmac_match); 524 525static struct platform_driver socfpga_dwmac_driver = { 526 .probe = socfpga_dwmac_probe, 527 .remove = stmmac_pltfr_remove, 528 .driver = { 529 .name = "socfpga-dwmac", 530 .pm = &socfpga_dwmac_pm_ops, 531 .of_match_table = socfpga_dwmac_match, 532 }, 533}; 534module_platform_driver(socfpga_dwmac_driver); 535 536MODULE_LICENSE("GPL v2");