root/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c

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

DEFINITIONS

This source file includes following definitions.
  1. dwc_eth_dwmac_config_dt
  2. dwc_qos_probe
  3. dwc_qos_remove
  4. tegra_eqos_fix_speed
  5. tegra_eqos_init
  6. tegra_eqos_probe
  7. tegra_eqos_remove
  8. dwc_eth_dwmac_probe
  9. dwc_eth_dwmac_remove

   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 
  27 struct 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 
  40 static 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 
 121 static 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 
 156 disable:
 157         clk_disable_unprepare(plat_dat->stmmac_clk);
 158         return ERR_PTR(err);
 159 }
 160 
 161 static 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 
 182 static 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 
 255 static 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 
 269 static 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 
 365 out:
 366         return eqos;
 367 
 368 reset:
 369         reset_control_assert(eqos->rst);
 370 reset_phy:
 371         gpiod_set_value(eqos->reset, 1);
 372 disable_tx:
 373         clk_disable_unprepare(eqos->clk_tx);
 374 disable_rx:
 375         clk_disable_unprepare(eqos->clk_rx);
 376 disable_slave:
 377         clk_disable_unprepare(eqos->clk_slave);
 378 disable_master:
 379         clk_disable_unprepare(eqos->clk_master);
 380 error:
 381         eqos = ERR_PTR(err);
 382         goto out;
 383 }
 384 
 385 static 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 
 399 struct 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 
 406 static const struct dwc_eth_dwmac_data dwc_qos_data = {
 407         .probe = dwc_qos_probe,
 408         .remove = dwc_qos_remove,
 409 };
 410 
 411 static const struct dwc_eth_dwmac_data tegra_eqos_data = {
 412         .probe = tegra_eqos_probe,
 413         .remove = tegra_eqos_remove,
 414 };
 415 
 416 static 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 
 466 remove:
 467         data->remove(pdev);
 468 remove_config:
 469         stmmac_remove_config_dt(pdev, plat_dat);
 470 
 471         return ret;
 472 }
 473 
 474 static 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 
 496 static 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 };
 501 MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
 502 
 503 static 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 };
 512 module_platform_driver(dwc_eth_dwmac_driver);
 513 
 514 MODULE_AUTHOR("Joao Pinto <jpinto@synopsys.com>");
 515 MODULE_DESCRIPTION("Synopsys DWC Ethernet Quality-of-Service v4.10a driver");
 516 MODULE_LICENSE("GPL v2");

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