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