linux/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Synopsys DWC Ethernet Quality-of-Service v4.10a linux driver
   4 *
   5 * Copyright (C) 2016 Joao Pinto <jpinto@synopsys.com>
   6 */
   7
   8#include <linux/clk.h>
   9#include <linux/clk-provider.h>
  10#include <linux/device.h>
  11#include <linux/gpio/consumer.h>
  12#include <linux/ethtool.h>
  13#include <linux/io.h>
  14#include <linux/iopoll.h>
  15#include <linux/ioport.h>
  16#include <linux/module.h>
  17#include <linux/of_device.h>
  18#include <linux/of_net.h>
  19#include <linux/mfd/syscon.h>
  20#include <linux/platform_device.h>
  21#include <linux/reset.h>
  22#include <linux/stmmac.h>
  23
  24#include "stmmac_platform.h"
  25#include "dwmac4.h"
  26
  27struct tegra_eqos {
  28        struct device *dev;
  29        void __iomem *regs;
  30
  31        struct reset_control *rst;
  32        struct clk *clk_master;
  33        struct clk *clk_slave;
  34        struct clk *clk_tx;
  35        struct clk *clk_rx;
  36
  37        struct gpio_desc *reset;
  38};
  39
  40static int dwc_eth_dwmac_config_dt(struct platform_device *pdev,
  41                                   struct plat_stmmacenet_data *plat_dat)
  42{
  43        struct device *dev = &pdev->dev;
  44        u32 burst_map = 0;
  45        u32 bit_index = 0;
  46        u32 a_index = 0;
  47
  48        if (!plat_dat->axi) {
  49                plat_dat->axi = kzalloc(sizeof(struct stmmac_axi), GFP_KERNEL);
  50
  51                if (!plat_dat->axi)
  52                        return -ENOMEM;
  53        }
  54
  55        plat_dat->axi->axi_lpi_en = device_property_read_bool(dev,
  56                                                              "snps,en-lpi");
  57        if (device_property_read_u32(dev, "snps,write-requests",
  58                                     &plat_dat->axi->axi_wr_osr_lmt)) {
  59                /**
  60                 * Since the register has a reset value of 1, if property
  61                 * is missing, default to 1.
  62                 */
  63                plat_dat->axi->axi_wr_osr_lmt = 1;
  64        } else {
  65                /**
  66                 * If property exists, to keep the behavior from dwc_eth_qos,
  67                 * subtract one after parsing.
  68                 */
  69                plat_dat->axi->axi_wr_osr_lmt--;
  70        }
  71
  72        if (device_property_read_u32(dev, "snps,read-requests",
  73                                     &plat_dat->axi->axi_rd_osr_lmt)) {
  74                /**
  75                 * Since the register has a reset value of 1, if property
  76                 * is missing, default to 1.
  77                 */
  78                plat_dat->axi->axi_rd_osr_lmt = 1;
  79        } else {
  80                /**
  81                 * If property exists, to keep the behavior from dwc_eth_qos,
  82                 * subtract one after parsing.
  83                 */
  84                plat_dat->axi->axi_rd_osr_lmt--;
  85        }
  86        device_property_read_u32(dev, "snps,burst-map", &burst_map);
  87
  88        /* converts burst-map bitmask to burst array */
  89        for (bit_index = 0; bit_index < 7; bit_index++) {
  90                if (burst_map & (1 << bit_index)) {
  91                        switch (bit_index) {
  92                        case 0:
  93                        plat_dat->axi->axi_blen[a_index] = 4; break;
  94                        case 1:
  95                        plat_dat->axi->axi_blen[a_index] = 8; break;
  96                        case 2:
  97                        plat_dat->axi->axi_blen[a_index] = 16; break;
  98                        case 3:
  99                        plat_dat->axi->axi_blen[a_index] = 32; break;
 100                        case 4:
 101                        plat_dat->axi->axi_blen[a_index] = 64; break;
 102                        case 5:
 103                        plat_dat->axi->axi_blen[a_index] = 128; break;
 104                        case 6:
 105                        plat_dat->axi->axi_blen[a_index] = 256; break;
 106                        default:
 107                        break;
 108                        }
 109                        a_index++;
 110                }
 111        }
 112
 113        /* dwc-qos needs GMAC4, AAL, TSO and PMT */
 114        plat_dat->has_gmac4 = 1;
 115        plat_dat->dma_cfg->aal = 1;
 116        plat_dat->tso_en = 1;
 117        plat_dat->pmt = 1;
 118
 119        return 0;
 120}
 121
 122static int dwc_qos_probe(struct platform_device *pdev,
 123                         struct plat_stmmacenet_data *plat_dat,
 124                         struct stmmac_resources *stmmac_res)
 125{
 126        int err;
 127
 128        plat_dat->stmmac_clk = devm_clk_get(&pdev->dev, "apb_pclk");
 129        if (IS_ERR(plat_dat->stmmac_clk)) {
 130                dev_err(&pdev->dev, "apb_pclk clock not found.\n");
 131                return PTR_ERR(plat_dat->stmmac_clk);
 132        }
 133
 134        err = clk_prepare_enable(plat_dat->stmmac_clk);
 135        if (err < 0) {
 136                dev_err(&pdev->dev, "failed to enable apb_pclk clock: %d\n",
 137                        err);
 138                return err;
 139        }
 140
 141        plat_dat->pclk = devm_clk_get(&pdev->dev, "phy_ref_clk");
 142        if (IS_ERR(plat_dat->pclk)) {
 143                dev_err(&pdev->dev, "phy_ref_clk clock not found.\n");
 144                err = PTR_ERR(plat_dat->pclk);
 145                goto disable;
 146        }
 147
 148        err = clk_prepare_enable(plat_dat->pclk);
 149        if (err < 0) {
 150                dev_err(&pdev->dev, "failed to enable phy_ref clock: %d\n",
 151                        err);
 152                goto disable;
 153        }
 154
 155        return 0;
 156
 157disable:
 158        clk_disable_unprepare(plat_dat->stmmac_clk);
 159        return err;
 160}
 161
 162static int dwc_qos_remove(struct platform_device *pdev)
 163{
 164        struct net_device *ndev = platform_get_drvdata(pdev);
 165        struct stmmac_priv *priv = netdev_priv(ndev);
 166
 167        clk_disable_unprepare(priv->plat->pclk);
 168        clk_disable_unprepare(priv->plat->stmmac_clk);
 169
 170        return 0;
 171}
 172
 173#define SDMEMCOMPPADCTRL 0x8800
 174#define  SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31)
 175
 176#define AUTO_CAL_CONFIG 0x8804
 177#define  AUTO_CAL_CONFIG_START BIT(31)
 178#define  AUTO_CAL_CONFIG_ENABLE BIT(29)
 179
 180#define AUTO_CAL_STATUS 0x880c
 181#define  AUTO_CAL_STATUS_ACTIVE BIT(31)
 182
 183static void tegra_eqos_fix_speed(void *priv, unsigned int speed)
 184{
 185        struct tegra_eqos *eqos = priv;
 186        unsigned long rate = 125000000;
 187        bool needs_calibration = false;
 188        u32 value;
 189        int err;
 190
 191        switch (speed) {
 192        case SPEED_1000:
 193                needs_calibration = true;
 194                rate = 125000000;
 195                break;
 196
 197        case SPEED_100:
 198                needs_calibration = true;
 199                rate = 25000000;
 200                break;
 201
 202        case SPEED_10:
 203                rate = 2500000;
 204                break;
 205
 206        default:
 207                dev_err(eqos->dev, "invalid speed %u\n", speed);
 208                break;
 209        }
 210
 211        if (needs_calibration) {
 212                /* calibrate */
 213                value = readl(eqos->regs + SDMEMCOMPPADCTRL);
 214                value |= SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
 215                writel(value, eqos->regs + SDMEMCOMPPADCTRL);
 216
 217                udelay(1);
 218
 219                value = readl(eqos->regs + AUTO_CAL_CONFIG);
 220                value |= AUTO_CAL_CONFIG_START | AUTO_CAL_CONFIG_ENABLE;
 221                writel(value, eqos->regs + AUTO_CAL_CONFIG);
 222
 223                err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS,
 224                                                value,
 225                                                value & AUTO_CAL_STATUS_ACTIVE,
 226                                                1, 10);
 227                if (err < 0) {
 228                        dev_err(eqos->dev, "calibration did not start\n");
 229                        goto failed;
 230                }
 231
 232                err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS,
 233                                                value,
 234                                                (value & AUTO_CAL_STATUS_ACTIVE) == 0,
 235                                                20, 200);
 236                if (err < 0) {
 237                        dev_err(eqos->dev, "calibration didn't finish\n");
 238                        goto failed;
 239                }
 240
 241        failed:
 242                value = readl(eqos->regs + SDMEMCOMPPADCTRL);
 243                value &= ~SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
 244                writel(value, eqos->regs + SDMEMCOMPPADCTRL);
 245        } else {
 246                value = readl(eqos->regs + AUTO_CAL_CONFIG);
 247                value &= ~AUTO_CAL_CONFIG_ENABLE;
 248                writel(value, eqos->regs + AUTO_CAL_CONFIG);
 249        }
 250
 251        err = clk_set_rate(eqos->clk_tx, rate);
 252        if (err < 0)
 253                dev_err(eqos->dev, "failed to set TX rate: %d\n", err);
 254}
 255
 256static int tegra_eqos_init(struct platform_device *pdev, void *priv)
 257{
 258        struct tegra_eqos *eqos = priv;
 259        unsigned long rate;
 260        u32 value;
 261
 262        rate = clk_get_rate(eqos->clk_slave);
 263
 264        value = (rate / 1000000) - 1;
 265        writel(value, eqos->regs + GMAC_1US_TIC_COUNTER);
 266
 267        return 0;
 268}
 269
 270static int tegra_eqos_probe(struct platform_device *pdev,
 271                            struct plat_stmmacenet_data *data,
 272                            struct stmmac_resources *res)
 273{
 274        struct device *dev = &pdev->dev;
 275        struct tegra_eqos *eqos;
 276        int err;
 277
 278        eqos = devm_kzalloc(&pdev->dev, sizeof(*eqos), GFP_KERNEL);
 279        if (!eqos)
 280                return -ENOMEM;
 281
 282        eqos->dev = &pdev->dev;
 283        eqos->regs = res->addr;
 284
 285        if (!is_of_node(dev->fwnode))
 286                goto bypass_clk_reset_gpio;
 287
 288        eqos->clk_master = devm_clk_get(&pdev->dev, "master_bus");
 289        if (IS_ERR(eqos->clk_master)) {
 290                err = PTR_ERR(eqos->clk_master);
 291                goto error;
 292        }
 293
 294        err = clk_prepare_enable(eqos->clk_master);
 295        if (err < 0)
 296                goto error;
 297
 298        eqos->clk_slave = devm_clk_get(&pdev->dev, "slave_bus");
 299        if (IS_ERR(eqos->clk_slave)) {
 300                err = PTR_ERR(eqos->clk_slave);
 301                goto disable_master;
 302        }
 303
 304        data->stmmac_clk = eqos->clk_slave;
 305
 306        err = clk_prepare_enable(eqos->clk_slave);
 307        if (err < 0)
 308                goto disable_master;
 309
 310        eqos->clk_rx = devm_clk_get(&pdev->dev, "rx");
 311        if (IS_ERR(eqos->clk_rx)) {
 312                err = PTR_ERR(eqos->clk_rx);
 313                goto disable_slave;
 314        }
 315
 316        err = clk_prepare_enable(eqos->clk_rx);
 317        if (err < 0)
 318                goto disable_slave;
 319
 320        eqos->clk_tx = devm_clk_get(&pdev->dev, "tx");
 321        if (IS_ERR(eqos->clk_tx)) {
 322                err = PTR_ERR(eqos->clk_tx);
 323                goto disable_rx;
 324        }
 325
 326        err = clk_prepare_enable(eqos->clk_tx);
 327        if (err < 0)
 328                goto disable_rx;
 329
 330        eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH);
 331        if (IS_ERR(eqos->reset)) {
 332                err = PTR_ERR(eqos->reset);
 333                goto disable_tx;
 334        }
 335
 336        usleep_range(2000, 4000);
 337        gpiod_set_value(eqos->reset, 0);
 338
 339        /* MDIO bus was already reset just above */
 340        data->mdio_bus_data->needs_reset = false;
 341
 342        eqos->rst = devm_reset_control_get(&pdev->dev, "eqos");
 343        if (IS_ERR(eqos->rst)) {
 344                err = PTR_ERR(eqos->rst);
 345                goto reset_phy;
 346        }
 347
 348        err = reset_control_assert(eqos->rst);
 349        if (err < 0)
 350                goto reset_phy;
 351
 352        usleep_range(2000, 4000);
 353
 354        err = reset_control_deassert(eqos->rst);
 355        if (err < 0)
 356                goto reset_phy;
 357
 358        usleep_range(2000, 4000);
 359
 360bypass_clk_reset_gpio:
 361        data->fix_mac_speed = tegra_eqos_fix_speed;
 362        data->init = tegra_eqos_init;
 363        data->bsp_priv = eqos;
 364
 365        err = tegra_eqos_init(pdev, eqos);
 366        if (err < 0)
 367                goto reset;
 368
 369        return 0;
 370reset:
 371        reset_control_assert(eqos->rst);
 372reset_phy:
 373        gpiod_set_value(eqos->reset, 1);
 374disable_tx:
 375        clk_disable_unprepare(eqos->clk_tx);
 376disable_rx:
 377        clk_disable_unprepare(eqos->clk_rx);
 378disable_slave:
 379        clk_disable_unprepare(eqos->clk_slave);
 380disable_master:
 381        clk_disable_unprepare(eqos->clk_master);
 382error:
 383        return err;
 384}
 385
 386static int tegra_eqos_remove(struct platform_device *pdev)
 387{
 388        struct tegra_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev);
 389
 390        reset_control_assert(eqos->rst);
 391        gpiod_set_value(eqos->reset, 1);
 392        clk_disable_unprepare(eqos->clk_tx);
 393        clk_disable_unprepare(eqos->clk_rx);
 394        clk_disable_unprepare(eqos->clk_slave);
 395        clk_disable_unprepare(eqos->clk_master);
 396
 397        return 0;
 398}
 399
 400struct dwc_eth_dwmac_data {
 401        int (*probe)(struct platform_device *pdev,
 402                     struct plat_stmmacenet_data *data,
 403                     struct stmmac_resources *res);
 404        int (*remove)(struct platform_device *pdev);
 405};
 406
 407static const struct dwc_eth_dwmac_data dwc_qos_data = {
 408        .probe = dwc_qos_probe,
 409        .remove = dwc_qos_remove,
 410};
 411
 412static const struct dwc_eth_dwmac_data tegra_eqos_data = {
 413        .probe = tegra_eqos_probe,
 414        .remove = tegra_eqos_remove,
 415};
 416
 417static int dwc_eth_dwmac_probe(struct platform_device *pdev)
 418{
 419        const struct dwc_eth_dwmac_data *data;
 420        struct plat_stmmacenet_data *plat_dat;
 421        struct stmmac_resources stmmac_res;
 422        int ret;
 423
 424        data = device_get_match_data(&pdev->dev);
 425
 426        memset(&stmmac_res, 0, sizeof(struct stmmac_resources));
 427
 428        /**
 429         * Since stmmac_platform supports name IRQ only, basic platform
 430         * resource initialization is done in the glue logic.
 431         */
 432        stmmac_res.irq = platform_get_irq(pdev, 0);
 433        if (stmmac_res.irq < 0)
 434                return stmmac_res.irq;
 435        stmmac_res.wol_irq = stmmac_res.irq;
 436
 437        stmmac_res.addr = devm_platform_ioremap_resource(pdev, 0);
 438        if (IS_ERR(stmmac_res.addr))
 439                return PTR_ERR(stmmac_res.addr);
 440
 441        plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
 442        if (IS_ERR(plat_dat))
 443                return PTR_ERR(plat_dat);
 444
 445        ret = data->probe(pdev, plat_dat, &stmmac_res);
 446        if (ret < 0) {
 447                if (ret != -EPROBE_DEFER)
 448                        dev_err(&pdev->dev, "failed to probe subdriver: %d\n",
 449                                ret);
 450
 451                goto remove_config;
 452        }
 453
 454        ret = dwc_eth_dwmac_config_dt(pdev, plat_dat);
 455        if (ret)
 456                goto remove;
 457
 458        ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
 459        if (ret)
 460                goto remove;
 461
 462        return ret;
 463
 464remove:
 465        data->remove(pdev);
 466remove_config:
 467        stmmac_remove_config_dt(pdev, plat_dat);
 468
 469        return ret;
 470}
 471
 472static int dwc_eth_dwmac_remove(struct platform_device *pdev)
 473{
 474        struct net_device *ndev = platform_get_drvdata(pdev);
 475        struct stmmac_priv *priv = netdev_priv(ndev);
 476        const struct dwc_eth_dwmac_data *data;
 477        int err;
 478
 479        data = device_get_match_data(&pdev->dev);
 480
 481        err = stmmac_dvr_remove(&pdev->dev);
 482        if (err < 0)
 483                dev_err(&pdev->dev, "failed to remove platform: %d\n", err);
 484
 485        err = data->remove(pdev);
 486        if (err < 0)
 487                dev_err(&pdev->dev, "failed to remove subdriver: %d\n", err);
 488
 489        stmmac_remove_config_dt(pdev, priv->plat);
 490
 491        return err;
 492}
 493
 494static const struct of_device_id dwc_eth_dwmac_match[] = {
 495        { .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data },
 496        { .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data },
 497        { }
 498};
 499MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
 500
 501static struct platform_driver dwc_eth_dwmac_driver = {
 502        .probe  = dwc_eth_dwmac_probe,
 503        .remove = dwc_eth_dwmac_remove,
 504        .driver = {
 505                .name           = "dwc-eth-dwmac",
 506                .pm             = &stmmac_pltfr_pm_ops,
 507                .of_match_table = dwc_eth_dwmac_match,
 508        },
 509};
 510module_platform_driver(dwc_eth_dwmac_driver);
 511
 512MODULE_AUTHOR("Joao Pinto <jpinto@synopsys.com>");
 513MODULE_DESCRIPTION("Synopsys DWC Ethernet Quality-of-Service v4.10a driver");
 514MODULE_LICENSE("GPL v2");
 515