linux/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
<<
>>
Prefs
   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
  43struct socfpga_dwmac;
  44struct socfpga_dwmac_ops {
  45        int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv);
  46};
  47
  48struct 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
  61static 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
 100static 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
 226err_node_put:
 227        of_node_put(np_sgmii_adapter);
 228        return ret;
 229}
 230
 231static 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
 239static 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
 262static 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
 324static 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
 380static 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
 449err_dvr_remove:
 450        stmmac_dvr_remove(&pdev->dev);
 451err_remove_config_dt:
 452        stmmac_remove_config_dt(pdev, plat_dat);
 453
 454        return ret;
 455}
 456
 457#ifdef CONFIG_PM_SLEEP
 458static 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
 488static SIMPLE_DEV_PM_OPS(socfpga_dwmac_pm_ops, stmmac_suspend,
 489                                               socfpga_dwmac_resume);
 490
 491static const struct socfpga_dwmac_ops socfpga_gen5_ops = {
 492        .set_phy_mode = socfpga_gen5_set_phy_mode,
 493};
 494
 495static const struct socfpga_dwmac_ops socfpga_gen10_ops = {
 496        .set_phy_mode = socfpga_gen10_set_phy_mode,
 497};
 498
 499static 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};
 504MODULE_DEVICE_TABLE(of, socfpga_dwmac_match);
 505
 506static 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};
 515module_platform_driver(socfpga_dwmac_driver);
 516
 517MODULE_LICENSE("GPL v2");
 518