linux/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * dwmac-stm32.c - DWMAC Specific Glue layer for STM32 MCU
   4 *
   5 * Copyright (C) STMicroelectronics SA 2017
   6 * Author:  Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
   7 */
   8
   9#include <linux/clk.h>
  10#include <linux/kernel.h>
  11#include <linux/mfd/syscon.h>
  12#include <linux/module.h>
  13#include <linux/of.h>
  14#include <linux/of_device.h>
  15#include <linux/of_net.h>
  16#include <linux/phy.h>
  17#include <linux/platform_device.h>
  18#include <linux/pm_wakeirq.h>
  19#include <linux/regmap.h>
  20#include <linux/slab.h>
  21#include <linux/stmmac.h>
  22
  23#include "stmmac_platform.h"
  24
  25#define SYSCFG_MCU_ETH_MASK             BIT(23)
  26#define SYSCFG_MP1_ETH_MASK             GENMASK(23, 16)
  27#define SYSCFG_PMCCLRR_OFFSET           0x40
  28
  29#define SYSCFG_PMCR_ETH_CLK_SEL         BIT(16)
  30#define SYSCFG_PMCR_ETH_REF_CLK_SEL     BIT(17)
  31
  32/*  Ethernet PHY interface selection in register SYSCFG Configuration
  33 *------------------------------------------
  34 * src   |BIT(23)| BIT(22)| BIT(21)|BIT(20)|
  35 *------------------------------------------
  36 * MII   |   0   |   0    |   0    |   1   |
  37 *------------------------------------------
  38 * GMII  |   0   |   0    |   0    |   0   |
  39 *------------------------------------------
  40 * RGMII |   0   |   0    |   1    |  n/a  |
  41 *------------------------------------------
  42 * RMII  |   1   |   0    |   0    |  n/a  |
  43 *------------------------------------------
  44 */
  45#define SYSCFG_PMCR_ETH_SEL_MII         BIT(20)
  46#define SYSCFG_PMCR_ETH_SEL_RGMII       BIT(21)
  47#define SYSCFG_PMCR_ETH_SEL_RMII        BIT(23)
  48#define SYSCFG_PMCR_ETH_SEL_GMII        0
  49#define SYSCFG_MCU_ETH_SEL_MII          0
  50#define SYSCFG_MCU_ETH_SEL_RMII         1
  51
  52/* STM32MP1 register definitions
  53 *
  54 * Below table summarizes the clock requirement and clock sources for
  55 * supported phy interface modes.
  56 * __________________________________________________________________________
  57 *|PHY_MODE | Normal | PHY wo crystal|   PHY wo crystal   |No 125Mhz from PHY|
  58 *|         |        |      25MHz    |        50MHz       |                  |
  59 * ---------------------------------------------------------------------------
  60 *|  MII    |    -   |     eth-ck    |        n/a         |       n/a        |
  61 *|         |        |               |                    |                  |
  62 * ---------------------------------------------------------------------------
  63 *|  GMII   |    -   |     eth-ck    |        n/a         |       n/a        |
  64 *|         |        |               |                    |                  |
  65 * ---------------------------------------------------------------------------
  66 *| RGMII   |    -   |     eth-ck    |        n/a         |  eth-ck (no pin) |
  67 *|         |        |               |                    |  st,eth-clk-sel  |
  68 * ---------------------------------------------------------------------------
  69 *| RMII    |    -   |     eth-ck    |      eth-ck        |       n/a        |
  70 *|         |        |               | st,eth-ref-clk-sel |                  |
  71 * ---------------------------------------------------------------------------
  72 *
  73 * BIT(17) : set this bit in RMII mode when you have PHY without crystal 50MHz
  74 * BIT(16) : set this bit in GMII/RGMII PHY when you do not want use 125Mhz
  75 * from PHY
  76 *-----------------------------------------------------
  77 * src   |         BIT(17)       |       BIT(16)      |
  78 *-----------------------------------------------------
  79 * MII   |           n/a         |         n/a        |
  80 *-----------------------------------------------------
  81 * GMII  |           n/a         |   st,eth-clk-sel   |
  82 *-----------------------------------------------------
  83 * RGMII |           n/a         |   st,eth-clk-sel   |
  84 *-----------------------------------------------------
  85 * RMII  |   st,eth-ref-clk-sel  |         n/a        |
  86 *-----------------------------------------------------
  87 *
  88 */
  89
  90struct stm32_dwmac {
  91        struct clk *clk_tx;
  92        struct clk *clk_rx;
  93        struct clk *clk_eth_ck;
  94        struct clk *clk_ethstp;
  95        struct clk *syscfg_clk;
  96        int eth_clk_sel_reg;
  97        int eth_ref_clk_sel_reg;
  98        int irq_pwr_wakeup;
  99        u32 mode_reg;            /* MAC glue-logic mode register */
 100        struct regmap *regmap;
 101        u32 speed;
 102        const struct stm32_ops *ops;
 103        struct device *dev;
 104};
 105
 106struct stm32_ops {
 107        int (*set_mode)(struct plat_stmmacenet_data *plat_dat);
 108        int (*clk_prepare)(struct stm32_dwmac *dwmac, bool prepare);
 109        int (*suspend)(struct stm32_dwmac *dwmac);
 110        void (*resume)(struct stm32_dwmac *dwmac);
 111        int (*parse_data)(struct stm32_dwmac *dwmac,
 112                          struct device *dev);
 113        u32 syscfg_eth_mask;
 114};
 115
 116static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat)
 117{
 118        struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
 119        int ret;
 120
 121        if (dwmac->ops->set_mode) {
 122                ret = dwmac->ops->set_mode(plat_dat);
 123                if (ret)
 124                        return ret;
 125        }
 126
 127        ret = clk_prepare_enable(dwmac->clk_tx);
 128        if (ret)
 129                return ret;
 130
 131        if (!dwmac->dev->power.is_suspended) {
 132                ret = clk_prepare_enable(dwmac->clk_rx);
 133                if (ret) {
 134                        clk_disable_unprepare(dwmac->clk_tx);
 135                        return ret;
 136                }
 137        }
 138
 139        if (dwmac->ops->clk_prepare) {
 140                ret = dwmac->ops->clk_prepare(dwmac, true);
 141                if (ret) {
 142                        clk_disable_unprepare(dwmac->clk_rx);
 143                        clk_disable_unprepare(dwmac->clk_tx);
 144                }
 145        }
 146
 147        return ret;
 148}
 149
 150static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
 151{
 152        int ret = 0;
 153
 154        if (prepare) {
 155                ret = clk_prepare_enable(dwmac->syscfg_clk);
 156                if (ret)
 157                        return ret;
 158
 159                if (dwmac->clk_eth_ck) {
 160                        ret = clk_prepare_enable(dwmac->clk_eth_ck);
 161                        if (ret) {
 162                                clk_disable_unprepare(dwmac->syscfg_clk);
 163                                return ret;
 164                        }
 165                }
 166        } else {
 167                clk_disable_unprepare(dwmac->syscfg_clk);
 168                if (dwmac->clk_eth_ck)
 169                        clk_disable_unprepare(dwmac->clk_eth_ck);
 170        }
 171        return ret;
 172}
 173
 174static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
 175{
 176        struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
 177        u32 reg = dwmac->mode_reg;
 178        int val, ret;
 179
 180        switch (plat_dat->interface) {
 181        case PHY_INTERFACE_MODE_MII:
 182                val = SYSCFG_PMCR_ETH_SEL_MII;
 183                pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n");
 184                break;
 185        case PHY_INTERFACE_MODE_GMII:
 186                val = SYSCFG_PMCR_ETH_SEL_GMII;
 187                if (dwmac->eth_clk_sel_reg)
 188                        val |= SYSCFG_PMCR_ETH_CLK_SEL;
 189                pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n");
 190                break;
 191        case PHY_INTERFACE_MODE_RMII:
 192                val = SYSCFG_PMCR_ETH_SEL_RMII;
 193                if (dwmac->eth_ref_clk_sel_reg)
 194                        val |= SYSCFG_PMCR_ETH_REF_CLK_SEL;
 195                pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n");
 196                break;
 197        case PHY_INTERFACE_MODE_RGMII:
 198        case PHY_INTERFACE_MODE_RGMII_ID:
 199        case PHY_INTERFACE_MODE_RGMII_RXID:
 200        case PHY_INTERFACE_MODE_RGMII_TXID:
 201                val = SYSCFG_PMCR_ETH_SEL_RGMII;
 202                if (dwmac->eth_clk_sel_reg)
 203                        val |= SYSCFG_PMCR_ETH_CLK_SEL;
 204                pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n");
 205                break;
 206        default:
 207                pr_debug("SYSCFG init :  Do not manage %d interface\n",
 208                         plat_dat->interface);
 209                /* Do not manage others interfaces */
 210                return -EINVAL;
 211        }
 212
 213        /* Need to update PMCCLRR (clear register) */
 214        ret = regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
 215                           dwmac->ops->syscfg_eth_mask);
 216
 217        /* Update PMCSETR (set register) */
 218        return regmap_update_bits(dwmac->regmap, reg,
 219                                 dwmac->ops->syscfg_eth_mask, val);
 220}
 221
 222static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat)
 223{
 224        struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
 225        u32 reg = dwmac->mode_reg;
 226        int val;
 227
 228        switch (plat_dat->interface) {
 229        case PHY_INTERFACE_MODE_MII:
 230                val = SYSCFG_MCU_ETH_SEL_MII;
 231                pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n");
 232                break;
 233        case PHY_INTERFACE_MODE_RMII:
 234                val = SYSCFG_MCU_ETH_SEL_RMII;
 235                pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n");
 236                break;
 237        default:
 238                pr_debug("SYSCFG init :  Do not manage %d interface\n",
 239                         plat_dat->interface);
 240                /* Do not manage others interfaces */
 241                return -EINVAL;
 242        }
 243
 244        return regmap_update_bits(dwmac->regmap, reg,
 245                                 dwmac->ops->syscfg_eth_mask, val << 23);
 246}
 247
 248static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac)
 249{
 250        clk_disable_unprepare(dwmac->clk_tx);
 251        clk_disable_unprepare(dwmac->clk_rx);
 252
 253        if (dwmac->ops->clk_prepare)
 254                dwmac->ops->clk_prepare(dwmac, false);
 255}
 256
 257static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac,
 258                                  struct device *dev)
 259{
 260        struct device_node *np = dev->of_node;
 261        int err;
 262
 263        /*  Get TX/RX clocks */
 264        dwmac->clk_tx = devm_clk_get(dev, "mac-clk-tx");
 265        if (IS_ERR(dwmac->clk_tx)) {
 266                dev_err(dev, "No ETH Tx clock provided...\n");
 267                return PTR_ERR(dwmac->clk_tx);
 268        }
 269
 270        dwmac->clk_rx = devm_clk_get(dev, "mac-clk-rx");
 271        if (IS_ERR(dwmac->clk_rx)) {
 272                dev_err(dev, "No ETH Rx clock provided...\n");
 273                return PTR_ERR(dwmac->clk_rx);
 274        }
 275
 276        if (dwmac->ops->parse_data) {
 277                err = dwmac->ops->parse_data(dwmac, dev);
 278                if (err)
 279                        return err;
 280        }
 281
 282        /* Get mode register */
 283        dwmac->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
 284        if (IS_ERR(dwmac->regmap))
 285                return PTR_ERR(dwmac->regmap);
 286
 287        err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->mode_reg);
 288        if (err)
 289                dev_err(dev, "Can't get sysconfig mode offset (%d)\n", err);
 290
 291        return err;
 292}
 293
 294static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
 295                               struct device *dev)
 296{
 297        struct platform_device *pdev = to_platform_device(dev);
 298        struct device_node *np = dev->of_node;
 299        int err = 0;
 300
 301        /* Gigabit Ethernet 125MHz clock selection. */
 302        dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel");
 303
 304        /* Ethernet 50Mhz RMII clock selection */
 305        dwmac->eth_ref_clk_sel_reg =
 306                of_property_read_bool(np, "st,eth-ref-clk-sel");
 307
 308        /*  Get ETH_CLK clocks */
 309        dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
 310        if (IS_ERR(dwmac->clk_eth_ck)) {
 311                dev_warn(dev, "No phy clock provided...\n");
 312                dwmac->clk_eth_ck = NULL;
 313        }
 314
 315        /*  Clock used for low power mode */
 316        dwmac->clk_ethstp = devm_clk_get(dev, "ethstp");
 317        if (IS_ERR(dwmac->clk_ethstp)) {
 318                dev_err(dev,
 319                        "No ETH peripheral clock provided for CStop mode ...\n");
 320                return PTR_ERR(dwmac->clk_ethstp);
 321        }
 322
 323        /*  Clock for sysconfig */
 324        dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk");
 325        if (IS_ERR(dwmac->syscfg_clk)) {
 326                dev_err(dev, "No syscfg clock provided...\n");
 327                return PTR_ERR(dwmac->syscfg_clk);
 328        }
 329
 330        /* Get IRQ information early to have an ability to ask for deferred
 331         * probe if needed before we went too far with resource allocation.
 332         */
 333        dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev,
 334                                                        "stm32_pwr_wakeup");
 335        if (dwmac->irq_pwr_wakeup == -EPROBE_DEFER)
 336                return -EPROBE_DEFER;
 337
 338        if (!dwmac->clk_eth_ck && dwmac->irq_pwr_wakeup >= 0) {
 339                err = device_init_wakeup(&pdev->dev, true);
 340                if (err) {
 341                        dev_err(&pdev->dev, "Failed to init wake up irq\n");
 342                        return err;
 343                }
 344                err = dev_pm_set_dedicated_wake_irq(&pdev->dev,
 345                                                    dwmac->irq_pwr_wakeup);
 346                if (err) {
 347                        dev_err(&pdev->dev, "Failed to set wake up irq\n");
 348                        device_init_wakeup(&pdev->dev, false);
 349                }
 350                device_set_wakeup_enable(&pdev->dev, false);
 351        }
 352        return err;
 353}
 354
 355static int stm32_dwmac_probe(struct platform_device *pdev)
 356{
 357        struct plat_stmmacenet_data *plat_dat;
 358        struct stmmac_resources stmmac_res;
 359        struct stm32_dwmac *dwmac;
 360        const struct stm32_ops *data;
 361        int ret;
 362
 363        ret = stmmac_get_platform_resources(pdev, &stmmac_res);
 364        if (ret)
 365                return ret;
 366
 367        plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
 368        if (IS_ERR(plat_dat))
 369                return PTR_ERR(plat_dat);
 370
 371        dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
 372        if (!dwmac) {
 373                ret = -ENOMEM;
 374                goto err_remove_config_dt;
 375        }
 376
 377        data = of_device_get_match_data(&pdev->dev);
 378        if (!data) {
 379                dev_err(&pdev->dev, "no of match data provided\n");
 380                ret = -EINVAL;
 381                goto err_remove_config_dt;
 382        }
 383
 384        dwmac->ops = data;
 385        dwmac->dev = &pdev->dev;
 386
 387        ret = stm32_dwmac_parse_data(dwmac, &pdev->dev);
 388        if (ret) {
 389                dev_err(&pdev->dev, "Unable to parse OF data\n");
 390                goto err_remove_config_dt;
 391        }
 392
 393        plat_dat->bsp_priv = dwmac;
 394
 395        ret = stm32_dwmac_init(plat_dat);
 396        if (ret)
 397                goto err_remove_config_dt;
 398
 399        ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
 400        if (ret)
 401                goto err_clk_disable;
 402
 403        return 0;
 404
 405err_clk_disable:
 406        stm32_dwmac_clk_disable(dwmac);
 407err_remove_config_dt:
 408        stmmac_remove_config_dt(pdev, plat_dat);
 409
 410        return ret;
 411}
 412
 413static int stm32_dwmac_remove(struct platform_device *pdev)
 414{
 415        struct net_device *ndev = platform_get_drvdata(pdev);
 416        struct stmmac_priv *priv = netdev_priv(ndev);
 417        int ret = stmmac_dvr_remove(&pdev->dev);
 418        struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
 419
 420        stm32_dwmac_clk_disable(priv->plat->bsp_priv);
 421
 422        if (dwmac->irq_pwr_wakeup >= 0) {
 423                dev_pm_clear_wake_irq(&pdev->dev);
 424                device_init_wakeup(&pdev->dev, false);
 425        }
 426
 427        return ret;
 428}
 429
 430static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
 431{
 432        int ret = 0;
 433
 434        ret = clk_prepare_enable(dwmac->clk_ethstp);
 435        if (ret)
 436                return ret;
 437
 438        clk_disable_unprepare(dwmac->clk_tx);
 439        clk_disable_unprepare(dwmac->syscfg_clk);
 440        if (dwmac->clk_eth_ck)
 441                clk_disable_unprepare(dwmac->clk_eth_ck);
 442
 443        return ret;
 444}
 445
 446static void stm32mp1_resume(struct stm32_dwmac *dwmac)
 447{
 448        clk_disable_unprepare(dwmac->clk_ethstp);
 449}
 450
 451static int stm32mcu_suspend(struct stm32_dwmac *dwmac)
 452{
 453        clk_disable_unprepare(dwmac->clk_tx);
 454        clk_disable_unprepare(dwmac->clk_rx);
 455
 456        return 0;
 457}
 458
 459#ifdef CONFIG_PM_SLEEP
 460static int stm32_dwmac_suspend(struct device *dev)
 461{
 462        struct net_device *ndev = dev_get_drvdata(dev);
 463        struct stmmac_priv *priv = netdev_priv(ndev);
 464        struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
 465
 466        int ret;
 467
 468        ret = stmmac_suspend(dev);
 469
 470        if (dwmac->ops->suspend)
 471                ret = dwmac->ops->suspend(dwmac);
 472
 473        return ret;
 474}
 475
 476static int stm32_dwmac_resume(struct device *dev)
 477{
 478        struct net_device *ndev = dev_get_drvdata(dev);
 479        struct stmmac_priv *priv = netdev_priv(ndev);
 480        struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
 481        int ret;
 482
 483        if (dwmac->ops->resume)
 484                dwmac->ops->resume(dwmac);
 485
 486        ret = stm32_dwmac_init(priv->plat);
 487        if (ret)
 488                return ret;
 489
 490        ret = stmmac_resume(dev);
 491
 492        return ret;
 493}
 494#endif /* CONFIG_PM_SLEEP */
 495
 496static SIMPLE_DEV_PM_OPS(stm32_dwmac_pm_ops,
 497        stm32_dwmac_suspend, stm32_dwmac_resume);
 498
 499static struct stm32_ops stm32mcu_dwmac_data = {
 500        .set_mode = stm32mcu_set_mode,
 501        .suspend = stm32mcu_suspend,
 502        .syscfg_eth_mask = SYSCFG_MCU_ETH_MASK
 503};
 504
 505static struct stm32_ops stm32mp1_dwmac_data = {
 506        .set_mode = stm32mp1_set_mode,
 507        .clk_prepare = stm32mp1_clk_prepare,
 508        .suspend = stm32mp1_suspend,
 509        .resume = stm32mp1_resume,
 510        .parse_data = stm32mp1_parse_data,
 511        .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK
 512};
 513
 514static const struct of_device_id stm32_dwmac_match[] = {
 515        { .compatible = "st,stm32-dwmac", .data = &stm32mcu_dwmac_data},
 516        { .compatible = "st,stm32mp1-dwmac", .data = &stm32mp1_dwmac_data},
 517        { }
 518};
 519MODULE_DEVICE_TABLE(of, stm32_dwmac_match);
 520
 521static struct platform_driver stm32_dwmac_driver = {
 522        .probe  = stm32_dwmac_probe,
 523        .remove = stm32_dwmac_remove,
 524        .driver = {
 525                .name           = "stm32-dwmac",
 526                .pm             = &stm32_dwmac_pm_ops,
 527                .of_match_table = stm32_dwmac_match,
 528        },
 529};
 530module_platform_driver(stm32_dwmac_driver);
 531
 532MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@gmail.com>");
 533MODULE_AUTHOR("Christophe Roullier <christophe.roullier@st.com>");
 534MODULE_DESCRIPTION("STMicroelectronics STM32 DWMAC Specific Glue layer");
 535MODULE_LICENSE("GPL v2");
 536