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