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