1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * dwmac-ingenic.c - Ingenic SoCs DWMAC specific glue layer 4 * 5 * Copyright (c) 2021 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com> 6 */ 7 8 #include <linux/bitfield.h> 9 #include <linux/clk.h> 10 #include <linux/kernel.h> 11 #include <linux/mfd/syscon.h> 12 #include <linux/module.h> 13 #include <linux/of.h> 14 #include <linux/of_net.h> 15 #include <linux/phy.h> 16 #include <linux/platform_device.h> 17 #include <linux/regmap.h> 18 #include <linux/slab.h> 19 #include <linux/stmmac.h> 20 21 #include "stmmac_platform.h" 22 23 #define MACPHYC_TXCLK_SEL_MASK GENMASK(31, 31) 24 #define MACPHYC_TXCLK_SEL_OUTPUT 0x1 25 #define MACPHYC_TXCLK_SEL_INPUT 0x0 26 #define MACPHYC_MODE_SEL_MASK GENMASK(31, 31) 27 #define MACPHYC_MODE_SEL_RMII 0x0 28 #define MACPHYC_TX_SEL_MASK GENMASK(19, 19) 29 #define MACPHYC_TX_SEL_ORIGIN 0x0 30 #define MACPHYC_TX_SEL_DELAY 0x1 31 #define MACPHYC_TX_DELAY_MASK GENMASK(18, 12) 32 #define MACPHYC_RX_SEL_MASK GENMASK(11, 11) 33 #define MACPHYC_RX_SEL_ORIGIN 0x0 34 #define MACPHYC_RX_SEL_DELAY 0x1 35 #define MACPHYC_RX_DELAY_MASK GENMASK(10, 4) 36 #define MACPHYC_SOFT_RST_MASK GENMASK(3, 3) 37 #define MACPHYC_PHY_INFT_MASK GENMASK(2, 0) 38 #define MACPHYC_PHY_INFT_RMII 0x4 39 #define MACPHYC_PHY_INFT_RGMII 0x1 40 #define MACPHYC_PHY_INFT_GMII 0x0 41 #define MACPHYC_PHY_INFT_MII 0x0 42 43 #define MACPHYC_TX_DELAY_PS_MAX 2496 44 #define MACPHYC_TX_DELAY_PS_MIN 20 45 46 #define MACPHYC_RX_DELAY_PS_MAX 2496 47 #define MACPHYC_RX_DELAY_PS_MIN 20 48 49 enum ingenic_mac_version { 50 ID_JZ4775, 51 ID_X1000, 52 ID_X1600, 53 ID_X1830, 54 ID_X2000, 55 }; 56 57 struct ingenic_mac { 58 const struct ingenic_soc_info *soc_info; 59 struct device *dev; 60 struct regmap *regmap; 61 62 int rx_delay; 63 int tx_delay; 64 }; 65 66 struct ingenic_soc_info { 67 enum ingenic_mac_version version; 68 u32 mask; 69 70 int (*set_mode)(struct plat_stmmacenet_data *plat_dat); 71 }; 72 73 static int ingenic_mac_init(struct plat_stmmacenet_data *plat_dat) 74 { 75 struct ingenic_mac *mac = plat_dat->bsp_priv; 76 int ret; 77 78 if (mac->soc_info->set_mode) { 79 ret = mac->soc_info->set_mode(plat_dat); 80 if (ret) 81 return ret; 82 } 83 84 return 0; 85 } 86 87 static int jz4775_mac_set_mode(struct plat_stmmacenet_data *plat_dat) 88 { 89 struct ingenic_mac *mac = plat_dat->bsp_priv; 90 unsigned int val; 91 92 switch (plat_dat->mac_interface) { 93 case PHY_INTERFACE_MODE_MII: 94 val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) | 95 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_MII); 96 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_MII\n"); 97 break; 98 99 case PHY_INTERFACE_MODE_GMII: 100 val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) | 101 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_GMII); 102 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_GMII\n"); 103 break; 104 105 case PHY_INTERFACE_MODE_RMII: 106 val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) | 107 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); 108 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); 109 break; 110 111 case PHY_INTERFACE_MODE_RGMII: 112 case PHY_INTERFACE_MODE_RGMII_ID: 113 case PHY_INTERFACE_MODE_RGMII_TXID: 114 case PHY_INTERFACE_MODE_RGMII_RXID: 115 val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) | 116 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII); 117 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n"); 118 break; 119 120 default: 121 dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); 122 return -EINVAL; 123 } 124 125 /* Update MAC PHY control register */ 126 return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val); 127 } 128 129 static int x1000_mac_set_mode(struct plat_stmmacenet_data *plat_dat) 130 { 131 struct ingenic_mac *mac = plat_dat->bsp_priv; 132 133 switch (plat_dat->mac_interface) { 134 case PHY_INTERFACE_MODE_RMII: 135 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); 136 break; 137 138 default: 139 dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); 140 return -EINVAL; 141 } 142 143 /* Update MAC PHY control register */ 144 return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, 0); 145 } 146 147 static int x1600_mac_set_mode(struct plat_stmmacenet_data *plat_dat) 148 { 149 struct ingenic_mac *mac = plat_dat->bsp_priv; 150 unsigned int val; 151 152 switch (plat_dat->mac_interface) { 153 case PHY_INTERFACE_MODE_RMII: 154 val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); 155 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); 156 break; 157 158 default: 159 dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); 160 return -EINVAL; 161 } 162 163 /* Update MAC PHY control register */ 164 return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val); 165 } 166 167 static int x1830_mac_set_mode(struct plat_stmmacenet_data *plat_dat) 168 { 169 struct ingenic_mac *mac = plat_dat->bsp_priv; 170 unsigned int val; 171 172 switch (plat_dat->mac_interface) { 173 case PHY_INTERFACE_MODE_RMII: 174 val = FIELD_PREP(MACPHYC_MODE_SEL_MASK, MACPHYC_MODE_SEL_RMII) | 175 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); 176 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); 177 break; 178 179 default: 180 dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); 181 return -EINVAL; 182 } 183 184 /* Update MAC PHY control register */ 185 return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val); 186 } 187 188 static int x2000_mac_set_mode(struct plat_stmmacenet_data *plat_dat) 189 { 190 struct ingenic_mac *mac = plat_dat->bsp_priv; 191 unsigned int val; 192 193 switch (plat_dat->mac_interface) { 194 case PHY_INTERFACE_MODE_RMII: 195 val = FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN) | 196 FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN) | 197 FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); 198 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); 199 break; 200 201 case PHY_INTERFACE_MODE_RGMII: 202 case PHY_INTERFACE_MODE_RGMII_ID: 203 case PHY_INTERFACE_MODE_RGMII_TXID: 204 case PHY_INTERFACE_MODE_RGMII_RXID: 205 val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII); 206 207 if (mac->tx_delay == 0) 208 val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN); 209 else 210 val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_DELAY) | 211 FIELD_PREP(MACPHYC_TX_DELAY_MASK, (mac->tx_delay + 9750) / 19500 - 1); 212 213 if (mac->rx_delay == 0) 214 val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN); 215 else 216 val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_DELAY) | 217 FIELD_PREP(MACPHYC_RX_DELAY_MASK, (mac->rx_delay + 9750) / 19500 - 1); 218 219 dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n"); 220 break; 221 222 default: 223 dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); 224 return -EINVAL; 225 } 226 227 /* Update MAC PHY control register */ 228 return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val); 229 } 230 231 static int ingenic_mac_probe(struct platform_device *pdev) 232 { 233 struct plat_stmmacenet_data *plat_dat; 234 struct stmmac_resources stmmac_res; 235 struct ingenic_mac *mac; 236 const struct ingenic_soc_info *data; 237 u32 tx_delay_ps, rx_delay_ps; 238 int ret; 239 240 ret = stmmac_get_platform_resources(pdev, &stmmac_res); 241 if (ret) 242 return ret; 243 244 plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); 245 if (IS_ERR(plat_dat)) 246 return PTR_ERR(plat_dat); 247 248 mac = devm_kzalloc(&pdev->dev, sizeof(*mac), GFP_KERNEL); 249 if (!mac) { 250 ret = -ENOMEM; 251 goto err_remove_config_dt; 252 } 253 254 data = of_device_get_match_data(&pdev->dev); 255 if (!data) { 256 dev_err(&pdev->dev, "No of match data provided\n"); 257 ret = -EINVAL; 258 goto err_remove_config_dt; 259 } 260 261 /* Get MAC PHY control register */ 262 mac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "mode-reg"); 263 if (IS_ERR(mac->regmap)) { 264 dev_err(&pdev->dev, "%s: Failed to get syscon regmap\n", __func__); 265 ret = PTR_ERR(mac->regmap); 266 goto err_remove_config_dt; 267 } 268 269 if (!of_property_read_u32(pdev->dev.of_node, "tx-clk-delay-ps", &tx_delay_ps)) { 270 if (tx_delay_ps >= MACPHYC_TX_DELAY_PS_MIN && 271 tx_delay_ps <= MACPHYC_TX_DELAY_PS_MAX) { 272 mac->tx_delay = tx_delay_ps * 1000; 273 } else { 274 dev_err(&pdev->dev, "Invalid TX clock delay: %dps\n", tx_delay_ps); 275 ret = -EINVAL; 276 goto err_remove_config_dt; 277 } 278 } 279 280 if (!of_property_read_u32(pdev->dev.of_node, "rx-clk-delay-ps", &rx_delay_ps)) { 281 if (rx_delay_ps >= MACPHYC_RX_DELAY_PS_MIN && 282 rx_delay_ps <= MACPHYC_RX_DELAY_PS_MAX) { 283 mac->rx_delay = rx_delay_ps * 1000; 284 } else { 285 dev_err(&pdev->dev, "Invalid RX clock delay: %dps\n", rx_delay_ps); 286 ret = -EINVAL; 287 goto err_remove_config_dt; 288 } 289 } 290 291 mac->soc_info = data; 292 mac->dev = &pdev->dev; 293 294 plat_dat->bsp_priv = mac; 295 296 ret = ingenic_mac_init(plat_dat); 297 if (ret) 298 goto err_remove_config_dt; 299 300 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 301 if (ret) 302 goto err_remove_config_dt; 303 304 return 0; 305 306 err_remove_config_dt: 307 stmmac_remove_config_dt(pdev, plat_dat); 308 309 return ret; 310 } 311 312 #ifdef CONFIG_PM_SLEEP 313 static int ingenic_mac_suspend(struct device *dev) 314 { 315 int ret; 316 317 ret = stmmac_suspend(dev); 318 319 return ret; 320 } 321 322 static int ingenic_mac_resume(struct device *dev) 323 { 324 struct net_device *ndev = dev_get_drvdata(dev); 325 struct stmmac_priv *priv = netdev_priv(ndev); 326 int ret; 327 328 ret = ingenic_mac_init(priv->plat); 329 if (ret) 330 return ret; 331 332 ret = stmmac_resume(dev); 333 334 return ret; 335 } 336 #endif /* CONFIG_PM_SLEEP */ 337 338 static SIMPLE_DEV_PM_OPS(ingenic_mac_pm_ops, ingenic_mac_suspend, ingenic_mac_resume); 339 340 static struct ingenic_soc_info jz4775_soc_info = { 341 .version = ID_JZ4775, 342 .mask = MACPHYC_TXCLK_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, 343 344 .set_mode = jz4775_mac_set_mode, 345 }; 346 347 static struct ingenic_soc_info x1000_soc_info = { 348 .version = ID_X1000, 349 .mask = MACPHYC_SOFT_RST_MASK, 350 351 .set_mode = x1000_mac_set_mode, 352 }; 353 354 static struct ingenic_soc_info x1600_soc_info = { 355 .version = ID_X1600, 356 .mask = MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, 357 358 .set_mode = x1600_mac_set_mode, 359 }; 360 361 static struct ingenic_soc_info x1830_soc_info = { 362 .version = ID_X1830, 363 .mask = MACPHYC_MODE_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, 364 365 .set_mode = x1830_mac_set_mode, 366 }; 367 368 static struct ingenic_soc_info x2000_soc_info = { 369 .version = ID_X2000, 370 .mask = MACPHYC_TX_SEL_MASK | MACPHYC_TX_DELAY_MASK | MACPHYC_RX_SEL_MASK | 371 MACPHYC_RX_DELAY_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, 372 373 .set_mode = x2000_mac_set_mode, 374 }; 375 376 static const struct of_device_id ingenic_mac_of_matches[] = { 377 { .compatible = "ingenic,jz4775-mac", .data = &jz4775_soc_info }, 378 { .compatible = "ingenic,x1000-mac", .data = &x1000_soc_info }, 379 { .compatible = "ingenic,x1600-mac", .data = &x1600_soc_info }, 380 { .compatible = "ingenic,x1830-mac", .data = &x1830_soc_info }, 381 { .compatible = "ingenic,x2000-mac", .data = &x2000_soc_info }, 382 { } 383 }; 384 MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches); 385 386 static struct platform_driver ingenic_mac_driver = { 387 .probe = ingenic_mac_probe, 388 .remove_new = stmmac_pltfr_remove, 389 .driver = { 390 .name = "ingenic-mac", 391 .pm = pm_ptr(&ingenic_mac_pm_ops), 392 .of_match_table = ingenic_mac_of_matches, 393 }, 394 }; 395 module_platform_driver(ingenic_mac_driver); 396 397 MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>"); 398 MODULE_DESCRIPTION("Ingenic SoCs DWMAC specific glue layer"); 399 MODULE_LICENSE("GPL v2"); 400