0001
0002
0003
0004
0005
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
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
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
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
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
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
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
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");