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/regmap.h>
  21#include <linux/clk.h>
  22#include <linux/of.h>
  23#include <linux/of_net.h>
  24
  25#include "stmmac_platform.h"
  26
  27#define DWMAC_125MHZ    125000000
  28#define DWMAC_50MHZ     50000000
  29#define DWMAC_25MHZ     25000000
  30#define DWMAC_2_5MHZ    2500000
  31
  32#define IS_PHY_IF_MODE_RGMII(iface)     (iface == PHY_INTERFACE_MODE_RGMII || \
  33                        iface == PHY_INTERFACE_MODE_RGMII_ID || \
  34                        iface == PHY_INTERFACE_MODE_RGMII_RXID || \
  35                        iface == PHY_INTERFACE_MODE_RGMII_TXID)
  36
  37#define IS_PHY_IF_MODE_GBIT(iface)      (IS_PHY_IF_MODE_RGMII(iface) || \
  38                                         iface == PHY_INTERFACE_MODE_GMII)
  39
  40/* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families)
  41 *
  42 * Below table summarizes the clock requirement and clock sources for
  43 * supported phy interface modes with link speeds.
  44 * ________________________________________________
  45 *|  PHY_MODE   | 1000 Mbit Link | 100 Mbit Link   |
  46 * ------------------------------------------------
  47 *|     MII     |       n/a      |      25Mhz      |
  48 *|             |                |      txclk      |
  49 * ------------------------------------------------
  50 *|     GMII    |     125Mhz     |      25Mhz      |
  51 *|             |  clk-125/txclk |      txclk      |
  52 * ------------------------------------------------
  53 *|     RGMII   |     125Mhz     |      25Mhz      |
  54 *|             |  clk-125/txclk |      clkgen     |
  55 *|             |    clkgen      |                 |
  56 * ------------------------------------------------
  57 *|     RMII    |       n/a      |      25Mhz      |
  58 *|             |                |clkgen/phyclk-in |
  59 * ------------------------------------------------
  60 *
  61 *        Register Configuration
  62 *-------------------------------
  63 * src   |BIT(8)| BIT(7)| BIT(6)|
  64 *-------------------------------
  65 * txclk |   0  |  n/a  |   1   |
  66 *-------------------------------
  67 * ck_125|   0  |  n/a  |   0   |
  68 *-------------------------------
  69 * phyclk|   1  |   0   |  n/a  |
  70 *-------------------------------
  71 * clkgen|   1  |   1   |  n/a  |
  72 *-------------------------------
  73 */
  74
  75#define STIH4XX_RETIME_SRC_MASK                 GENMASK(8, 6)
  76#define STIH4XX_ETH_SEL_TX_RETIME_CLK           BIT(8)
  77#define STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK  BIT(7)
  78#define STIH4XX_ETH_SEL_TXCLK_NOT_CLK125        BIT(6)
  79
  80/* STiD127 register definitions
  81 *-----------------------
  82 * src   |BIT(6)| BIT(7)|
  83 *-----------------------
  84 * MII   |  1   |   n/a |
  85 *-----------------------
  86 * RMII  |  n/a |   1   |
  87 * clkgen|      |       |
  88 *-----------------------
  89 * RMII  |  n/a |   0   |
  90 * phyclk|      |       |
  91 *-----------------------
  92 * RGMII |  1   |  n/a  |
  93 * clkgen|      |       |
  94 *-----------------------
  95 */
  96
  97#define STID127_RETIME_SRC_MASK                 GENMASK(7, 6)
  98#define STID127_ETH_SEL_INTERNAL_NOTEXT_PHYCLK  BIT(7)
  99#define STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK   BIT(6)
 100
 101#define ENMII_MASK      GENMASK(5, 5)
 102#define ENMII           BIT(5)
 103#define EN_MASK         GENMASK(1, 1)
 104#define EN              BIT(1)
 105
 106/*
 107 * 3 bits [4:2]
 108 *      000-GMII/MII
 109 *      001-RGMII
 110 *      010-SGMII
 111 *      100-RMII
 112 */
 113#define MII_PHY_SEL_MASK        GENMASK(4, 2)
 114#define ETH_PHY_SEL_RMII        BIT(4)
 115#define ETH_PHY_SEL_SGMII       BIT(3)
 116#define ETH_PHY_SEL_RGMII       BIT(2)
 117#define ETH_PHY_SEL_GMII        0x0
 118#define ETH_PHY_SEL_MII         0x0
 119
 120struct sti_dwmac {
 121        int interface;          /* MII interface */
 122        bool ext_phyclk;        /* Clock from external PHY */
 123        u32 tx_retime_src;      /* TXCLK Retiming*/
 124        struct clk *clk;        /* PHY clock */
 125        u32 ctrl_reg;           /* GMAC glue-logic control register */
 126        int clk_sel_reg;        /* GMAC ext clk selection register */
 127        struct device *dev;
 128        struct regmap *regmap;
 129        u32 speed;
 130};
 131
 132static u32 phy_intf_sels[] = {
 133        [PHY_INTERFACE_MODE_MII] = ETH_PHY_SEL_MII,
 134        [PHY_INTERFACE_MODE_GMII] = ETH_PHY_SEL_GMII,
 135        [PHY_INTERFACE_MODE_RGMII] = ETH_PHY_SEL_RGMII,
 136        [PHY_INTERFACE_MODE_RGMII_ID] = ETH_PHY_SEL_RGMII,
 137        [PHY_INTERFACE_MODE_SGMII] = ETH_PHY_SEL_SGMII,
 138        [PHY_INTERFACE_MODE_RMII] = ETH_PHY_SEL_RMII,
 139};
 140
 141enum {
 142        TX_RETIME_SRC_NA = 0,
 143        TX_RETIME_SRC_TXCLK = 1,
 144        TX_RETIME_SRC_CLK_125,
 145        TX_RETIME_SRC_PHYCLK,
 146        TX_RETIME_SRC_CLKGEN,
 147};
 148
 149static u32 stih4xx_tx_retime_val[] = {
 150        [TX_RETIME_SRC_TXCLK] = STIH4XX_ETH_SEL_TXCLK_NOT_CLK125,
 151        [TX_RETIME_SRC_CLK_125] = 0x0,
 152        [TX_RETIME_SRC_PHYCLK] = STIH4XX_ETH_SEL_TX_RETIME_CLK,
 153        [TX_RETIME_SRC_CLKGEN] = STIH4XX_ETH_SEL_TX_RETIME_CLK
 154                                 | STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
 155};
 156
 157static void stih4xx_fix_retime_src(void *priv, u32 spd)
 158{
 159        struct sti_dwmac *dwmac = priv;
 160        u32 src = dwmac->tx_retime_src;
 161        u32 reg = dwmac->ctrl_reg;
 162        u32 freq = 0;
 163
 164        if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
 165                src = TX_RETIME_SRC_TXCLK;
 166        } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
 167                if (dwmac->ext_phyclk) {
 168                        src = TX_RETIME_SRC_PHYCLK;
 169                } else {
 170                        src = TX_RETIME_SRC_CLKGEN;
 171                        freq = DWMAC_50MHZ;
 172                }
 173        } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
 174                /* On GiGa clk source can be either ext or from clkgen */
 175                if (spd == SPEED_1000) {
 176                        freq = DWMAC_125MHZ;
 177                } else {
 178                        /* Switch to clkgen for these speeds */
 179                        src = TX_RETIME_SRC_CLKGEN;
 180                        if (spd == SPEED_100)
 181                                freq = DWMAC_25MHZ;
 182                        else if (spd == SPEED_10)
 183                                freq = DWMAC_2_5MHZ;
 184                }
 185        }
 186
 187        if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk && freq)
 188                clk_set_rate(dwmac->clk, freq);
 189
 190        regmap_update_bits(dwmac->regmap, reg, STIH4XX_RETIME_SRC_MASK,
 191                           stih4xx_tx_retime_val[src]);
 192}
 193
 194static void stid127_fix_retime_src(void *priv, u32 spd)
 195{
 196        struct sti_dwmac *dwmac = priv;
 197        u32 reg = dwmac->ctrl_reg;
 198        u32 freq = 0;
 199        u32 val = 0;
 200
 201        if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
 202                val = STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK;
 203        } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
 204                if (!dwmac->ext_phyclk) {
 205                        val = STID127_ETH_SEL_INTERNAL_NOTEXT_PHYCLK;
 206                        freq = DWMAC_50MHZ;
 207                }
 208        } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
 209                val = STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK;
 210                if (spd == SPEED_1000)
 211                        freq = DWMAC_125MHZ;
 212                else if (spd == SPEED_100)
 213                        freq = DWMAC_25MHZ;
 214                else if (spd == SPEED_10)
 215                        freq = DWMAC_2_5MHZ;
 216        }
 217
 218        if (dwmac->clk && freq)
 219                clk_set_rate(dwmac->clk, freq);
 220
 221        regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val);
 222}
 223
 224static void sti_dwmac_ctrl_init(struct sti_dwmac *dwmac)
 225{
 226        struct regmap *regmap = dwmac->regmap;
 227        int iface = dwmac->interface;
 228        struct device *dev = dwmac->dev;
 229        struct device_node *np = dev->of_node;
 230        u32 reg = dwmac->ctrl_reg;
 231        u32 val;
 232
 233        if (dwmac->clk)
 234                clk_prepare_enable(dwmac->clk);
 235
 236        if (of_property_read_bool(np, "st,gmac_en"))
 237                regmap_update_bits(regmap, reg, EN_MASK, EN);
 238
 239        regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
 240
 241        val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
 242        regmap_update_bits(regmap, reg, ENMII_MASK, val);
 243}
 244
 245static int stix4xx_init(struct platform_device *pdev, void *priv)
 246{
 247        struct sti_dwmac *dwmac = priv;
 248        u32 spd = dwmac->speed;
 249
 250        sti_dwmac_ctrl_init(dwmac);
 251
 252        stih4xx_fix_retime_src(priv, spd);
 253
 254        return 0;
 255}
 256
 257static int stid127_init(struct platform_device *pdev, void *priv)
 258{
 259        struct sti_dwmac *dwmac = priv;
 260        u32 spd = dwmac->speed;
 261
 262        sti_dwmac_ctrl_init(dwmac);
 263
 264        stid127_fix_retime_src(priv, spd);
 265
 266        return 0;
 267}
 268
 269static void sti_dwmac_exit(struct platform_device *pdev, void *priv)
 270{
 271        struct sti_dwmac *dwmac = priv;
 272
 273        if (dwmac->clk)
 274                clk_disable_unprepare(dwmac->clk);
 275}
 276static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
 277                                struct platform_device *pdev)
 278{
 279        struct resource *res;
 280        struct device *dev = &pdev->dev;
 281        struct device_node *np = dev->of_node;
 282        struct regmap *regmap;
 283        int err;
 284
 285        if (!np)
 286                return -EINVAL;
 287
 288        /* clk selection from extra syscfg register */
 289        dwmac->clk_sel_reg = -ENXIO;
 290        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-clkconf");
 291        if (res)
 292                dwmac->clk_sel_reg = res->start;
 293
 294        regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
 295        if (IS_ERR(regmap))
 296                return PTR_ERR(regmap);
 297
 298        err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->ctrl_reg);
 299        if (err) {
 300                dev_err(dev, "Can't get sysconfig ctrl offset (%d)\n", err);
 301                return err;
 302        }
 303
 304        dwmac->dev = dev;
 305        dwmac->interface = of_get_phy_mode(np);
 306        dwmac->regmap = regmap;
 307        dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
 308        dwmac->tx_retime_src = TX_RETIME_SRC_NA;
 309        dwmac->speed = SPEED_100;
 310
 311        if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
 312                const char *rs;
 313
 314                err = of_property_read_string(np, "st,tx-retime-src", &rs);
 315                if (err < 0) {
 316                        dev_warn(dev, "Use internal clock source\n");
 317                        dwmac->tx_retime_src = TX_RETIME_SRC_CLKGEN;
 318                } else if (!strcasecmp(rs, "clk_125")) {
 319                        dwmac->tx_retime_src = TX_RETIME_SRC_CLK_125;
 320                } else if (!strcasecmp(rs, "txclk")) {
 321                        dwmac->tx_retime_src = TX_RETIME_SRC_TXCLK;
 322                }
 323
 324                dwmac->speed = SPEED_1000;
 325        }
 326
 327        dwmac->clk = devm_clk_get(dev, "sti-ethclk");
 328        if (IS_ERR(dwmac->clk)) {
 329                dev_warn(dev, "No phy clock provided...\n");
 330                dwmac->clk = NULL;
 331        }
 332
 333        return 0;
 334}
 335
 336static void *sti_dwmac_setup(struct platform_device *pdev)
 337{
 338        struct sti_dwmac *dwmac;
 339        int ret;
 340
 341        dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
 342        if (!dwmac)
 343                return ERR_PTR(-ENOMEM);
 344
 345        ret = sti_dwmac_parse_data(dwmac, pdev);
 346        if (ret) {
 347                dev_err(&pdev->dev, "Unable to parse OF data\n");
 348                return ERR_PTR(ret);
 349        }
 350
 351        return dwmac;
 352}
 353
 354const struct stmmac_of_data stih4xx_dwmac_data = {
 355        .fix_mac_speed = stih4xx_fix_retime_src,
 356        .setup = sti_dwmac_setup,
 357        .init = stix4xx_init,
 358        .exit = sti_dwmac_exit,
 359};
 360
 361const struct stmmac_of_data stid127_dwmac_data = {
 362        .fix_mac_speed = stid127_fix_retime_src,
 363        .setup = sti_dwmac_setup,
 364        .init = stid127_init,
 365        .exit = sti_dwmac_exit,
 366};
 367