Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer
0004  *
0005  * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
0006  * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
0007  * Contributors: Giuseppe Cavallaro <peppe.cavallaro@st.com>
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/slab.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/stmmac.h>
0014 #include <linux/phy.h>
0015 #include <linux/mfd/syscon.h>
0016 #include <linux/module.h>
0017 #include <linux/regmap.h>
0018 #include <linux/clk.h>
0019 #include <linux/of.h>
0020 #include <linux/of_device.h>
0021 #include <linux/of_net.h>
0022 
0023 #include "stmmac_platform.h"
0024 
0025 #define DWMAC_125MHZ    125000000
0026 #define DWMAC_50MHZ 50000000
0027 #define DWMAC_25MHZ 25000000
0028 #define DWMAC_2_5MHZ    2500000
0029 
0030 #define IS_PHY_IF_MODE_RGMII(iface) (iface == PHY_INTERFACE_MODE_RGMII || \
0031             iface == PHY_INTERFACE_MODE_RGMII_ID || \
0032             iface == PHY_INTERFACE_MODE_RGMII_RXID || \
0033             iface == PHY_INTERFACE_MODE_RGMII_TXID)
0034 
0035 #define IS_PHY_IF_MODE_GBIT(iface)  (IS_PHY_IF_MODE_RGMII(iface) || \
0036                      iface == PHY_INTERFACE_MODE_GMII)
0037 
0038 /* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families)
0039  *
0040  * Below table summarizes the clock requirement and clock sources for
0041  * supported phy interface modes with link speeds.
0042  * ________________________________________________
0043  *|  PHY_MODE   | 1000 Mbit Link | 100 Mbit Link   |
0044  * ------------------------------------------------
0045  *| MII |   n/a  |  25Mhz      |
0046  *|     |        |  txclk      |
0047  * ------------------------------------------------
0048  *| GMII    |     125Mhz     |  25Mhz      |
0049  *|     |  clk-125/txclk |  txclk      |
0050  * ------------------------------------------------
0051  *| RGMII   |     125Mhz     |  25Mhz      |
0052  *|     |  clk-125/txclk |  clkgen     |
0053  *|     |    clkgen  |         |
0054  * ------------------------------------------------
0055  *| RMII    |   n/a  |  25Mhz      |
0056  *|     |        |clkgen/phyclk-in |
0057  * ------------------------------------------------
0058  *
0059  *    Register Configuration
0060  *-------------------------------
0061  * src   |BIT(8)| BIT(7)| BIT(6)|
0062  *-------------------------------
0063  * txclk |   0  |  n/a  |   1   |
0064  *-------------------------------
0065  * ck_125|   0  |  n/a  |   0   |
0066  *-------------------------------
0067  * phyclk|   1  |   0   |  n/a  |
0068  *-------------------------------
0069  * clkgen|   1  |   1   |  n/a  |
0070  *-------------------------------
0071  */
0072 
0073 #define STIH4XX_RETIME_SRC_MASK         GENMASK(8, 6)
0074 #define STIH4XX_ETH_SEL_TX_RETIME_CLK       BIT(8)
0075 #define STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK  BIT(7)
0076 #define STIH4XX_ETH_SEL_TXCLK_NOT_CLK125    BIT(6)
0077 
0078 /* STiD127 register definitions
0079  *-----------------------
0080  * src   |BIT(6)| BIT(7)|
0081  *-----------------------
0082  * MII   |  1   |   n/a |
0083  *-----------------------
0084  * RMII  |  n/a |   1   |
0085  * clkgen|  |   |
0086  *-----------------------
0087  * RMII  |  n/a |   0   |
0088  * phyclk|  |   |
0089  *-----------------------
0090  * RGMII |  1   |  n/a  |
0091  * clkgen|  |   |
0092  *-----------------------
0093  */
0094 
0095 #define STID127_RETIME_SRC_MASK         GENMASK(7, 6)
0096 #define STID127_ETH_SEL_INTERNAL_NOTEXT_PHYCLK  BIT(7)
0097 #define STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK   BIT(6)
0098 
0099 #define ENMII_MASK  GENMASK(5, 5)
0100 #define ENMII       BIT(5)
0101 #define EN_MASK     GENMASK(1, 1)
0102 #define EN      BIT(1)
0103 
0104 /*
0105  * 3 bits [4:2]
0106  *  000-GMII/MII
0107  *  001-RGMII
0108  *  010-SGMII
0109  *  100-RMII
0110  */
0111 #define MII_PHY_SEL_MASK    GENMASK(4, 2)
0112 #define ETH_PHY_SEL_RMII    BIT(4)
0113 #define ETH_PHY_SEL_SGMII   BIT(3)
0114 #define ETH_PHY_SEL_RGMII   BIT(2)
0115 #define ETH_PHY_SEL_GMII    0x0
0116 #define ETH_PHY_SEL_MII     0x0
0117 
0118 struct sti_dwmac {
0119     phy_interface_t interface;  /* MII interface */
0120     bool ext_phyclk;    /* Clock from external PHY */
0121     u32 tx_retime_src;  /* TXCLK Retiming*/
0122     struct clk *clk;    /* PHY clock */
0123     u32 ctrl_reg;       /* GMAC glue-logic control register */
0124     int clk_sel_reg;    /* GMAC ext clk selection register */
0125     struct regmap *regmap;
0126     bool gmac_en;
0127     u32 speed;
0128     void (*fix_retime_src)(void *priv, unsigned int speed);
0129 };
0130 
0131 struct sti_dwmac_of_data {
0132     void (*fix_retime_src)(void *priv, unsigned int speed);
0133 };
0134 
0135 static u32 phy_intf_sels[] = {
0136     [PHY_INTERFACE_MODE_MII] = ETH_PHY_SEL_MII,
0137     [PHY_INTERFACE_MODE_GMII] = ETH_PHY_SEL_GMII,
0138     [PHY_INTERFACE_MODE_RGMII] = ETH_PHY_SEL_RGMII,
0139     [PHY_INTERFACE_MODE_RGMII_ID] = ETH_PHY_SEL_RGMII,
0140     [PHY_INTERFACE_MODE_SGMII] = ETH_PHY_SEL_SGMII,
0141     [PHY_INTERFACE_MODE_RMII] = ETH_PHY_SEL_RMII,
0142 };
0143 
0144 enum {
0145     TX_RETIME_SRC_NA = 0,
0146     TX_RETIME_SRC_TXCLK = 1,
0147     TX_RETIME_SRC_CLK_125,
0148     TX_RETIME_SRC_PHYCLK,
0149     TX_RETIME_SRC_CLKGEN,
0150 };
0151 
0152 static u32 stih4xx_tx_retime_val[] = {
0153     [TX_RETIME_SRC_TXCLK] = STIH4XX_ETH_SEL_TXCLK_NOT_CLK125,
0154     [TX_RETIME_SRC_CLK_125] = 0x0,
0155     [TX_RETIME_SRC_PHYCLK] = STIH4XX_ETH_SEL_TX_RETIME_CLK,
0156     [TX_RETIME_SRC_CLKGEN] = STIH4XX_ETH_SEL_TX_RETIME_CLK
0157                  | STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
0158 };
0159 
0160 static void stih4xx_fix_retime_src(void *priv, u32 spd)
0161 {
0162     struct sti_dwmac *dwmac = priv;
0163     u32 src = dwmac->tx_retime_src;
0164     u32 reg = dwmac->ctrl_reg;
0165     u32 freq = 0;
0166 
0167     if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
0168         src = TX_RETIME_SRC_TXCLK;
0169     } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
0170         if (dwmac->ext_phyclk) {
0171             src = TX_RETIME_SRC_PHYCLK;
0172         } else {
0173             src = TX_RETIME_SRC_CLKGEN;
0174             freq = DWMAC_50MHZ;
0175         }
0176     } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
0177         /* On GiGa clk source can be either ext or from clkgen */
0178         if (spd == SPEED_1000) {
0179             freq = DWMAC_125MHZ;
0180         } else {
0181             /* Switch to clkgen for these speeds */
0182             src = TX_RETIME_SRC_CLKGEN;
0183             if (spd == SPEED_100)
0184                 freq = DWMAC_25MHZ;
0185             else if (spd == SPEED_10)
0186                 freq = DWMAC_2_5MHZ;
0187         }
0188     }
0189 
0190     if (src == TX_RETIME_SRC_CLKGEN && freq)
0191         clk_set_rate(dwmac->clk, freq);
0192 
0193     regmap_update_bits(dwmac->regmap, reg, STIH4XX_RETIME_SRC_MASK,
0194                stih4xx_tx_retime_val[src]);
0195 }
0196 
0197 static void stid127_fix_retime_src(void *priv, u32 spd)
0198 {
0199     struct sti_dwmac *dwmac = priv;
0200     u32 reg = dwmac->ctrl_reg;
0201     u32 freq = 0;
0202     u32 val = 0;
0203 
0204     if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
0205         val = STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK;
0206     } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
0207         if (!dwmac->ext_phyclk) {
0208             val = STID127_ETH_SEL_INTERNAL_NOTEXT_PHYCLK;
0209             freq = DWMAC_50MHZ;
0210         }
0211     } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
0212         val = STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK;
0213         if (spd == SPEED_1000)
0214             freq = DWMAC_125MHZ;
0215         else if (spd == SPEED_100)
0216             freq = DWMAC_25MHZ;
0217         else if (spd == SPEED_10)
0218             freq = DWMAC_2_5MHZ;
0219     }
0220 
0221     if (freq)
0222         clk_set_rate(dwmac->clk, freq);
0223 
0224     regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val);
0225 }
0226 
0227 static int sti_dwmac_set_mode(struct sti_dwmac *dwmac)
0228 {
0229     struct regmap *regmap = dwmac->regmap;
0230     int iface = dwmac->interface;
0231     u32 reg = dwmac->ctrl_reg;
0232     u32 val;
0233 
0234     if (dwmac->gmac_en)
0235         regmap_update_bits(regmap, reg, EN_MASK, EN);
0236 
0237     regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
0238 
0239     val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
0240     regmap_update_bits(regmap, reg, ENMII_MASK, val);
0241 
0242     dwmac->fix_retime_src(dwmac, dwmac->speed);
0243 
0244     return 0;
0245 }
0246 
0247 static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
0248                 struct platform_device *pdev)
0249 {
0250     struct resource *res;
0251     struct device *dev = &pdev->dev;
0252     struct device_node *np = dev->of_node;
0253     struct regmap *regmap;
0254     int err;
0255 
0256     /* clk selection from extra syscfg register */
0257     dwmac->clk_sel_reg = -ENXIO;
0258     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-clkconf");
0259     if (res)
0260         dwmac->clk_sel_reg = res->start;
0261 
0262     regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
0263     if (IS_ERR(regmap))
0264         return PTR_ERR(regmap);
0265 
0266     err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->ctrl_reg);
0267     if (err) {
0268         dev_err(dev, "Can't get sysconfig ctrl offset (%d)\n", err);
0269         return err;
0270     }
0271 
0272     err = of_get_phy_mode(np, &dwmac->interface);
0273     if (err && err != -ENODEV) {
0274         dev_err(dev, "Can't get phy-mode\n");
0275         return err;
0276     }
0277 
0278     dwmac->regmap = regmap;
0279     dwmac->gmac_en = of_property_read_bool(np, "st,gmac_en");
0280     dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
0281     dwmac->tx_retime_src = TX_RETIME_SRC_NA;
0282     dwmac->speed = SPEED_100;
0283 
0284     if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
0285         const char *rs;
0286 
0287         dwmac->tx_retime_src = TX_RETIME_SRC_CLKGEN;
0288 
0289         err = of_property_read_string(np, "st,tx-retime-src", &rs);
0290         if (err < 0) {
0291             dev_warn(dev, "Use internal clock source\n");
0292         } else {
0293             if (!strcasecmp(rs, "clk_125"))
0294                 dwmac->tx_retime_src = TX_RETIME_SRC_CLK_125;
0295             else if (!strcasecmp(rs, "txclk"))
0296                 dwmac->tx_retime_src = TX_RETIME_SRC_TXCLK;
0297         }
0298         dwmac->speed = SPEED_1000;
0299     }
0300 
0301     dwmac->clk = devm_clk_get(dev, "sti-ethclk");
0302     if (IS_ERR(dwmac->clk)) {
0303         dev_warn(dev, "No phy clock provided...\n");
0304         dwmac->clk = NULL;
0305     }
0306 
0307     return 0;
0308 }
0309 
0310 static int sti_dwmac_probe(struct platform_device *pdev)
0311 {
0312     struct plat_stmmacenet_data *plat_dat;
0313     const struct sti_dwmac_of_data *data;
0314     struct stmmac_resources stmmac_res;
0315     struct sti_dwmac *dwmac;
0316     int ret;
0317 
0318     data = of_device_get_match_data(&pdev->dev);
0319     if (!data) {
0320         dev_err(&pdev->dev, "No OF match data provided\n");
0321         return -EINVAL;
0322     }
0323 
0324     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
0325     if (ret)
0326         return ret;
0327 
0328     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
0329     if (IS_ERR(plat_dat))
0330         return PTR_ERR(plat_dat);
0331 
0332     dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
0333     if (!dwmac) {
0334         ret = -ENOMEM;
0335         goto err_remove_config_dt;
0336     }
0337 
0338     ret = sti_dwmac_parse_data(dwmac, pdev);
0339     if (ret) {
0340         dev_err(&pdev->dev, "Unable to parse OF data\n");
0341         goto err_remove_config_dt;
0342     }
0343 
0344     dwmac->fix_retime_src = data->fix_retime_src;
0345 
0346     plat_dat->bsp_priv = dwmac;
0347     plat_dat->fix_mac_speed = data->fix_retime_src;
0348 
0349     ret = clk_prepare_enable(dwmac->clk);
0350     if (ret)
0351         goto err_remove_config_dt;
0352 
0353     ret = sti_dwmac_set_mode(dwmac);
0354     if (ret)
0355         goto disable_clk;
0356 
0357     ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
0358     if (ret)
0359         goto disable_clk;
0360 
0361     return 0;
0362 
0363 disable_clk:
0364     clk_disable_unprepare(dwmac->clk);
0365 err_remove_config_dt:
0366     stmmac_remove_config_dt(pdev, plat_dat);
0367 
0368     return ret;
0369 }
0370 
0371 static int sti_dwmac_remove(struct platform_device *pdev)
0372 {
0373     struct sti_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
0374     int ret = stmmac_dvr_remove(&pdev->dev);
0375 
0376     clk_disable_unprepare(dwmac->clk);
0377 
0378     return ret;
0379 }
0380 
0381 #ifdef CONFIG_PM_SLEEP
0382 static int sti_dwmac_suspend(struct device *dev)
0383 {
0384     struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev);
0385     int ret = stmmac_suspend(dev);
0386 
0387     clk_disable_unprepare(dwmac->clk);
0388 
0389     return ret;
0390 }
0391 
0392 static int sti_dwmac_resume(struct device *dev)
0393 {
0394     struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev);
0395 
0396     clk_prepare_enable(dwmac->clk);
0397     sti_dwmac_set_mode(dwmac);
0398 
0399     return stmmac_resume(dev);
0400 }
0401 #endif /* CONFIG_PM_SLEEP */
0402 
0403 static SIMPLE_DEV_PM_OPS(sti_dwmac_pm_ops, sti_dwmac_suspend,
0404                        sti_dwmac_resume);
0405 
0406 static const struct sti_dwmac_of_data stih4xx_dwmac_data = {
0407     .fix_retime_src = stih4xx_fix_retime_src,
0408 };
0409 
0410 static const struct sti_dwmac_of_data stid127_dwmac_data = {
0411     .fix_retime_src = stid127_fix_retime_src,
0412 };
0413 
0414 static const struct of_device_id sti_dwmac_match[] = {
0415     { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data},
0416     { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data},
0417     { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
0418     { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
0419     { }
0420 };
0421 MODULE_DEVICE_TABLE(of, sti_dwmac_match);
0422 
0423 static struct platform_driver sti_dwmac_driver = {
0424     .probe  = sti_dwmac_probe,
0425     .remove = sti_dwmac_remove,
0426     .driver = {
0427         .name           = "sti-dwmac",
0428         .pm     = &sti_dwmac_pm_ops,
0429         .of_match_table = sti_dwmac_match,
0430     },
0431 };
0432 module_platform_driver(sti_dwmac_driver);
0433 
0434 MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@st.com>");
0435 MODULE_DESCRIPTION("STMicroelectronics DWMAC Specific Glue layer");
0436 MODULE_LICENSE("GPL");