Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * dwmac-ingenic.c - Ingenic SoCs DWMAC specific glue layer
0004  *
0005  * Copyright (c) 2021 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
0006  */
0007 
0008 #include <linux/bitfield.h>
0009 #include <linux/clk.h>
0010 #include <linux/kernel.h>
0011 #include <linux/mfd/syscon.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/of_device.h>
0015 #include <linux/of_net.h>
0016 #include <linux/phy.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/regmap.h>
0019 #include <linux/slab.h>
0020 #include <linux/stmmac.h>
0021 
0022 #include "stmmac_platform.h"
0023 
0024 #define MACPHYC_TXCLK_SEL_MASK      GENMASK(31, 31)
0025 #define MACPHYC_TXCLK_SEL_OUTPUT    0x1
0026 #define MACPHYC_TXCLK_SEL_INPUT     0x0
0027 #define MACPHYC_MODE_SEL_MASK       GENMASK(31, 31)
0028 #define MACPHYC_MODE_SEL_RMII       0x0
0029 #define MACPHYC_TX_SEL_MASK         GENMASK(19, 19)
0030 #define MACPHYC_TX_SEL_ORIGIN       0x0
0031 #define MACPHYC_TX_SEL_DELAY        0x1
0032 #define MACPHYC_TX_DELAY_MASK       GENMASK(18, 12)
0033 #define MACPHYC_RX_SEL_MASK         GENMASK(11, 11)
0034 #define MACPHYC_RX_SEL_ORIGIN       0x0
0035 #define MACPHYC_RX_SEL_DELAY        0x1
0036 #define MACPHYC_RX_DELAY_MASK       GENMASK(10, 4)
0037 #define MACPHYC_SOFT_RST_MASK       GENMASK(3, 3)
0038 #define MACPHYC_PHY_INFT_MASK       GENMASK(2, 0)
0039 #define MACPHYC_PHY_INFT_RMII       0x4
0040 #define MACPHYC_PHY_INFT_RGMII      0x1
0041 #define MACPHYC_PHY_INFT_GMII       0x0
0042 #define MACPHYC_PHY_INFT_MII        0x0
0043 
0044 #define MACPHYC_TX_DELAY_PS_MAX     2496
0045 #define MACPHYC_TX_DELAY_PS_MIN     20
0046 
0047 #define MACPHYC_RX_DELAY_PS_MAX     2496
0048 #define MACPHYC_RX_DELAY_PS_MIN     20
0049 
0050 enum ingenic_mac_version {
0051     ID_JZ4775,
0052     ID_X1000,
0053     ID_X1600,
0054     ID_X1830,
0055     ID_X2000,
0056 };
0057 
0058 struct ingenic_mac {
0059     const struct ingenic_soc_info *soc_info;
0060     struct device *dev;
0061     struct regmap *regmap;
0062 
0063     int rx_delay;
0064     int tx_delay;
0065 };
0066 
0067 struct ingenic_soc_info {
0068     enum ingenic_mac_version version;
0069     u32 mask;
0070 
0071     int (*set_mode)(struct plat_stmmacenet_data *plat_dat);
0072 };
0073 
0074 static int ingenic_mac_init(struct plat_stmmacenet_data *plat_dat)
0075 {
0076     struct ingenic_mac *mac = plat_dat->bsp_priv;
0077     int ret;
0078 
0079     if (mac->soc_info->set_mode) {
0080         ret = mac->soc_info->set_mode(plat_dat);
0081         if (ret)
0082             return ret;
0083     }
0084 
0085     return 0;
0086 }
0087 
0088 static int jz4775_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
0089 {
0090     struct ingenic_mac *mac = plat_dat->bsp_priv;
0091     unsigned int val;
0092 
0093     switch (plat_dat->interface) {
0094     case PHY_INTERFACE_MODE_MII:
0095         val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
0096               FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_MII);
0097         dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_MII\n");
0098         break;
0099 
0100     case PHY_INTERFACE_MODE_GMII:
0101         val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
0102               FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_GMII);
0103         dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_GMII\n");
0104         break;
0105 
0106     case PHY_INTERFACE_MODE_RMII:
0107         val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
0108               FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
0109         dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
0110         break;
0111 
0112     case PHY_INTERFACE_MODE_RGMII:
0113     case PHY_INTERFACE_MODE_RGMII_ID:
0114     case PHY_INTERFACE_MODE_RGMII_TXID:
0115     case PHY_INTERFACE_MODE_RGMII_RXID:
0116         val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
0117               FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII);
0118         dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n");
0119         break;
0120 
0121     default:
0122         dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface);
0123         return -EINVAL;
0124     }
0125 
0126     /* Update MAC PHY control register */
0127     return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
0128 }
0129 
0130 static int x1000_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
0131 {
0132     struct ingenic_mac *mac = plat_dat->bsp_priv;
0133 
0134     switch (plat_dat->interface) {
0135     case PHY_INTERFACE_MODE_RMII:
0136         dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
0137         break;
0138 
0139     default:
0140         dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface);
0141         return -EINVAL;
0142     }
0143 
0144     /* Update MAC PHY control register */
0145     return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, 0);
0146 }
0147 
0148 static int x1600_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
0149 {
0150     struct ingenic_mac *mac = plat_dat->bsp_priv;
0151     unsigned int val;
0152 
0153     switch (plat_dat->interface) {
0154     case PHY_INTERFACE_MODE_RMII:
0155         val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
0156         dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
0157         break;
0158 
0159     default:
0160         dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface);
0161         return -EINVAL;
0162     }
0163 
0164     /* Update MAC PHY control register */
0165     return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
0166 }
0167 
0168 static int x1830_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
0169 {
0170     struct ingenic_mac *mac = plat_dat->bsp_priv;
0171     unsigned int val;
0172 
0173     switch (plat_dat->interface) {
0174     case PHY_INTERFACE_MODE_RMII:
0175         val = FIELD_PREP(MACPHYC_MODE_SEL_MASK, MACPHYC_MODE_SEL_RMII) |
0176               FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
0177         dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
0178         break;
0179 
0180     default:
0181         dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface);
0182         return -EINVAL;
0183     }
0184 
0185     /* Update MAC PHY control register */
0186     return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
0187 }
0188 
0189 static int x2000_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
0190 {
0191     struct ingenic_mac *mac = plat_dat->bsp_priv;
0192     unsigned int val;
0193 
0194     switch (plat_dat->interface) {
0195     case PHY_INTERFACE_MODE_RMII:
0196         val = FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN) |
0197               FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN) |
0198               FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
0199         dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
0200         break;
0201 
0202     case PHY_INTERFACE_MODE_RGMII:
0203     case PHY_INTERFACE_MODE_RGMII_ID:
0204     case PHY_INTERFACE_MODE_RGMII_TXID:
0205     case PHY_INTERFACE_MODE_RGMII_RXID:
0206         val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII);
0207 
0208         if (mac->tx_delay == 0)
0209             val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN);
0210         else
0211             val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_DELAY) |
0212                    FIELD_PREP(MACPHYC_TX_DELAY_MASK, (mac->tx_delay + 9750) / 19500 - 1);
0213 
0214         if (mac->rx_delay == 0)
0215             val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN);
0216         else
0217             val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_DELAY) |
0218                    FIELD_PREP(MACPHYC_RX_DELAY_MASK, (mac->rx_delay + 9750) / 19500 - 1);
0219 
0220         dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n");
0221         break;
0222 
0223     default:
0224         dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface);
0225         return -EINVAL;
0226     }
0227 
0228     /* Update MAC PHY control register */
0229     return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
0230 }
0231 
0232 static int ingenic_mac_probe(struct platform_device *pdev)
0233 {
0234     struct plat_stmmacenet_data *plat_dat;
0235     struct stmmac_resources stmmac_res;
0236     struct ingenic_mac *mac;
0237     const struct ingenic_soc_info *data;
0238     u32 tx_delay_ps, rx_delay_ps;
0239     int ret;
0240 
0241     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
0242     if (ret)
0243         return ret;
0244 
0245     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
0246     if (IS_ERR(plat_dat))
0247         return PTR_ERR(plat_dat);
0248 
0249     mac = devm_kzalloc(&pdev->dev, sizeof(*mac), GFP_KERNEL);
0250     if (!mac) {
0251         ret = -ENOMEM;
0252         goto err_remove_config_dt;
0253     }
0254 
0255     data = of_device_get_match_data(&pdev->dev);
0256     if (!data) {
0257         dev_err(&pdev->dev, "No of match data provided\n");
0258         ret = -EINVAL;
0259         goto err_remove_config_dt;
0260     }
0261 
0262     /* Get MAC PHY control register */
0263     mac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "mode-reg");
0264     if (IS_ERR(mac->regmap)) {
0265         dev_err(&pdev->dev, "%s: Failed to get syscon regmap\n", __func__);
0266         ret = PTR_ERR(mac->regmap);
0267         goto err_remove_config_dt;
0268     }
0269 
0270     if (!of_property_read_u32(pdev->dev.of_node, "tx-clk-delay-ps", &tx_delay_ps)) {
0271         if (tx_delay_ps >= MACPHYC_TX_DELAY_PS_MIN &&
0272             tx_delay_ps <= MACPHYC_TX_DELAY_PS_MAX) {
0273             mac->tx_delay = tx_delay_ps * 1000;
0274         } else {
0275             dev_err(&pdev->dev, "Invalid TX clock delay: %dps\n", tx_delay_ps);
0276             ret = -EINVAL;
0277             goto err_remove_config_dt;
0278         }
0279     }
0280 
0281     if (!of_property_read_u32(pdev->dev.of_node, "rx-clk-delay-ps", &rx_delay_ps)) {
0282         if (rx_delay_ps >= MACPHYC_RX_DELAY_PS_MIN &&
0283             rx_delay_ps <= MACPHYC_RX_DELAY_PS_MAX) {
0284             mac->rx_delay = rx_delay_ps * 1000;
0285         } else {
0286             dev_err(&pdev->dev, "Invalid RX clock delay: %dps\n", rx_delay_ps);
0287             ret = -EINVAL;
0288             goto err_remove_config_dt;
0289         }
0290     }
0291 
0292     mac->soc_info = data;
0293     mac->dev = &pdev->dev;
0294 
0295     plat_dat->bsp_priv = mac;
0296 
0297     ret = ingenic_mac_init(plat_dat);
0298     if (ret)
0299         goto err_remove_config_dt;
0300 
0301     ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
0302     if (ret)
0303         goto err_remove_config_dt;
0304 
0305     return 0;
0306 
0307 err_remove_config_dt:
0308     stmmac_remove_config_dt(pdev, plat_dat);
0309 
0310     return ret;
0311 }
0312 
0313 #ifdef CONFIG_PM_SLEEP
0314 static int ingenic_mac_suspend(struct device *dev)
0315 {
0316     int ret;
0317 
0318     ret = stmmac_suspend(dev);
0319 
0320     return ret;
0321 }
0322 
0323 static int ingenic_mac_resume(struct device *dev)
0324 {
0325     struct net_device *ndev = dev_get_drvdata(dev);
0326     struct stmmac_priv *priv = netdev_priv(ndev);
0327     int ret;
0328 
0329     ret = ingenic_mac_init(priv->plat);
0330     if (ret)
0331         return ret;
0332 
0333     ret = stmmac_resume(dev);
0334 
0335     return ret;
0336 }
0337 #endif /* CONFIG_PM_SLEEP */
0338 
0339 static SIMPLE_DEV_PM_OPS(ingenic_mac_pm_ops, ingenic_mac_suspend, ingenic_mac_resume);
0340 
0341 static struct ingenic_soc_info jz4775_soc_info = {
0342     .version = ID_JZ4775,
0343     .mask = MACPHYC_TXCLK_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
0344 
0345     .set_mode = jz4775_mac_set_mode,
0346 };
0347 
0348 static struct ingenic_soc_info x1000_soc_info = {
0349     .version = ID_X1000,
0350     .mask = MACPHYC_SOFT_RST_MASK,
0351 
0352     .set_mode = x1000_mac_set_mode,
0353 };
0354 
0355 static struct ingenic_soc_info x1600_soc_info = {
0356     .version = ID_X1600,
0357     .mask = MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
0358 
0359     .set_mode = x1600_mac_set_mode,
0360 };
0361 
0362 static struct ingenic_soc_info x1830_soc_info = {
0363     .version = ID_X1830,
0364     .mask = MACPHYC_MODE_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
0365 
0366     .set_mode = x1830_mac_set_mode,
0367 };
0368 
0369 static struct ingenic_soc_info x2000_soc_info = {
0370     .version = ID_X2000,
0371     .mask = MACPHYC_TX_SEL_MASK | MACPHYC_TX_DELAY_MASK | MACPHYC_RX_SEL_MASK |
0372             MACPHYC_RX_DELAY_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
0373 
0374     .set_mode = x2000_mac_set_mode,
0375 };
0376 
0377 static const struct of_device_id ingenic_mac_of_matches[] = {
0378     { .compatible = "ingenic,jz4775-mac", .data = &jz4775_soc_info },
0379     { .compatible = "ingenic,x1000-mac", .data = &x1000_soc_info },
0380     { .compatible = "ingenic,x1600-mac", .data = &x1600_soc_info },
0381     { .compatible = "ingenic,x1830-mac", .data = &x1830_soc_info },
0382     { .compatible = "ingenic,x2000-mac", .data = &x2000_soc_info },
0383     { }
0384 };
0385 MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches);
0386 
0387 static struct platform_driver ingenic_mac_driver = {
0388     .probe      = ingenic_mac_probe,
0389     .remove     = stmmac_pltfr_remove,
0390     .driver     = {
0391         .name   = "ingenic-mac",
0392         .pm     = pm_ptr(&ingenic_mac_pm_ops),
0393         .of_match_table = ingenic_mac_of_matches,
0394     },
0395 };
0396 module_platform_driver(ingenic_mac_driver);
0397 
0398 MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>");
0399 MODULE_DESCRIPTION("Ingenic SoCs DWMAC specific glue layer");
0400 MODULE_LICENSE("GPL v2");