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 void *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 ERR_CAST(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_PTR(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 NULL;
 156
 157disable:
 158        clk_disable_unprepare(plat_dat->stmmac_clk);
 159        return ERR_PTR(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 void *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                err = -ENOMEM;
 281                goto error;
 282        }
 283
 284        eqos->dev = &pdev->dev;
 285        eqos->regs = res->addr;
 286
 287        if (!is_of_node(dev->fwnode))
 288                goto bypass_clk_reset_gpio;
 289
 290        eqos->clk_master = devm_clk_get(&pdev->dev, "master_bus");
 291        if (IS_ERR(eqos->clk_master)) {
 292                err = PTR_ERR(eqos->clk_master);
 293                goto error;
 294        }
 295
 296        err = clk_prepare_enable(eqos->clk_master);
 297        if (err < 0)
 298                goto error;
 299
 300        eqos->clk_slave = devm_clk_get(&pdev->dev, "slave_bus");
 301        if (IS_ERR(eqos->clk_slave)) {
 302                err = PTR_ERR(eqos->clk_slave);
 303                goto disable_master;
 304        }
 305
 306        data->stmmac_clk = eqos->clk_slave;
 307
 308        err = clk_prepare_enable(eqos->clk_slave);
 309        if (err < 0)
 310                goto disable_master;
 311
 312        eqos->clk_rx = devm_clk_get(&pdev->dev, "rx");
 313        if (IS_ERR(eqos->clk_rx)) {
 314                err = PTR_ERR(eqos->clk_rx);
 315                goto disable_slave;
 316        }
 317
 318        err = clk_prepare_enable(eqos->clk_rx);
 319        if (err < 0)
 320                goto disable_slave;
 321
 322        eqos->clk_tx = devm_clk_get(&pdev->dev, "tx");
 323        if (IS_ERR(eqos->clk_tx)) {
 324                err = PTR_ERR(eqos->clk_tx);
 325                goto disable_rx;
 326        }
 327
 328        err = clk_prepare_enable(eqos->clk_tx);
 329        if (err < 0)
 330                goto disable_rx;
 331
 332        eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH);
 333        if (IS_ERR(eqos->reset)) {
 334                err = PTR_ERR(eqos->reset);
 335                goto disable_tx;
 336        }
 337
 338        usleep_range(2000, 4000);
 339        gpiod_set_value(eqos->reset, 0);
 340
 341        /* MDIO bus was already reset just above */
 342        data->mdio_bus_data->needs_reset = false;
 343
 344        eqos->rst = devm_reset_control_get(&pdev->dev, "eqos");
 345        if (IS_ERR(eqos->rst)) {
 346                err = PTR_ERR(eqos->rst);
 347                goto reset_phy;
 348        }
 349
 350        err = reset_control_assert(eqos->rst);
 351        if (err < 0)
 352                goto reset_phy;
 353
 354        usleep_range(2000, 4000);
 355
 356        err = reset_control_deassert(eqos->rst);
 357        if (err < 0)
 358                goto reset_phy;
 359
 360        usleep_range(2000, 4000);
 361
 362bypass_clk_reset_gpio:
 363        data->fix_mac_speed = tegra_eqos_fix_speed;
 364        data->init = tegra_eqos_init;
 365        data->bsp_priv = eqos;
 366
 367        err = tegra_eqos_init(pdev, eqos);
 368        if (err < 0)
 369                goto reset;
 370
 371out:
 372        return eqos;
 373
 374reset:
 375        reset_control_assert(eqos->rst);
 376reset_phy:
 377        gpiod_set_value(eqos->reset, 1);
 378disable_tx:
 379        clk_disable_unprepare(eqos->clk_tx);
 380disable_rx:
 381        clk_disable_unprepare(eqos->clk_rx);
 382disable_slave:
 383        clk_disable_unprepare(eqos->clk_slave);
 384disable_master:
 385        clk_disable_unprepare(eqos->clk_master);
 386error:
 387        eqos = ERR_PTR(err);
 388        goto out;
 389}
 390
 391static int tegra_eqos_remove(struct platform_device *pdev)
 392{
 393        struct tegra_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev);
 394
 395        reset_control_assert(eqos->rst);
 396        gpiod_set_value(eqos->reset, 1);
 397        clk_disable_unprepare(eqos->clk_tx);
 398        clk_disable_unprepare(eqos->clk_rx);
 399        clk_disable_unprepare(eqos->clk_slave);
 400        clk_disable_unprepare(eqos->clk_master);
 401
 402        return 0;
 403}
 404
 405struct dwc_eth_dwmac_data {
 406        void *(*probe)(struct platform_device *pdev,
 407                       struct plat_stmmacenet_data *data,
 408                       struct stmmac_resources *res);
 409        int (*remove)(struct platform_device *pdev);
 410};
 411
 412static const struct dwc_eth_dwmac_data dwc_qos_data = {
 413        .probe = dwc_qos_probe,
 414        .remove = dwc_qos_remove,
 415};
 416
 417static const struct dwc_eth_dwmac_data tegra_eqos_data = {
 418        .probe = tegra_eqos_probe,
 419        .remove = tegra_eqos_remove,
 420};
 421
 422static int dwc_eth_dwmac_probe(struct platform_device *pdev)
 423{
 424        const struct dwc_eth_dwmac_data *data;
 425        struct plat_stmmacenet_data *plat_dat;
 426        struct stmmac_resources stmmac_res;
 427        void *priv;
 428        int ret;
 429
 430        data = device_get_match_data(&pdev->dev);
 431
 432        memset(&stmmac_res, 0, sizeof(struct stmmac_resources));
 433
 434        /**
 435         * Since stmmac_platform supports name IRQ only, basic platform
 436         * resource initialization is done in the glue logic.
 437         */
 438        stmmac_res.irq = platform_get_irq(pdev, 0);
 439        if (stmmac_res.irq < 0)
 440                return stmmac_res.irq;
 441        stmmac_res.wol_irq = stmmac_res.irq;
 442
 443        stmmac_res.addr = devm_platform_ioremap_resource(pdev, 0);
 444        if (IS_ERR(stmmac_res.addr))
 445                return PTR_ERR(stmmac_res.addr);
 446
 447        plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
 448        if (IS_ERR(plat_dat))
 449                return PTR_ERR(plat_dat);
 450
 451        priv = data->probe(pdev, plat_dat, &stmmac_res);
 452        if (IS_ERR(priv)) {
 453                ret = PTR_ERR(priv);
 454
 455                if (ret != -EPROBE_DEFER)
 456                        dev_err(&pdev->dev, "failed to probe subdriver: %d\n",
 457                                ret);
 458
 459                goto remove_config;
 460        }
 461
 462        ret = dwc_eth_dwmac_config_dt(pdev, plat_dat);
 463        if (ret)
 464                goto remove;
 465
 466        ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
 467        if (ret)
 468                goto remove;
 469
 470        return ret;
 471
 472remove:
 473        data->remove(pdev);
 474remove_config:
 475        stmmac_remove_config_dt(pdev, plat_dat);
 476
 477        return ret;
 478}
 479
 480static int dwc_eth_dwmac_remove(struct platform_device *pdev)
 481{
 482        struct net_device *ndev = platform_get_drvdata(pdev);
 483        struct stmmac_priv *priv = netdev_priv(ndev);
 484        const struct dwc_eth_dwmac_data *data;
 485        int err;
 486
 487        data = device_get_match_data(&pdev->dev);
 488
 489        err = stmmac_dvr_remove(&pdev->dev);
 490        if (err < 0)
 491                dev_err(&pdev->dev, "failed to remove platform: %d\n", err);
 492
 493        err = data->remove(pdev);
 494        if (err < 0)
 495                dev_err(&pdev->dev, "failed to remove subdriver: %d\n", err);
 496
 497        stmmac_remove_config_dt(pdev, priv->plat);
 498
 499        return err;
 500}
 501
 502static const struct of_device_id dwc_eth_dwmac_match[] = {
 503        { .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data },
 504        { .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data },
 505        { }
 506};
 507MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
 508
 509static struct platform_driver dwc_eth_dwmac_driver = {
 510        .probe  = dwc_eth_dwmac_probe,
 511        .remove = dwc_eth_dwmac_remove,
 512        .driver = {
 513                .name           = "dwc-eth-dwmac",
 514                .pm             = &stmmac_pltfr_pm_ops,
 515                .of_match_table = dwc_eth_dwmac_match,
 516        },
 517};
 518module_platform_driver(dwc_eth_dwmac_driver);
 519
 520MODULE_AUTHOR("Joao Pinto <jpinto@synopsys.com>");
 521MODULE_DESCRIPTION("Synopsys DWC Ethernet Quality-of-Service v4.10a driver");
 522MODULE_LICENSE("GPL v2");
 523