Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.19 694 lines 20 kB view raw
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/clocksource_ids.h> 9#include <linux/of.h> 10#include <linux/of_address.h> 11#include <linux/of_net.h> 12#include <linux/phy.h> 13#include <linux/regmap.h> 14#include <linux/mdio/mdio-regmap.h> 15#include <linux/pcs-lynx.h> 16#include <linux/reset.h> 17#include <linux/stmmac.h> 18 19#include "dwxgmac2.h" 20#include "stmmac.h" 21#include "stmmac_platform.h" 22#include "stmmac_ptp.h" 23 24#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0 25#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1 26#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2 27#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2 28#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003 29#define SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000010 30#define SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000100 31 32#define SYSMGR_FPGAGRP_MODULE_REG 0x00000028 33#define SYSMGR_FPGAGRP_MODULE_EMAC 0x00000004 34#define SYSMGR_FPGAINTF_EMAC_REG 0x00000070 35#define SYSMGR_FPGAINTF_EMAC_BIT 0x1 36 37#define EMAC_SPLITTER_CTRL_REG 0x0 38#define EMAC_SPLITTER_CTRL_SPEED_MASK 0x3 39#define EMAC_SPLITTER_CTRL_SPEED_10 0x2 40#define EMAC_SPLITTER_CTRL_SPEED_100 0x3 41#define EMAC_SPLITTER_CTRL_SPEED_1000 0x0 42 43#define SGMII_ADAPTER_CTRL_REG 0x00 44#define SGMII_ADAPTER_ENABLE 0x0000 45#define SGMII_ADAPTER_DISABLE 0x0001 46 47#define SMTG_MDIO_ADDR 0x15 48#define SMTG_TSC_WORD0 0xC 49#define SMTG_TSC_WORD1 0xD 50#define SMTG_TSC_WORD2 0xE 51#define SMTG_TSC_WORD3 0xF 52#define SMTG_TSC_SHIFT 16 53 54struct socfpga_dwmac; 55struct socfpga_dwmac_ops { 56 int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv); 57 void (*setup_plat_dat)(struct socfpga_dwmac *dwmac_priv); 58}; 59 60struct socfpga_dwmac { 61 u32 reg_offset; 62 u32 reg_shift; 63 struct device *dev; 64 struct plat_stmmacenet_data *plat_dat; 65 struct regmap *sys_mgr_base_addr; 66 struct reset_control *stmmac_rst; 67 struct reset_control *stmmac_ocp_rst; 68 void __iomem *splitter_base; 69 void __iomem *tse_pcs_base; 70 void __iomem *sgmii_adapter_base; 71 bool f2h_ptp_ref_clk; 72 const struct socfpga_dwmac_ops *ops; 73}; 74 75static void socfpga_dwmac_fix_mac_speed(void *bsp_priv, int speed, 76 unsigned int mode) 77{ 78 struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)bsp_priv; 79 struct stmmac_priv *priv = netdev_priv(dev_get_drvdata(dwmac->dev)); 80 void __iomem *splitter_base = dwmac->splitter_base; 81 void __iomem *sgmii_adapter_base = dwmac->sgmii_adapter_base; 82 u32 val; 83 84 if (sgmii_adapter_base) 85 writew(SGMII_ADAPTER_DISABLE, 86 sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); 87 88 if (splitter_base) { 89 val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG); 90 val &= ~EMAC_SPLITTER_CTRL_SPEED_MASK; 91 92 switch (speed) { 93 case 1000: 94 val |= EMAC_SPLITTER_CTRL_SPEED_1000; 95 break; 96 case 100: 97 val |= EMAC_SPLITTER_CTRL_SPEED_100; 98 break; 99 case 10: 100 val |= EMAC_SPLITTER_CTRL_SPEED_10; 101 break; 102 default: 103 return; 104 } 105 writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); 106 } 107 108 if ((priv->plat->phy_interface == PHY_INTERFACE_MODE_SGMII || 109 priv->plat->phy_interface == PHY_INTERFACE_MODE_1000BASEX) && 110 sgmii_adapter_base) 111 writew(SGMII_ADAPTER_ENABLE, 112 sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); 113} 114 115static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) 116{ 117 struct device_node *np = dev->of_node; 118 struct regmap *sys_mgr_base_addr; 119 u32 reg_offset, reg_shift; 120 int ret, index; 121 struct device_node *np_splitter = NULL; 122 struct device_node *np_sgmii_adapter = NULL; 123 struct resource res_splitter; 124 struct resource res_tse_pcs; 125 struct resource res_sgmii_adapter; 126 127 sys_mgr_base_addr = 128 altr_sysmgr_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon"); 129 if (IS_ERR(sys_mgr_base_addr)) { 130 dev_info(dev, "No sysmgr-syscon node found\n"); 131 return PTR_ERR(sys_mgr_base_addr); 132 } 133 134 ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 1, &reg_offset); 135 if (ret) { 136 dev_info(dev, "Could not read reg_offset from sysmgr-syscon!\n"); 137 return -EINVAL; 138 } 139 140 ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 2, &reg_shift); 141 if (ret) { 142 dev_info(dev, "Could not read reg_shift from sysmgr-syscon!\n"); 143 return -EINVAL; 144 } 145 146 dwmac->f2h_ptp_ref_clk = of_property_read_bool(np, "altr,f2h_ptp_ref_clk"); 147 148 np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0); 149 if (np_splitter) { 150 ret = of_address_to_resource(np_splitter, 0, &res_splitter); 151 of_node_put(np_splitter); 152 if (ret) { 153 dev_info(dev, "Missing emac splitter address\n"); 154 return -EINVAL; 155 } 156 157 dwmac->splitter_base = devm_ioremap_resource(dev, &res_splitter); 158 if (IS_ERR(dwmac->splitter_base)) { 159 dev_info(dev, "Failed to mapping emac splitter\n"); 160 return PTR_ERR(dwmac->splitter_base); 161 } 162 } 163 164 np_sgmii_adapter = of_parse_phandle(np, 165 "altr,gmii-to-sgmii-converter", 0); 166 if (np_sgmii_adapter) { 167 index = of_property_match_string(np_sgmii_adapter, "reg-names", 168 "hps_emac_interface_splitter_avalon_slave"); 169 170 if (index >= 0) { 171 if (of_address_to_resource(np_sgmii_adapter, index, 172 &res_splitter)) { 173 dev_err(dev, 174 "%s: ERROR: missing emac splitter address\n", 175 __func__); 176 ret = -EINVAL; 177 goto err_node_put; 178 } 179 180 dwmac->splitter_base = 181 devm_ioremap_resource(dev, &res_splitter); 182 183 if (IS_ERR(dwmac->splitter_base)) { 184 ret = PTR_ERR(dwmac->splitter_base); 185 goto err_node_put; 186 } 187 } 188 189 index = of_property_match_string(np_sgmii_adapter, "reg-names", 190 "gmii_to_sgmii_adapter_avalon_slave"); 191 192 if (index >= 0) { 193 if (of_address_to_resource(np_sgmii_adapter, index, 194 &res_sgmii_adapter)) { 195 dev_err(dev, 196 "%s: ERROR: failed mapping adapter\n", 197 __func__); 198 ret = -EINVAL; 199 goto err_node_put; 200 } 201 202 dwmac->sgmii_adapter_base = 203 devm_ioremap_resource(dev, &res_sgmii_adapter); 204 205 if (IS_ERR(dwmac->sgmii_adapter_base)) { 206 ret = PTR_ERR(dwmac->sgmii_adapter_base); 207 goto err_node_put; 208 } 209 } 210 211 index = of_property_match_string(np_sgmii_adapter, "reg-names", 212 "eth_tse_control_port"); 213 214 if (index >= 0) { 215 if (of_address_to_resource(np_sgmii_adapter, index, 216 &res_tse_pcs)) { 217 dev_err(dev, 218 "%s: ERROR: failed mapping tse control port\n", 219 __func__); 220 ret = -EINVAL; 221 goto err_node_put; 222 } 223 224 dwmac->tse_pcs_base = 225 devm_ioremap_resource(dev, &res_tse_pcs); 226 227 if (IS_ERR(dwmac->tse_pcs_base)) { 228 ret = PTR_ERR(dwmac->tse_pcs_base); 229 goto err_node_put; 230 } 231 } 232 } 233 dwmac->reg_offset = reg_offset; 234 dwmac->reg_shift = reg_shift; 235 dwmac->sys_mgr_base_addr = sys_mgr_base_addr; 236 dwmac->dev = dev; 237 of_node_put(np_sgmii_adapter); 238 239 return 0; 240 241err_node_put: 242 of_node_put(np_sgmii_adapter); 243 return ret; 244} 245 246static int socfpga_get_plat_phymode(struct socfpga_dwmac *dwmac) 247{ 248 return dwmac->plat_dat->phy_interface; 249} 250 251static void socfpga_sgmii_config(struct socfpga_dwmac *dwmac, bool enable) 252{ 253 u16 val = enable ? SGMII_ADAPTER_ENABLE : SGMII_ADAPTER_DISABLE; 254 255 writew(val, dwmac->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); 256} 257 258static int socfpga_set_phy_mode_common(int phymode, u32 *val) 259{ 260 switch (phymode) { 261 case PHY_INTERFACE_MODE_RGMII: 262 case PHY_INTERFACE_MODE_RGMII_ID: 263 case PHY_INTERFACE_MODE_RGMII_RXID: 264 case PHY_INTERFACE_MODE_RGMII_TXID: 265 *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; 266 break; 267 case PHY_INTERFACE_MODE_MII: 268 case PHY_INTERFACE_MODE_GMII: 269 case PHY_INTERFACE_MODE_SGMII: 270 case PHY_INTERFACE_MODE_1000BASEX: 271 *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; 272 break; 273 case PHY_INTERFACE_MODE_RMII: 274 *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII; 275 break; 276 default: 277 return -EINVAL; 278 } 279 return 0; 280} 281 282static void get_smtgtime(struct mii_bus *mii, int smtg_addr, u64 *smtg_time) 283{ 284 u64 ns; 285 286 ns = mdiobus_read(mii, smtg_addr, SMTG_TSC_WORD3); 287 ns <<= SMTG_TSC_SHIFT; 288 ns |= mdiobus_read(mii, smtg_addr, SMTG_TSC_WORD2); 289 ns <<= SMTG_TSC_SHIFT; 290 ns |= mdiobus_read(mii, smtg_addr, SMTG_TSC_WORD1); 291 ns <<= SMTG_TSC_SHIFT; 292 ns |= mdiobus_read(mii, smtg_addr, SMTG_TSC_WORD0); 293 294 *smtg_time = ns; 295} 296 297static int smtg_crosststamp(ktime_t *device, struct system_counterval_t *system, 298 void *ctx) 299{ 300 struct stmmac_priv *priv = (struct stmmac_priv *)ctx; 301 u32 num_snapshot, gpio_value, acr_value; 302 void __iomem *ptpaddr = priv->ptpaddr; 303 void __iomem *ioaddr = priv->hw->pcsr; 304 unsigned long flags; 305 u64 smtg_time = 0; 306 u64 ptp_time = 0; 307 int i, ret; 308 u32 v; 309 310 /* Both internal crosstimestamping and external triggered event 311 * timestamping cannot be run concurrently. 312 */ 313 if (priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN) 314 return -EBUSY; 315 316 mutex_lock(&priv->aux_ts_lock); 317 /* Enable Internal snapshot trigger */ 318 acr_value = readl(ptpaddr + PTP_ACR); 319 acr_value &= ~PTP_ACR_MASK; 320 switch (priv->plat->int_snapshot_num) { 321 case AUX_SNAPSHOT0: 322 acr_value |= PTP_ACR_ATSEN0; 323 break; 324 case AUX_SNAPSHOT1: 325 acr_value |= PTP_ACR_ATSEN1; 326 break; 327 case AUX_SNAPSHOT2: 328 acr_value |= PTP_ACR_ATSEN2; 329 break; 330 case AUX_SNAPSHOT3: 331 acr_value |= PTP_ACR_ATSEN3; 332 break; 333 default: 334 mutex_unlock(&priv->aux_ts_lock); 335 return -EINVAL; 336 } 337 writel(acr_value, ptpaddr + PTP_ACR); 338 339 /* Clear FIFO */ 340 acr_value = readl(ptpaddr + PTP_ACR); 341 acr_value |= PTP_ACR_ATSFC; 342 writel(acr_value, ptpaddr + PTP_ACR); 343 /* Release the mutex */ 344 mutex_unlock(&priv->aux_ts_lock); 345 346 /* Trigger Internal snapshot signal. Create a rising edge by just toggle 347 * the GPO0 to low and back to high. 348 */ 349 gpio_value = readl(ioaddr + XGMAC_GPIO_STATUS); 350 gpio_value &= ~XGMAC_GPIO_GPO0; 351 writel(gpio_value, ioaddr + XGMAC_GPIO_STATUS); 352 gpio_value |= XGMAC_GPIO_GPO0; 353 writel(gpio_value, ioaddr + XGMAC_GPIO_STATUS); 354 355 /* Poll for time sync operation done */ 356 ret = readl_poll_timeout(priv->ioaddr + XGMAC_INT_STATUS, v, 357 (v & XGMAC_INT_TSIS), 100, 10000); 358 if (ret) { 359 netdev_err(priv->dev, "%s: Wait for time sync operation timeout\n", 360 __func__); 361 return ret; 362 } 363 364 *system = (struct system_counterval_t) { 365 .cycles = 0, 366 .cs_id = CSID_ARM_ARCH_COUNTER, 367 .use_nsecs = false, 368 }; 369 370 num_snapshot = (readl(ioaddr + XGMAC_TIMESTAMP_STATUS) & 371 XGMAC_TIMESTAMP_ATSNS_MASK) >> 372 XGMAC_TIMESTAMP_ATSNS_SHIFT; 373 374 /* Repeat until the timestamps are from the FIFO last segment */ 375 for (i = 0; i < num_snapshot; i++) { 376 read_lock_irqsave(&priv->ptp_lock, flags); 377 stmmac_get_ptptime(priv, ptpaddr, &ptp_time); 378 *device = ns_to_ktime(ptp_time); 379 read_unlock_irqrestore(&priv->ptp_lock, flags); 380 } 381 382 get_smtgtime(priv->mii, SMTG_MDIO_ADDR, &smtg_time); 383 system->cycles = smtg_time; 384 385 return 0; 386} 387 388static int socfpga_gen5_set_phy_mode(struct socfpga_dwmac *dwmac) 389{ 390 struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr; 391 int phymode = socfpga_get_plat_phymode(dwmac); 392 u32 reg_offset = dwmac->reg_offset; 393 u32 reg_shift = dwmac->reg_shift; 394 u32 ctrl, val, module; 395 396 if (socfpga_set_phy_mode_common(phymode, &val)) { 397 dev_err(dwmac->dev, "bad phy mode %d\n", phymode); 398 return -EINVAL; 399 } 400 401 /* Overwrite val to GMII if splitter core is enabled. The phymode here 402 * is the actual phy mode on phy hardware, but phy interface from 403 * EMAC core is GMII. 404 */ 405 if (dwmac->splitter_base) 406 val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; 407 408 /* Assert reset to the enet controller before changing the phy mode */ 409 reset_control_assert(dwmac->stmmac_ocp_rst); 410 reset_control_assert(dwmac->stmmac_rst); 411 412 regmap_read(sys_mgr_base_addr, reg_offset, &ctrl); 413 ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); 414 ctrl |= val << reg_shift; 415 416 if (dwmac->f2h_ptp_ref_clk || 417 phymode == PHY_INTERFACE_MODE_MII || 418 phymode == PHY_INTERFACE_MODE_GMII || 419 phymode == PHY_INTERFACE_MODE_SGMII) { 420 regmap_read(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG, 421 &module); 422 module |= (SYSMGR_FPGAGRP_MODULE_EMAC << (reg_shift / 2)); 423 regmap_write(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG, 424 module); 425 } 426 427 if (dwmac->f2h_ptp_ref_clk) 428 ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2); 429 else 430 ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << 431 (reg_shift / 2)); 432 433 regmap_write(sys_mgr_base_addr, reg_offset, ctrl); 434 435 /* Deassert reset for the phy configuration to be sampled by 436 * the enet controller, and operation to start in requested mode 437 */ 438 reset_control_deassert(dwmac->stmmac_ocp_rst); 439 reset_control_deassert(dwmac->stmmac_rst); 440 if (phymode == PHY_INTERFACE_MODE_SGMII) 441 socfpga_sgmii_config(dwmac, true); 442 443 return 0; 444} 445 446static int socfpga_gen10_set_phy_mode(struct socfpga_dwmac *dwmac) 447{ 448 struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr; 449 int phymode = socfpga_get_plat_phymode(dwmac); 450 u32 reg_offset = dwmac->reg_offset; 451 u32 reg_shift = dwmac->reg_shift; 452 u32 ctrl, val, module; 453 454 if (socfpga_set_phy_mode_common(phymode, &val)) 455 return -EINVAL; 456 457 /* Overwrite val to GMII if splitter core is enabled. The phymode here 458 * is the actual phy mode on phy hardware, but phy interface from 459 * EMAC core is GMII. 460 */ 461 if (dwmac->splitter_base) 462 val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; 463 464 /* Assert reset to the enet controller before changing the phy mode */ 465 reset_control_assert(dwmac->stmmac_ocp_rst); 466 reset_control_assert(dwmac->stmmac_rst); 467 468 regmap_read(sys_mgr_base_addr, reg_offset, &ctrl); 469 ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK); 470 ctrl |= val; 471 472 if (dwmac->f2h_ptp_ref_clk || 473 phymode == PHY_INTERFACE_MODE_MII || 474 phymode == PHY_INTERFACE_MODE_GMII || 475 phymode == PHY_INTERFACE_MODE_SGMII) { 476 ctrl |= SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK; 477 regmap_read(sys_mgr_base_addr, SYSMGR_FPGAINTF_EMAC_REG, 478 &module); 479 module |= (SYSMGR_FPGAINTF_EMAC_BIT << reg_shift); 480 regmap_write(sys_mgr_base_addr, SYSMGR_FPGAINTF_EMAC_REG, 481 module); 482 } else { 483 ctrl &= ~SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK; 484 } 485 486 regmap_write(sys_mgr_base_addr, reg_offset, ctrl); 487 488 /* Deassert reset for the phy configuration to be sampled by 489 * the enet controller, and operation to start in requested mode 490 */ 491 reset_control_deassert(dwmac->stmmac_ocp_rst); 492 reset_control_deassert(dwmac->stmmac_rst); 493 if (phymode == PHY_INTERFACE_MODE_SGMII) 494 socfpga_sgmii_config(dwmac, true); 495 return 0; 496} 497 498static int socfpga_dwmac_pcs_init(struct stmmac_priv *priv) 499{ 500 struct socfpga_dwmac *dwmac = priv->plat->bsp_priv; 501 struct regmap_config pcs_regmap_cfg = { 502 .reg_bits = 16, 503 .val_bits = 16, 504 .reg_shift = REGMAP_UPSHIFT(1), 505 }; 506 struct mdio_regmap_config mrc; 507 struct regmap *pcs_regmap; 508 struct phylink_pcs *pcs; 509 struct mii_bus *pcs_bus; 510 511 if (!dwmac->tse_pcs_base) 512 return 0; 513 514 pcs_regmap = devm_regmap_init_mmio(priv->device, dwmac->tse_pcs_base, 515 &pcs_regmap_cfg); 516 if (IS_ERR(pcs_regmap)) 517 return PTR_ERR(pcs_regmap); 518 519 memset(&mrc, 0, sizeof(mrc)); 520 mrc.regmap = pcs_regmap; 521 mrc.parent = priv->device; 522 mrc.valid_addr = 0x0; 523 mrc.autoscan = false; 524 525 /* Can't use ndev->name here because it will not have been initialised, 526 * and in any case, the user can rename network interfaces at runtime. 527 */ 528 snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", 529 dev_name(priv->device)); 530 pcs_bus = devm_mdio_regmap_register(priv->device, &mrc); 531 if (IS_ERR(pcs_bus)) 532 return PTR_ERR(pcs_bus); 533 534 pcs = lynx_pcs_create_mdiodev(pcs_bus, 0); 535 if (IS_ERR(pcs)) 536 return PTR_ERR(pcs); 537 538 priv->hw->phylink_pcs = pcs; 539 return 0; 540} 541 542static void socfpga_dwmac_pcs_exit(struct stmmac_priv *priv) 543{ 544 if (priv->hw->phylink_pcs) 545 lynx_pcs_destroy(priv->hw->phylink_pcs); 546} 547 548static struct phylink_pcs *socfpga_dwmac_select_pcs(struct stmmac_priv *priv, 549 phy_interface_t interface) 550{ 551 return priv->hw->phylink_pcs; 552} 553 554static int socfpga_dwmac_init(struct device *dev, void *bsp_priv) 555{ 556 struct socfpga_dwmac *dwmac = bsp_priv; 557 558 return dwmac->ops->set_phy_mode(dwmac); 559} 560 561static void socfpga_gen5_setup_plat_dat(struct socfpga_dwmac *dwmac) 562{ 563 struct plat_stmmacenet_data *plat_dat = dwmac->plat_dat; 564 565 plat_dat->core_type = DWMAC_CORE_GMAC; 566 567 /* Rx watchdog timer in dwmac is buggy in this hw */ 568 plat_dat->riwt_off = 1; 569} 570 571static void socfpga_agilex5_setup_plat_dat(struct socfpga_dwmac *dwmac) 572{ 573 struct plat_stmmacenet_data *plat_dat = dwmac->plat_dat; 574 575 plat_dat->core_type = DWMAC_CORE_XGMAC; 576 577 /* Enable TSO */ 578 plat_dat->flags |= STMMAC_FLAG_TSO_EN; 579 580 /* Enable TBS */ 581 switch (plat_dat->tx_queues_to_use) { 582 case 8: 583 plat_dat->tx_queues_cfg[7].tbs_en = true; 584 fallthrough; 585 case 7: 586 plat_dat->tx_queues_cfg[6].tbs_en = true; 587 break; 588 default: 589 /* Tx Queues 0 - 5 doesn't support TBS on Agilex5 */ 590 break; 591 } 592 593 /* Hw supported cross-timestamp */ 594 plat_dat->int_snapshot_num = AUX_SNAPSHOT0; 595 plat_dat->crosststamp = smtg_crosststamp; 596} 597 598static int socfpga_dwmac_probe(struct platform_device *pdev) 599{ 600 struct plat_stmmacenet_data *plat_dat; 601 struct stmmac_resources stmmac_res; 602 struct device *dev = &pdev->dev; 603 int ret; 604 struct socfpga_dwmac *dwmac; 605 const struct socfpga_dwmac_ops *ops; 606 607 ops = device_get_match_data(&pdev->dev); 608 if (!ops) { 609 dev_err(&pdev->dev, "no of match data provided\n"); 610 return -EINVAL; 611 } 612 613 ret = stmmac_get_platform_resources(pdev, &stmmac_res); 614 if (ret) 615 return ret; 616 617 plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac); 618 if (IS_ERR(plat_dat)) 619 return PTR_ERR(plat_dat); 620 621 dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL); 622 if (!dwmac) 623 return -ENOMEM; 624 625 dwmac->stmmac_ocp_rst = devm_reset_control_get_optional(dev, "stmmaceth-ocp"); 626 if (IS_ERR(dwmac->stmmac_ocp_rst)) { 627 ret = PTR_ERR(dwmac->stmmac_ocp_rst); 628 dev_err(dev, "error getting reset control of ocp %d\n", ret); 629 return ret; 630 } 631 632 reset_control_deassert(dwmac->stmmac_ocp_rst); 633 634 ret = socfpga_dwmac_parse_data(dwmac, dev); 635 if (ret) { 636 dev_err(dev, "Unable to parse OF data\n"); 637 return ret; 638 } 639 640 /* The socfpga driver needs to control the stmmac reset to set the phy 641 * mode. Create a copy of the core reset handle so it can be used by 642 * the driver later. 643 */ 644 dwmac->stmmac_rst = plat_dat->stmmac_rst; 645 dwmac->ops = ops; 646 dwmac->plat_dat = plat_dat; 647 648 plat_dat->bsp_priv = dwmac; 649 plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed; 650 plat_dat->init = socfpga_dwmac_init; 651 plat_dat->pcs_init = socfpga_dwmac_pcs_init; 652 plat_dat->pcs_exit = socfpga_dwmac_pcs_exit; 653 plat_dat->select_pcs = socfpga_dwmac_select_pcs; 654 655 ops->setup_plat_dat(dwmac); 656 657 return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); 658} 659 660static const struct socfpga_dwmac_ops socfpga_gen5_ops = { 661 .set_phy_mode = socfpga_gen5_set_phy_mode, 662 .setup_plat_dat = socfpga_gen5_setup_plat_dat, 663}; 664 665static const struct socfpga_dwmac_ops socfpga_gen10_ops = { 666 .set_phy_mode = socfpga_gen10_set_phy_mode, 667 .setup_plat_dat = socfpga_gen5_setup_plat_dat, 668}; 669 670static const struct socfpga_dwmac_ops socfpga_agilex5_ops = { 671 .set_phy_mode = socfpga_gen10_set_phy_mode, 672 .setup_plat_dat = socfpga_agilex5_setup_plat_dat, 673}; 674 675static const struct of_device_id socfpga_dwmac_match[] = { 676 { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gen5_ops }, 677 { .compatible = "altr,socfpga-stmmac-a10-s10", .data = &socfpga_gen10_ops }, 678 { .compatible = "altr,socfpga-stmmac-agilex5", .data = &socfpga_agilex5_ops }, 679 { } 680}; 681MODULE_DEVICE_TABLE(of, socfpga_dwmac_match); 682 683static struct platform_driver socfpga_dwmac_driver = { 684 .probe = socfpga_dwmac_probe, 685 .driver = { 686 .name = "socfpga-dwmac", 687 .pm = &stmmac_pltfr_pm_ops, 688 .of_match_table = socfpga_dwmac_match, 689 }, 690}; 691module_platform_driver(socfpga_dwmac_driver); 692 693MODULE_DESCRIPTION("Altera SOC DWMAC Specific Glue layer"); 694MODULE_LICENSE("GPL v2");