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