linux/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer
   4 *
   5 * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
   6 * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
   7 * Contributors: Giuseppe Cavallaro <peppe.cavallaro@st.com>
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/slab.h>
  12#include <linux/platform_device.h>
  13#include <linux/stmmac.h>
  14#include <linux/phy.h>
  15#include <linux/mfd/syscon.h>
  16#include <linux/module.h>
  17#include <linux/regmap.h>
  18#include <linux/clk.h>
  19#include <linux/of.h>
  20#include <linux/of_device.h>
  21#include <linux/of_net.h>
  22
  23#include "stmmac_platform.h"
  24
  25#define DWMAC_125MHZ    125000000
  26#define DWMAC_50MHZ     50000000
  27#define DWMAC_25MHZ     25000000
  28#define DWMAC_2_5MHZ    2500000
  29
  30#define IS_PHY_IF_MODE_RGMII(iface)     (iface == PHY_INTERFACE_MODE_RGMII || \
  31                        iface == PHY_INTERFACE_MODE_RGMII_ID || \
  32                        iface == PHY_INTERFACE_MODE_RGMII_RXID || \
  33                        iface == PHY_INTERFACE_MODE_RGMII_TXID)
  34
  35#define IS_PHY_IF_MODE_GBIT(iface)      (IS_PHY_IF_MODE_RGMII(iface) || \
  36                                         iface == PHY_INTERFACE_MODE_GMII)
  37
  38/* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families)
  39 *
  40 * Below table summarizes the clock requirement and clock sources for
  41 * supported phy interface modes with link speeds.
  42 * ________________________________________________
  43 *|  PHY_MODE   | 1000 Mbit Link | 100 Mbit Link   |
  44 * ------------------------------------------------
  45 *|     MII     |       n/a      |      25Mhz      |
  46 *|             |                |      txclk      |
  47 * ------------------------------------------------
  48 *|     GMII    |     125Mhz     |      25Mhz      |
  49 *|             |  clk-125/txclk |      txclk      |
  50 * ------------------------------------------------
  51 *|     RGMII   |     125Mhz     |      25Mhz      |
  52 *|             |  clk-125/txclk |      clkgen     |
  53 *|             |    clkgen      |                 |
  54 * ------------------------------------------------
  55 *|     RMII    |       n/a      |      25Mhz      |
  56 *|             |                |clkgen/phyclk-in |
  57 * ------------------------------------------------
  58 *
  59 *        Register Configuration
  60 *-------------------------------
  61 * src   |BIT(8)| BIT(7)| BIT(6)|
  62 *-------------------------------
  63 * txclk |   0  |  n/a  |   1   |
  64 *-------------------------------
  65 * ck_125|   0  |  n/a  |   0   |
  66 *-------------------------------
  67 * phyclk|   1  |   0   |  n/a  |
  68 *-------------------------------
  69 * clkgen|   1  |   1   |  n/a  |
  70 *-------------------------------
  71 */
  72
  73#define STIH4XX_RETIME_SRC_MASK                 GENMASK(8, 6)
  74#define STIH4XX_ETH_SEL_TX_RETIME_CLK           BIT(8)
  75#define STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK  BIT(7)
  76#define STIH4XX_ETH_SEL_TXCLK_NOT_CLK125        BIT(6)
  77
  78/* STiD127 register definitions
  79 *-----------------------
  80 * src   |BIT(6)| BIT(7)|
  81 *-----------------------
  82 * MII   |  1   |   n/a |
  83 *-----------------------
  84 * RMII  |  n/a |   1   |
  85 * clkgen|      |       |
  86 *-----------------------
  87 * RMII  |  n/a |   0   |
  88 * phyclk|      |       |
  89 *-----------------------
  90 * RGMII |  1   |  n/a  |
  91 * clkgen|      |       |
  92 *-----------------------
  93 */
  94
  95#define STID127_RETIME_SRC_MASK                 GENMASK(7, 6)
  96#define STID127_ETH_SEL_INTERNAL_NOTEXT_PHYCLK  BIT(7)
  97#define STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK   BIT(6)
  98
  99#define ENMII_MASK      GENMASK(5, 5)
 100#define ENMII           BIT(5)
 101#define EN_MASK         GENMASK(1, 1)
 102#define EN              BIT(1)
 103
 104/*
 105 * 3 bits [4:2]
 106 *      000-GMII/MII
 107 *      001-RGMII
 108 *      010-SGMII
 109 *      100-RMII
 110 */
 111#define MII_PHY_SEL_MASK        GENMASK(4, 2)
 112#define ETH_PHY_SEL_RMII        BIT(4)
 113#define ETH_PHY_SEL_SGMII       BIT(3)
 114#define ETH_PHY_SEL_RGMII       BIT(2)
 115#define ETH_PHY_SEL_GMII        0x0
 116#define ETH_PHY_SEL_MII         0x0
 117
 118struct sti_dwmac {
 119        phy_interface_t interface;      /* MII interface */
 120        bool ext_phyclk;        /* Clock from external PHY */
 121        u32 tx_retime_src;      /* TXCLK Retiming*/
 122        struct clk *clk;        /* PHY clock */
 123        u32 ctrl_reg;           /* GMAC glue-logic control register */
 124        int clk_sel_reg;        /* GMAC ext clk selection register */
 125        struct regmap *regmap;
 126        bool gmac_en;
 127        u32 speed;
 128        void (*fix_retime_src)(void *priv, unsigned int speed);
 129};
 130
 131struct sti_dwmac_of_data {
 132        void (*fix_retime_src)(void *priv, unsigned int speed);
 133};
 134
 135static u32 phy_intf_sels[] = {
 136        [PHY_INTERFACE_MODE_MII] = ETH_PHY_SEL_MII,
 137        [PHY_INTERFACE_MODE_GMII] = ETH_PHY_SEL_GMII,
 138        [PHY_INTERFACE_MODE_RGMII] = ETH_PHY_SEL_RGMII,
 139        [PHY_INTERFACE_MODE_RGMII_ID] = ETH_PHY_SEL_RGMII,
 140        [PHY_INTERFACE_MODE_SGMII] = ETH_PHY_SEL_SGMII,
 141        [PHY_INTERFACE_MODE_RMII] = ETH_PHY_SEL_RMII,
 142};
 143
 144enum {
 145        TX_RETIME_SRC_NA = 0,
 146        TX_RETIME_SRC_TXCLK = 1,
 147        TX_RETIME_SRC_CLK_125,
 148        TX_RETIME_SRC_PHYCLK,
 149        TX_RETIME_SRC_CLKGEN,
 150};
 151
 152static u32 stih4xx_tx_retime_val[] = {
 153        [TX_RETIME_SRC_TXCLK] = STIH4XX_ETH_SEL_TXCLK_NOT_CLK125,
 154        [TX_RETIME_SRC_CLK_125] = 0x0,
 155        [TX_RETIME_SRC_PHYCLK] = STIH4XX_ETH_SEL_TX_RETIME_CLK,
 156        [TX_RETIME_SRC_CLKGEN] = STIH4XX_ETH_SEL_TX_RETIME_CLK
 157                                 | STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
 158};
 159
 160static void stih4xx_fix_retime_src(void *priv, u32 spd)
 161{
 162        struct sti_dwmac *dwmac = priv;
 163        u32 src = dwmac->tx_retime_src;
 164        u32 reg = dwmac->ctrl_reg;
 165        u32 freq = 0;
 166
 167        if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
 168                src = TX_RETIME_SRC_TXCLK;
 169        } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
 170                if (dwmac->ext_phyclk) {
 171                        src = TX_RETIME_SRC_PHYCLK;
 172                } else {
 173                        src = TX_RETIME_SRC_CLKGEN;
 174                        freq = DWMAC_50MHZ;
 175                }
 176        } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
 177                /* On GiGa clk source can be either ext or from clkgen */
 178                if (spd == SPEED_1000) {
 179                        freq = DWMAC_125MHZ;
 180                } else {
 181                        /* Switch to clkgen for these speeds */
 182                        src = TX_RETIME_SRC_CLKGEN;
 183                        if (spd == SPEED_100)
 184                                freq = DWMAC_25MHZ;
 185                        else if (spd == SPEED_10)
 186                                freq = DWMAC_2_5MHZ;
 187                }
 188        }
 189
 190        if (src == TX_RETIME_SRC_CLKGEN && freq)
 191                clk_set_rate(dwmac->clk, freq);
 192
 193        regmap_update_bits(dwmac->regmap, reg, STIH4XX_RETIME_SRC_MASK,
 194                           stih4xx_tx_retime_val[src]);
 195}
 196
 197static void stid127_fix_retime_src(void *priv, u32 spd)
 198{
 199        struct sti_dwmac *dwmac = priv;
 200        u32 reg = dwmac->ctrl_reg;
 201        u32 freq = 0;
 202        u32 val = 0;
 203
 204        if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
 205                val = STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK;
 206        } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
 207                if (!dwmac->ext_phyclk) {
 208                        val = STID127_ETH_SEL_INTERNAL_NOTEXT_PHYCLK;
 209                        freq = DWMAC_50MHZ;
 210                }
 211        } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
 212                val = STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK;
 213                if (spd == SPEED_1000)
 214                        freq = DWMAC_125MHZ;
 215                else if (spd == SPEED_100)
 216                        freq = DWMAC_25MHZ;
 217                else if (spd == SPEED_10)
 218                        freq = DWMAC_2_5MHZ;
 219        }
 220
 221        if (freq)
 222                clk_set_rate(dwmac->clk, freq);
 223
 224        regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val);
 225}
 226
 227static int sti_dwmac_set_mode(struct sti_dwmac *dwmac)
 228{
 229        struct regmap *regmap = dwmac->regmap;
 230        int iface = dwmac->interface;
 231        u32 reg = dwmac->ctrl_reg;
 232        u32 val;
 233
 234        if (dwmac->gmac_en)
 235                regmap_update_bits(regmap, reg, EN_MASK, EN);
 236
 237        regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
 238
 239        val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
 240        regmap_update_bits(regmap, reg, ENMII_MASK, val);
 241
 242        dwmac->fix_retime_src(dwmac, dwmac->speed);
 243
 244        return 0;
 245}
 246
 247static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
 248                                struct platform_device *pdev)
 249{
 250        struct resource *res;
 251        struct device *dev = &pdev->dev;
 252        struct device_node *np = dev->of_node;
 253        struct regmap *regmap;
 254        int err;
 255
 256        /* clk selection from extra syscfg register */
 257        dwmac->clk_sel_reg = -ENXIO;
 258        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-clkconf");
 259        if (res)
 260                dwmac->clk_sel_reg = res->start;
 261
 262        regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
 263        if (IS_ERR(regmap))
 264                return PTR_ERR(regmap);
 265
 266        err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->ctrl_reg);
 267        if (err) {
 268                dev_err(dev, "Can't get sysconfig ctrl offset (%d)\n", err);
 269                return err;
 270        }
 271
 272        err = of_get_phy_mode(np, &dwmac->interface);
 273        if (err && err != -ENODEV) {
 274                dev_err(dev, "Can't get phy-mode\n");
 275                return err;
 276        }
 277
 278        dwmac->regmap = regmap;
 279        dwmac->gmac_en = of_property_read_bool(np, "st,gmac_en");
 280        dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
 281        dwmac->tx_retime_src = TX_RETIME_SRC_NA;
 282        dwmac->speed = SPEED_100;
 283
 284        if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
 285                const char *rs;
 286
 287                dwmac->tx_retime_src = TX_RETIME_SRC_CLKGEN;
 288
 289                err = of_property_read_string(np, "st,tx-retime-src", &rs);
 290                if (err < 0) {
 291                        dev_warn(dev, "Use internal clock source\n");
 292                } else {
 293                        if (!strcasecmp(rs, "clk_125"))
 294                                dwmac->tx_retime_src = TX_RETIME_SRC_CLK_125;
 295                        else if (!strcasecmp(rs, "txclk"))
 296                                dwmac->tx_retime_src = TX_RETIME_SRC_TXCLK;
 297                }
 298                dwmac->speed = SPEED_1000;
 299        }
 300
 301        dwmac->clk = devm_clk_get(dev, "sti-ethclk");
 302        if (IS_ERR(dwmac->clk)) {
 303                dev_warn(dev, "No phy clock provided...\n");
 304                dwmac->clk = NULL;
 305        }
 306
 307        return 0;
 308}
 309
 310static int sti_dwmac_probe(struct platform_device *pdev)
 311{
 312        struct plat_stmmacenet_data *plat_dat;
 313        const struct sti_dwmac_of_data *data;
 314        struct stmmac_resources stmmac_res;
 315        struct sti_dwmac *dwmac;
 316        int ret;
 317
 318        data = of_device_get_match_data(&pdev->dev);
 319        if (!data) {
 320                dev_err(&pdev->dev, "No OF match data provided\n");
 321                return -EINVAL;
 322        }
 323
 324        ret = stmmac_get_platform_resources(pdev, &stmmac_res);
 325        if (ret)
 326                return ret;
 327
 328        plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
 329        if (IS_ERR(plat_dat))
 330                return PTR_ERR(plat_dat);
 331
 332        dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
 333        if (!dwmac) {
 334                ret = -ENOMEM;
 335                goto err_remove_config_dt;
 336        }
 337
 338        ret = sti_dwmac_parse_data(dwmac, pdev);
 339        if (ret) {
 340                dev_err(&pdev->dev, "Unable to parse OF data\n");
 341                goto err_remove_config_dt;
 342        }
 343
 344        dwmac->fix_retime_src = data->fix_retime_src;
 345
 346        plat_dat->bsp_priv = dwmac;
 347        plat_dat->fix_mac_speed = data->fix_retime_src;
 348
 349        ret = clk_prepare_enable(dwmac->clk);
 350        if (ret)
 351                goto err_remove_config_dt;
 352
 353        ret = sti_dwmac_set_mode(dwmac);
 354        if (ret)
 355                goto disable_clk;
 356
 357        ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
 358        if (ret)
 359                goto disable_clk;
 360
 361        return 0;
 362
 363disable_clk:
 364        clk_disable_unprepare(dwmac->clk);
 365err_remove_config_dt:
 366        stmmac_remove_config_dt(pdev, plat_dat);
 367
 368        return ret;
 369}
 370
 371static int sti_dwmac_remove(struct platform_device *pdev)
 372{
 373        struct sti_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
 374        int ret = stmmac_dvr_remove(&pdev->dev);
 375
 376        clk_disable_unprepare(dwmac->clk);
 377
 378        return ret;
 379}
 380
 381#ifdef CONFIG_PM_SLEEP
 382static int sti_dwmac_suspend(struct device *dev)
 383{
 384        struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev);
 385        int ret = stmmac_suspend(dev);
 386
 387        clk_disable_unprepare(dwmac->clk);
 388
 389        return ret;
 390}
 391
 392static int sti_dwmac_resume(struct device *dev)
 393{
 394        struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev);
 395
 396        clk_prepare_enable(dwmac->clk);
 397        sti_dwmac_set_mode(dwmac);
 398
 399        return stmmac_resume(dev);
 400}
 401#endif /* CONFIG_PM_SLEEP */
 402
 403static SIMPLE_DEV_PM_OPS(sti_dwmac_pm_ops, sti_dwmac_suspend,
 404                                           sti_dwmac_resume);
 405
 406static const struct sti_dwmac_of_data stih4xx_dwmac_data = {
 407        .fix_retime_src = stih4xx_fix_retime_src,
 408};
 409
 410static const struct sti_dwmac_of_data stid127_dwmac_data = {
 411        .fix_retime_src = stid127_fix_retime_src,
 412};
 413
 414static const struct of_device_id sti_dwmac_match[] = {
 415        { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data},
 416        { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data},
 417        { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
 418        { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
 419        { }
 420};
 421MODULE_DEVICE_TABLE(of, sti_dwmac_match);
 422
 423static struct platform_driver sti_dwmac_driver = {
 424        .probe  = sti_dwmac_probe,
 425        .remove = sti_dwmac_remove,
 426        .driver = {
 427                .name           = "sti-dwmac",
 428                .pm             = &sti_dwmac_pm_ops,
 429                .of_match_table = sti_dwmac_match,
 430        },
 431};
 432module_platform_driver(sti_dwmac_driver);
 433
 434MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@st.com>");
 435MODULE_DESCRIPTION("STMicroelectronics DWMAC Specific Glue layer");
 436MODULE_LICENSE("GPL");
 437