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