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 = devm_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 return -ENOMEM; 251 252 data = of_device_get_match_data(&pdev->dev); 253 if (!data) { 254 dev_err(&pdev->dev, "No of match data provided\n"); 255 return -EINVAL; 256 } 257 258 /* Get MAC PHY control register */ 259 mac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "mode-reg"); 260 if (IS_ERR(mac->regmap)) { 261 dev_err(&pdev->dev, "%s: Failed to get syscon regmap\n", __func__); 262 return PTR_ERR(mac->regmap); 263 } 264 265 if (!of_property_read_u32(pdev->dev.of_node, "tx-clk-delay-ps", &tx_delay_ps)) { 266 if (tx_delay_ps >= MACPHYC_TX_DELAY_PS_MIN && 267 tx_delay_ps <= MACPHYC_TX_DELAY_PS_MAX) { 268 mac->tx_delay = tx_delay_ps * 1000; 269 } else { 270 dev_err(&pdev->dev, "Invalid TX clock delay: %dps\n", tx_delay_ps); 271 return -EINVAL; 272 } 273 } 274 275 if (!of_property_read_u32(pdev->dev.of_node, "rx-clk-delay-ps", &rx_delay_ps)) { 276 if (rx_delay_ps >= MACPHYC_RX_DELAY_PS_MIN && 277 rx_delay_ps <= MACPHYC_RX_DELAY_PS_MAX) { 278 mac->rx_delay = rx_delay_ps * 1000; 279 } else { 280 dev_err(&pdev->dev, "Invalid RX clock delay: %dps\n", rx_delay_ps); 281 return -EINVAL; 282 } 283 } 284 285 mac->soc_info = data; 286 mac->dev = &pdev->dev; 287 288 plat_dat->bsp_priv = mac; 289 290 ret = ingenic_mac_init(plat_dat); 291 if (ret) 292 return ret; 293 294 return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 295 } 296 297 #ifdef CONFIG_PM_SLEEP 298 static int ingenic_mac_suspend(struct device *dev) 299 { 300 int ret; 301 302 ret = stmmac_suspend(dev); 303 304 return ret; 305 } 306 307 static int ingenic_mac_resume(struct device *dev) 308 { 309 struct net_device *ndev = dev_get_drvdata(dev); 310 struct stmmac_priv *priv = netdev_priv(ndev); 311 int ret; 312 313 ret = ingenic_mac_init(priv->plat); 314 if (ret) 315 return ret; 316 317 ret = stmmac_resume(dev); 318 319 return ret; 320 } 321 #endif /* CONFIG_PM_SLEEP */ 322 323 static SIMPLE_DEV_PM_OPS(ingenic_mac_pm_ops, ingenic_mac_suspend, ingenic_mac_resume); 324 325 static struct ingenic_soc_info jz4775_soc_info = { 326 .version = ID_JZ4775, 327 .mask = MACPHYC_TXCLK_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, 328 329 .set_mode = jz4775_mac_set_mode, 330 }; 331 332 static struct ingenic_soc_info x1000_soc_info = { 333 .version = ID_X1000, 334 .mask = MACPHYC_SOFT_RST_MASK, 335 336 .set_mode = x1000_mac_set_mode, 337 }; 338 339 static struct ingenic_soc_info x1600_soc_info = { 340 .version = ID_X1600, 341 .mask = MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, 342 343 .set_mode = x1600_mac_set_mode, 344 }; 345 346 static struct ingenic_soc_info x1830_soc_info = { 347 .version = ID_X1830, 348 .mask = MACPHYC_MODE_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, 349 350 .set_mode = x1830_mac_set_mode, 351 }; 352 353 static struct ingenic_soc_info x2000_soc_info = { 354 .version = ID_X2000, 355 .mask = MACPHYC_TX_SEL_MASK | MACPHYC_TX_DELAY_MASK | MACPHYC_RX_SEL_MASK | 356 MACPHYC_RX_DELAY_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, 357 358 .set_mode = x2000_mac_set_mode, 359 }; 360 361 static const struct of_device_id ingenic_mac_of_matches[] = { 362 { .compatible = "ingenic,jz4775-mac", .data = &jz4775_soc_info }, 363 { .compatible = "ingenic,x1000-mac", .data = &x1000_soc_info }, 364 { .compatible = "ingenic,x1600-mac", .data = &x1600_soc_info }, 365 { .compatible = "ingenic,x1830-mac", .data = &x1830_soc_info }, 366 { .compatible = "ingenic,x2000-mac", .data = &x2000_soc_info }, 367 { } 368 }; 369 MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches); 370 371 static struct platform_driver ingenic_mac_driver = { 372 .probe = ingenic_mac_probe, 373 .remove_new = stmmac_pltfr_remove, 374 .driver = { 375 .name = "ingenic-mac", 376 .pm = pm_ptr(&ingenic_mac_pm_ops), 377 .of_match_table = ingenic_mac_of_matches, 378 }, 379 }; 380 module_platform_driver(ingenic_mac_driver); 381 382 MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>"); 383 MODULE_DESCRIPTION("Ingenic SoCs DWMAC specific glue layer"); 384 MODULE_LICENSE("GPL v2"); 385