root/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. socfpga_dwmac_fix_mac_speed
  2. socfpga_dwmac_parse_data
  3. socfpga_get_plat_phymode
  4. socfpga_set_phy_mode_common
  5. socfpga_gen5_set_phy_mode
  6. socfpga_gen10_set_phy_mode
  7. socfpga_dwmac_probe
  8. socfpga_dwmac_resume

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

/* [<][>][^][v][top][bottom][index][help] */