1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * dwmac-imx.c - DWMAC Specific Glue layer for NXP imx8 4 * 5 * Copyright 2020 NXP 6 * 7 */ 8 9 #include <linux/clk.h> 10 #include <linux/gpio/consumer.h> 11 #include <linux/kernel.h> 12 #include <linux/mfd/syscon.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/of_net.h> 16 #include <linux/phy.h> 17 #include <linux/platform_device.h> 18 #include <linux/pm_wakeirq.h> 19 #include <linux/regmap.h> 20 #include <linux/slab.h> 21 #include <linux/stmmac.h> 22 23 #include "stmmac_platform.h" 24 25 #define GPR_ENET_QOS_INTF_MODE_MASK GENMASK(21, 16) 26 #define GPR_ENET_QOS_INTF_SEL_MII (0x0 << 16) 27 #define GPR_ENET_QOS_INTF_SEL_RMII (0x4 << 16) 28 #define GPR_ENET_QOS_INTF_SEL_RGMII (0x1 << 16) 29 #define GPR_ENET_QOS_CLK_GEN_EN (0x1 << 19) 30 #define GPR_ENET_QOS_CLK_TX_CLK_SEL (0x1 << 20) 31 #define GPR_ENET_QOS_RGMII_EN (0x1 << 21) 32 33 #define MX93_GPR_ENET_QOS_INTF_MODE_MASK GENMASK(3, 0) 34 #define MX93_GPR_ENET_QOS_INTF_MASK GENMASK(3, 1) 35 #define MX93_GPR_ENET_QOS_INTF_SEL_MII (0x0 << 1) 36 #define MX93_GPR_ENET_QOS_INTF_SEL_RMII (0x4 << 1) 37 #define MX93_GPR_ENET_QOS_INTF_SEL_RGMII (0x1 << 1) 38 #define MX93_GPR_ENET_QOS_CLK_GEN_EN (0x1 << 0) 39 #define MX93_GPR_ENET_QOS_CLK_SEL_MASK BIT_MASK(0) 40 #define MX93_GPR_CLK_SEL_OFFSET (4) 41 42 #define DMA_BUS_MODE 0x00001000 43 #define DMA_BUS_MODE_SFT_RESET (0x1 << 0) 44 #define RMII_RESET_SPEED (0x3 << 14) 45 #define CTRL_SPEED_MASK GENMASK(15, 14) 46 47 struct imx_dwmac_ops { 48 u32 addr_width; 49 u32 flags; 50 bool mac_rgmii_txclk_auto_adj; 51 52 int (*fix_soc_reset)(struct stmmac_priv *priv, void __iomem *ioaddr); 53 int (*set_intf_mode)(struct plat_stmmacenet_data *plat_dat); 54 void (*fix_mac_speed)(void *priv, int speed, unsigned int mode); 55 }; 56 57 struct imx_priv_data { 58 struct device *dev; 59 struct clk *clk_tx; 60 struct clk *clk_mem; 61 struct regmap *intf_regmap; 62 u32 intf_reg_off; 63 bool rmii_refclk_ext; 64 void __iomem *base_addr; 65 66 const struct imx_dwmac_ops *ops; 67 struct plat_stmmacenet_data *plat_dat; 68 }; 69 70 static int imx8mp_set_intf_mode(struct plat_stmmacenet_data *plat_dat) 71 { 72 struct imx_priv_data *dwmac = plat_dat->bsp_priv; 73 int val; 74 75 switch (plat_dat->mac_interface) { 76 case PHY_INTERFACE_MODE_MII: 77 val = GPR_ENET_QOS_INTF_SEL_MII; 78 break; 79 case PHY_INTERFACE_MODE_RMII: 80 val = GPR_ENET_QOS_INTF_SEL_RMII; 81 val |= (dwmac->rmii_refclk_ext ? 0 : GPR_ENET_QOS_CLK_TX_CLK_SEL); 82 break; 83 case PHY_INTERFACE_MODE_RGMII: 84 case PHY_INTERFACE_MODE_RGMII_ID: 85 case PHY_INTERFACE_MODE_RGMII_RXID: 86 case PHY_INTERFACE_MODE_RGMII_TXID: 87 val = GPR_ENET_QOS_INTF_SEL_RGMII | 88 GPR_ENET_QOS_RGMII_EN; 89 break; 90 default: 91 pr_debug("imx dwmac doesn't support %d interface\n", 92 plat_dat->mac_interface); 93 return -EINVAL; 94 } 95 96 val |= GPR_ENET_QOS_CLK_GEN_EN; 97 return regmap_update_bits(dwmac->intf_regmap, dwmac->intf_reg_off, 98 GPR_ENET_QOS_INTF_MODE_MASK, val); 99 }; 100 101 static int 102 imx8dxl_set_intf_mode(struct plat_stmmacenet_data *plat_dat) 103 { 104 int ret = 0; 105 106 /* TBD: depends on imx8dxl scu interfaces to be upstreamed */ 107 return ret; 108 } 109 110 static int imx93_set_intf_mode(struct plat_stmmacenet_data *plat_dat) 111 { 112 struct imx_priv_data *dwmac = plat_dat->bsp_priv; 113 int val, ret; 114 115 switch (plat_dat->mac_interface) { 116 case PHY_INTERFACE_MODE_MII: 117 val = MX93_GPR_ENET_QOS_INTF_SEL_MII; 118 break; 119 case PHY_INTERFACE_MODE_RMII: 120 if (dwmac->rmii_refclk_ext) { 121 ret = regmap_clear_bits(dwmac->intf_regmap, 122 dwmac->intf_reg_off + 123 MX93_GPR_CLK_SEL_OFFSET, 124 MX93_GPR_ENET_QOS_CLK_SEL_MASK); 125 if (ret) 126 return ret; 127 } 128 val = MX93_GPR_ENET_QOS_INTF_SEL_RMII; 129 break; 130 case PHY_INTERFACE_MODE_RGMII: 131 case PHY_INTERFACE_MODE_RGMII_ID: 132 case PHY_INTERFACE_MODE_RGMII_RXID: 133 case PHY_INTERFACE_MODE_RGMII_TXID: 134 val = MX93_GPR_ENET_QOS_INTF_SEL_RGMII; 135 break; 136 default: 137 dev_dbg(dwmac->dev, "imx dwmac doesn't support %d interface\n", 138 plat_dat->mac_interface); 139 return -EINVAL; 140 } 141 142 val |= MX93_GPR_ENET_QOS_CLK_GEN_EN; 143 return regmap_update_bits(dwmac->intf_regmap, dwmac->intf_reg_off, 144 MX93_GPR_ENET_QOS_INTF_MODE_MASK, val); 145 }; 146 147 static int imx_dwmac_clks_config(void *priv, bool enabled) 148 { 149 struct imx_priv_data *dwmac = priv; 150 int ret = 0; 151 152 if (enabled) { 153 ret = clk_prepare_enable(dwmac->clk_mem); 154 if (ret) { 155 dev_err(dwmac->dev, "mem clock enable failed\n"); 156 return ret; 157 } 158 159 ret = clk_prepare_enable(dwmac->clk_tx); 160 if (ret) { 161 dev_err(dwmac->dev, "tx clock enable failed\n"); 162 clk_disable_unprepare(dwmac->clk_mem); 163 return ret; 164 } 165 } else { 166 clk_disable_unprepare(dwmac->clk_tx); 167 clk_disable_unprepare(dwmac->clk_mem); 168 } 169 170 return ret; 171 } 172 173 static int imx_dwmac_init(struct platform_device *pdev, void *priv) 174 { 175 struct plat_stmmacenet_data *plat_dat; 176 struct imx_priv_data *dwmac = priv; 177 int ret; 178 179 plat_dat = dwmac->plat_dat; 180 181 if (dwmac->ops->set_intf_mode) { 182 ret = dwmac->ops->set_intf_mode(plat_dat); 183 if (ret) 184 return ret; 185 } 186 187 return 0; 188 } 189 190 static void imx_dwmac_exit(struct platform_device *pdev, void *priv) 191 { 192 /* nothing to do now */ 193 } 194 195 static int imx_dwmac_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i, 196 phy_interface_t interface, int speed) 197 { 198 struct imx_priv_data *dwmac = bsp_priv; 199 200 interface = dwmac->plat_dat->mac_interface; 201 if (interface == PHY_INTERFACE_MODE_RMII || 202 interface == PHY_INTERFACE_MODE_MII) 203 return 0; 204 205 return stmmac_set_clk_tx_rate(bsp_priv, clk_tx_i, interface, speed); 206 } 207 208 static void imx_dwmac_fix_speed(void *priv, int speed, unsigned int mode) 209 { 210 struct plat_stmmacenet_data *plat_dat; 211 struct imx_priv_data *dwmac = priv; 212 long rate; 213 int err; 214 215 plat_dat = dwmac->plat_dat; 216 217 if (dwmac->ops->mac_rgmii_txclk_auto_adj || 218 (plat_dat->mac_interface == PHY_INTERFACE_MODE_RMII) || 219 (plat_dat->mac_interface == PHY_INTERFACE_MODE_MII)) 220 return; 221 222 rate = rgmii_clock(speed); 223 if (rate < 0) { 224 dev_err(dwmac->dev, "invalid speed %d\n", speed); 225 return; 226 } 227 228 err = clk_set_rate(dwmac->clk_tx, rate); 229 if (err < 0) 230 dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate); 231 } 232 233 static void imx93_dwmac_fix_speed(void *priv, int speed, unsigned int mode) 234 { 235 struct imx_priv_data *dwmac = priv; 236 unsigned int iface; 237 int ctrl, old_ctrl; 238 239 imx_dwmac_fix_speed(priv, speed, mode); 240 241 if (!dwmac || mode != MLO_AN_FIXED) 242 return; 243 244 if (regmap_read(dwmac->intf_regmap, dwmac->intf_reg_off, &iface)) 245 return; 246 247 iface &= MX93_GPR_ENET_QOS_INTF_MASK; 248 if (iface != MX93_GPR_ENET_QOS_INTF_SEL_RGMII) 249 return; 250 251 old_ctrl = readl(dwmac->base_addr + MAC_CTRL_REG); 252 ctrl = old_ctrl & ~CTRL_SPEED_MASK; 253 regmap_update_bits(dwmac->intf_regmap, dwmac->intf_reg_off, 254 MX93_GPR_ENET_QOS_INTF_MODE_MASK, 0); 255 writel(ctrl, dwmac->base_addr + MAC_CTRL_REG); 256 257 /* Ensure the settings for CTRL are applied. */ 258 readl(dwmac->base_addr + MAC_CTRL_REG); 259 260 usleep_range(10, 20); 261 iface |= MX93_GPR_ENET_QOS_CLK_GEN_EN; 262 regmap_update_bits(dwmac->intf_regmap, dwmac->intf_reg_off, 263 MX93_GPR_ENET_QOS_INTF_MODE_MASK, iface); 264 265 writel(old_ctrl, dwmac->base_addr + MAC_CTRL_REG); 266 } 267 268 static int imx_dwmac_mx93_reset(struct stmmac_priv *priv, void __iomem *ioaddr) 269 { 270 struct plat_stmmacenet_data *plat_dat = priv->plat; 271 u32 value = readl(ioaddr + DMA_BUS_MODE); 272 273 /* DMA SW reset */ 274 value |= DMA_BUS_MODE_SFT_RESET; 275 writel(value, ioaddr + DMA_BUS_MODE); 276 277 if (plat_dat->mac_interface == PHY_INTERFACE_MODE_RMII) { 278 usleep_range(100, 200); 279 writel(RMII_RESET_SPEED, ioaddr + MAC_CTRL_REG); 280 } 281 282 return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value, 283 !(value & DMA_BUS_MODE_SFT_RESET), 284 10000, 1000000); 285 } 286 287 static int 288 imx_dwmac_parse_dt(struct imx_priv_data *dwmac, struct device *dev) 289 { 290 struct device_node *np = dev->of_node; 291 int err = 0; 292 293 dwmac->rmii_refclk_ext = of_property_read_bool(np, "snps,rmii_refclk_ext"); 294 295 dwmac->clk_tx = devm_clk_get(dev, "tx"); 296 if (IS_ERR(dwmac->clk_tx)) { 297 dev_err(dev, "failed to get tx clock\n"); 298 return PTR_ERR(dwmac->clk_tx); 299 } 300 301 dwmac->clk_mem = NULL; 302 303 if (of_machine_is_compatible("fsl,imx8dxl") || 304 of_machine_is_compatible("fsl,imx91") || 305 of_machine_is_compatible("fsl,imx93")) { 306 dwmac->clk_mem = devm_clk_get(dev, "mem"); 307 if (IS_ERR(dwmac->clk_mem)) { 308 dev_err(dev, "failed to get mem clock\n"); 309 return PTR_ERR(dwmac->clk_mem); 310 } 311 } 312 313 if (of_machine_is_compatible("fsl,imx8mp") || 314 of_machine_is_compatible("fsl,imx91") || 315 of_machine_is_compatible("fsl,imx93")) { 316 /* Binding doc describes the propety: 317 * is required by i.MX8MP, i.MX91, i.MX93. 318 * is optinoal for i.MX8DXL. 319 */ 320 dwmac->intf_regmap = 321 syscon_regmap_lookup_by_phandle_args(np, "intf_mode", 1, 322 &dwmac->intf_reg_off); 323 if (IS_ERR(dwmac->intf_regmap)) 324 return PTR_ERR(dwmac->intf_regmap); 325 } 326 327 return err; 328 } 329 330 static int imx_dwmac_probe(struct platform_device *pdev) 331 { 332 struct plat_stmmacenet_data *plat_dat; 333 struct stmmac_resources stmmac_res; 334 struct imx_priv_data *dwmac; 335 const struct imx_dwmac_ops *data; 336 int ret; 337 338 ret = stmmac_get_platform_resources(pdev, &stmmac_res); 339 if (ret) 340 return ret; 341 342 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); 343 if (!dwmac) 344 return -ENOMEM; 345 346 plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac); 347 if (IS_ERR(plat_dat)) 348 return PTR_ERR(plat_dat); 349 350 data = of_device_get_match_data(&pdev->dev); 351 if (!data) { 352 dev_err(&pdev->dev, "failed to get match data\n"); 353 return -EINVAL; 354 } 355 356 dwmac->ops = data; 357 dwmac->dev = &pdev->dev; 358 359 ret = imx_dwmac_parse_dt(dwmac, &pdev->dev); 360 if (ret) { 361 dev_err(&pdev->dev, "failed to parse OF data\n"); 362 return ret; 363 } 364 365 if (data->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY) 366 plat_dat->flags |= STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY; 367 368 /* Default TX Q0 to use TSO and rest TXQ for TBS */ 369 for (int i = 1; i < plat_dat->tx_queues_to_use; i++) 370 plat_dat->tx_queues_cfg[i].tbs_en = 1; 371 372 plat_dat->host_dma_width = dwmac->ops->addr_width; 373 plat_dat->init = imx_dwmac_init; 374 plat_dat->exit = imx_dwmac_exit; 375 plat_dat->clks_config = imx_dwmac_clks_config; 376 plat_dat->bsp_priv = dwmac; 377 dwmac->plat_dat = plat_dat; 378 dwmac->base_addr = stmmac_res.addr; 379 380 ret = imx_dwmac_clks_config(dwmac, true); 381 if (ret) 382 return ret; 383 384 if (dwmac->ops->fix_mac_speed) { 385 plat_dat->fix_mac_speed = dwmac->ops->fix_mac_speed; 386 } else if (!dwmac->ops->mac_rgmii_txclk_auto_adj) { 387 plat_dat->clk_tx_i = dwmac->clk_tx; 388 plat_dat->set_clk_tx_rate = imx_dwmac_set_clk_tx_rate; 389 } 390 391 dwmac->plat_dat->fix_soc_reset = dwmac->ops->fix_soc_reset; 392 393 ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); 394 if (ret) 395 imx_dwmac_clks_config(dwmac, false); 396 397 return ret; 398 } 399 400 static struct imx_dwmac_ops imx8mp_dwmac_data = { 401 .addr_width = 34, 402 .mac_rgmii_txclk_auto_adj = false, 403 .set_intf_mode = imx8mp_set_intf_mode, 404 .flags = STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY, 405 }; 406 407 static struct imx_dwmac_ops imx8dxl_dwmac_data = { 408 .addr_width = 32, 409 .mac_rgmii_txclk_auto_adj = true, 410 .set_intf_mode = imx8dxl_set_intf_mode, 411 }; 412 413 static struct imx_dwmac_ops imx93_dwmac_data = { 414 .addr_width = 32, 415 .mac_rgmii_txclk_auto_adj = true, 416 .set_intf_mode = imx93_set_intf_mode, 417 .fix_soc_reset = imx_dwmac_mx93_reset, 418 .fix_mac_speed = imx93_dwmac_fix_speed, 419 }; 420 421 static const struct of_device_id imx_dwmac_match[] = { 422 { .compatible = "nxp,imx8mp-dwmac-eqos", .data = &imx8mp_dwmac_data }, 423 { .compatible = "nxp,imx8dxl-dwmac-eqos", .data = &imx8dxl_dwmac_data }, 424 { .compatible = "nxp,imx93-dwmac-eqos", .data = &imx93_dwmac_data }, 425 { } 426 }; 427 MODULE_DEVICE_TABLE(of, imx_dwmac_match); 428 429 static struct platform_driver imx_dwmac_driver = { 430 .probe = imx_dwmac_probe, 431 .remove = stmmac_pltfr_remove, 432 .driver = { 433 .name = "imx-dwmac", 434 .pm = &stmmac_pltfr_pm_ops, 435 .of_match_table = imx_dwmac_match, 436 }, 437 }; 438 module_platform_driver(imx_dwmac_driver); 439 440 MODULE_AUTHOR("NXP"); 441 MODULE_DESCRIPTION("NXP imx8 DWMAC Specific Glue layer"); 442 MODULE_LICENSE("GPL v2"); 443