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