1 /* 2 * dwmac-stm32.c - DWMAC Specific Glue layer for STM32 MCU 3 * 4 * Copyright (C) STMicroelectronics SA 2017 5 * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics. 6 * License terms: GNU General Public License (GPL), version 2 7 * 8 */ 9 10 #include <linux/clk.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 SYSCFG_MCU_ETH_MASK BIT(23) 27 #define SYSCFG_MP1_ETH_MASK GENMASK(23, 16) 28 29 #define SYSCFG_PMCR_ETH_CLK_SEL BIT(16) 30 #define SYSCFG_PMCR_ETH_REF_CLK_SEL BIT(17) 31 #define SYSCFG_PMCR_ETH_SEL_MII BIT(20) 32 #define SYSCFG_PMCR_ETH_SEL_RGMII BIT(21) 33 #define SYSCFG_PMCR_ETH_SEL_RMII BIT(23) 34 #define SYSCFG_PMCR_ETH_SEL_GMII 0 35 #define SYSCFG_MCU_ETH_SEL_MII 0 36 #define SYSCFG_MCU_ETH_SEL_RMII 1 37 38 struct stm32_dwmac { 39 struct clk *clk_tx; 40 struct clk *clk_rx; 41 struct clk *clk_eth_ck; 42 struct clk *clk_ethstp; 43 struct clk *syscfg_clk; 44 bool int_phyclk; /* Clock from RCC to drive PHY */ 45 u32 mode_reg; /* MAC glue-logic mode register */ 46 struct regmap *regmap; 47 u32 speed; 48 const struct stm32_ops *ops; 49 struct device *dev; 50 }; 51 52 struct stm32_ops { 53 int (*set_mode)(struct plat_stmmacenet_data *plat_dat); 54 int (*clk_prepare)(struct stm32_dwmac *dwmac, bool prepare); 55 int (*suspend)(struct stm32_dwmac *dwmac); 56 void (*resume)(struct stm32_dwmac *dwmac); 57 int (*parse_data)(struct stm32_dwmac *dwmac, 58 struct device *dev); 59 u32 syscfg_eth_mask; 60 }; 61 62 static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) 63 { 64 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; 65 int ret; 66 67 if (dwmac->ops->set_mode) { 68 ret = dwmac->ops->set_mode(plat_dat); 69 if (ret) 70 return ret; 71 } 72 73 ret = clk_prepare_enable(dwmac->clk_tx); 74 if (ret) 75 return ret; 76 77 if (!dwmac->dev->power.is_suspended) { 78 ret = clk_prepare_enable(dwmac->clk_rx); 79 if (ret) { 80 clk_disable_unprepare(dwmac->clk_tx); 81 return ret; 82 } 83 } 84 85 if (dwmac->ops->clk_prepare) { 86 ret = dwmac->ops->clk_prepare(dwmac, true); 87 if (ret) { 88 clk_disable_unprepare(dwmac->clk_rx); 89 clk_disable_unprepare(dwmac->clk_tx); 90 } 91 } 92 93 return ret; 94 } 95 96 static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare) 97 { 98 int ret = 0; 99 100 if (prepare) { 101 ret = clk_prepare_enable(dwmac->syscfg_clk); 102 if (ret) 103 return ret; 104 105 if (dwmac->int_phyclk) { 106 ret = clk_prepare_enable(dwmac->clk_eth_ck); 107 if (ret) { 108 clk_disable_unprepare(dwmac->syscfg_clk); 109 return ret; 110 } 111 } 112 } else { 113 clk_disable_unprepare(dwmac->syscfg_clk); 114 if (dwmac->int_phyclk) 115 clk_disable_unprepare(dwmac->clk_eth_ck); 116 } 117 return ret; 118 } 119 120 static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) 121 { 122 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; 123 u32 reg = dwmac->mode_reg; 124 int val; 125 126 switch (plat_dat->interface) { 127 case PHY_INTERFACE_MODE_MII: 128 val = SYSCFG_PMCR_ETH_SEL_MII; 129 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n"); 130 break; 131 case PHY_INTERFACE_MODE_GMII: 132 val = SYSCFG_PMCR_ETH_SEL_GMII; 133 if (dwmac->int_phyclk) 134 val |= SYSCFG_PMCR_ETH_CLK_SEL; 135 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n"); 136 break; 137 case PHY_INTERFACE_MODE_RMII: 138 val = SYSCFG_PMCR_ETH_SEL_RMII; 139 if (dwmac->int_phyclk) 140 val |= SYSCFG_PMCR_ETH_REF_CLK_SEL; 141 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n"); 142 break; 143 case PHY_INTERFACE_MODE_RGMII: 144 val = SYSCFG_PMCR_ETH_SEL_RGMII; 145 if (dwmac->int_phyclk) 146 val |= SYSCFG_PMCR_ETH_CLK_SEL; 147 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n"); 148 break; 149 default: 150 pr_debug("SYSCFG init : Do not manage %d interface\n", 151 plat_dat->interface); 152 /* Do not manage others interfaces */ 153 return -EINVAL; 154 } 155 156 return regmap_update_bits(dwmac->regmap, reg, 157 dwmac->ops->syscfg_eth_mask, val); 158 } 159 160 static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) 161 { 162 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; 163 u32 reg = dwmac->mode_reg; 164 int val; 165 166 switch (plat_dat->interface) { 167 case PHY_INTERFACE_MODE_MII: 168 val = SYSCFG_MCU_ETH_SEL_MII; 169 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n"); 170 break; 171 case PHY_INTERFACE_MODE_RMII: 172 val = SYSCFG_MCU_ETH_SEL_RMII; 173 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n"); 174 break; 175 default: 176 pr_debug("SYSCFG init : Do not manage %d interface\n", 177 plat_dat->interface); 178 /* Do not manage others interfaces */ 179 return -EINVAL; 180 } 181 182 return regmap_update_bits(dwmac->regmap, reg, 183 dwmac->ops->syscfg_eth_mask, val); 184 } 185 186 static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac) 187 { 188 clk_disable_unprepare(dwmac->clk_tx); 189 clk_disable_unprepare(dwmac->clk_rx); 190 191 if (dwmac->ops->clk_prepare) 192 dwmac->ops->clk_prepare(dwmac, false); 193 } 194 195 static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac, 196 struct device *dev) 197 { 198 struct device_node *np = dev->of_node; 199 int err; 200 201 /* Get TX/RX clocks */ 202 dwmac->clk_tx = devm_clk_get(dev, "mac-clk-tx"); 203 if (IS_ERR(dwmac->clk_tx)) { 204 dev_err(dev, "No ETH Tx clock provided...\n"); 205 return PTR_ERR(dwmac->clk_tx); 206 } 207 208 dwmac->clk_rx = devm_clk_get(dev, "mac-clk-rx"); 209 if (IS_ERR(dwmac->clk_rx)) { 210 dev_err(dev, "No ETH Rx clock provided...\n"); 211 return PTR_ERR(dwmac->clk_rx); 212 } 213 214 if (dwmac->ops->parse_data) { 215 err = dwmac->ops->parse_data(dwmac, dev); 216 if (err) 217 return err; 218 } 219 220 /* Get mode register */ 221 dwmac->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon"); 222 if (IS_ERR(dwmac->regmap)) 223 return PTR_ERR(dwmac->regmap); 224 225 err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->mode_reg); 226 if (err) 227 dev_err(dev, "Can't get sysconfig mode offset (%d)\n", err); 228 229 return err; 230 } 231 232 static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, 233 struct device *dev) 234 { 235 struct device_node *np = dev->of_node; 236 237 dwmac->int_phyclk = of_property_read_bool(np, "st,int-phyclk"); 238 239 /* Check if internal clk from RCC selected */ 240 if (dwmac->int_phyclk) { 241 /* Get ETH_CLK clocks */ 242 dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck"); 243 if (IS_ERR(dwmac->clk_eth_ck)) { 244 dev_err(dev, "No ETH CK clock provided...\n"); 245 return PTR_ERR(dwmac->clk_eth_ck); 246 } 247 } 248 249 /* Clock used for low power mode */ 250 dwmac->clk_ethstp = devm_clk_get(dev, "ethstp"); 251 if (IS_ERR(dwmac->clk_ethstp)) { 252 dev_err(dev, "No ETH peripheral clock provided for CStop mode ...\n"); 253 return PTR_ERR(dwmac->clk_ethstp); 254 } 255 256 /* Clock for sysconfig */ 257 dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk"); 258 if (IS_ERR(dwmac->syscfg_clk)) { 259 dev_err(dev, "No syscfg clock provided...\n"); 260 return PTR_ERR(dwmac->syscfg_clk); 261 } 262 263 return 0; 264 } 265 266 static int stm32_dwmac_probe(struct platform_device *pdev) 267 { 268 struct plat_stmmacenet_data *plat_dat; 269 struct stmmac_resources stmmac_res; 270 struct stm32_dwmac *dwmac; 271 const struct stm32_ops *data; 272 int ret; 273 274 ret = stmmac_get_platform_resources(pdev, &stmmac_res); 275 if (ret) 276 return ret; 277 278 plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); 279 if (IS_ERR(plat_dat)) 280 return PTR_ERR(plat_dat); 281 282 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); 283 if (!dwmac) { 284 ret = -ENOMEM; 285 goto err_remove_config_dt; 286 } 287 288 data = of_device_get_match_data(&pdev->dev); 289 if (!data) { 290 dev_err(&pdev->dev, "no of match data provided\n"); 291 ret = -EINVAL; 292 goto err_remove_config_dt; 293 } 294 295 dwmac->ops = data; 296 dwmac->dev = &pdev->dev; 297 298 ret = stm32_dwmac_parse_data(dwmac, &pdev->dev); 299 if (ret) { 300 dev_err(&pdev->dev, "Unable to parse OF data\n"); 301 goto err_remove_config_dt; 302 } 303 304 plat_dat->bsp_priv = dwmac; 305 306 ret = stm32_dwmac_init(plat_dat); 307 if (ret) 308 goto err_remove_config_dt; 309 310 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 311 if (ret) 312 goto err_clk_disable; 313 314 return 0; 315 316 err_clk_disable: 317 stm32_dwmac_clk_disable(dwmac); 318 err_remove_config_dt: 319 stmmac_remove_config_dt(pdev, plat_dat); 320 321 return ret; 322 } 323 324 static int stm32_dwmac_remove(struct platform_device *pdev) 325 { 326 struct net_device *ndev = platform_get_drvdata(pdev); 327 struct stmmac_priv *priv = netdev_priv(ndev); 328 int ret = stmmac_dvr_remove(&pdev->dev); 329 330 stm32_dwmac_clk_disable(priv->plat->bsp_priv); 331 332 return ret; 333 } 334 335 static int stm32mp1_suspend(struct stm32_dwmac *dwmac) 336 { 337 int ret = 0; 338 339 ret = clk_prepare_enable(dwmac->clk_ethstp); 340 if (ret) 341 return ret; 342 343 clk_disable_unprepare(dwmac->clk_tx); 344 clk_disable_unprepare(dwmac->syscfg_clk); 345 if (dwmac->int_phyclk) 346 clk_disable_unprepare(dwmac->clk_eth_ck); 347 348 return ret; 349 } 350 351 static void stm32mp1_resume(struct stm32_dwmac *dwmac) 352 { 353 clk_disable_unprepare(dwmac->clk_ethstp); 354 } 355 356 static int stm32mcu_suspend(struct stm32_dwmac *dwmac) 357 { 358 clk_disable_unprepare(dwmac->clk_tx); 359 clk_disable_unprepare(dwmac->clk_rx); 360 361 return 0; 362 } 363 364 #ifdef CONFIG_PM_SLEEP 365 static int stm32_dwmac_suspend(struct device *dev) 366 { 367 struct net_device *ndev = dev_get_drvdata(dev); 368 struct stmmac_priv *priv = netdev_priv(ndev); 369 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; 370 371 int ret; 372 373 ret = stmmac_suspend(dev); 374 375 if (dwmac->ops->suspend) 376 ret = dwmac->ops->suspend(dwmac); 377 378 return ret; 379 } 380 381 static int stm32_dwmac_resume(struct device *dev) 382 { 383 struct net_device *ndev = dev_get_drvdata(dev); 384 struct stmmac_priv *priv = netdev_priv(ndev); 385 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; 386 int ret; 387 388 if (dwmac->ops->resume) 389 dwmac->ops->resume(dwmac); 390 391 ret = stm32_dwmac_init(priv->plat); 392 if (ret) 393 return ret; 394 395 ret = stmmac_resume(dev); 396 397 return ret; 398 } 399 #endif /* CONFIG_PM_SLEEP */ 400 401 static SIMPLE_DEV_PM_OPS(stm32_dwmac_pm_ops, 402 stm32_dwmac_suspend, stm32_dwmac_resume); 403 404 static struct stm32_ops stm32mcu_dwmac_data = { 405 .set_mode = stm32mcu_set_mode, 406 .suspend = stm32mcu_suspend, 407 .syscfg_eth_mask = SYSCFG_MCU_ETH_MASK 408 }; 409 410 static struct stm32_ops stm32mp1_dwmac_data = { 411 .set_mode = stm32mp1_set_mode, 412 .clk_prepare = stm32mp1_clk_prepare, 413 .suspend = stm32mp1_suspend, 414 .resume = stm32mp1_resume, 415 .parse_data = stm32mp1_parse_data, 416 .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK 417 }; 418 419 static const struct of_device_id stm32_dwmac_match[] = { 420 { .compatible = "st,stm32-dwmac", .data = &stm32mcu_dwmac_data}, 421 { .compatible = "st,stm32mp1-dwmac", .data = &stm32mp1_dwmac_data}, 422 { } 423 }; 424 MODULE_DEVICE_TABLE(of, stm32_dwmac_match); 425 426 static struct platform_driver stm32_dwmac_driver = { 427 .probe = stm32_dwmac_probe, 428 .remove = stm32_dwmac_remove, 429 .driver = { 430 .name = "stm32-dwmac", 431 .pm = &stm32_dwmac_pm_ops, 432 .of_match_table = stm32_dwmac_match, 433 }, 434 }; 435 module_platform_driver(stm32_dwmac_driver); 436 437 MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@gmail.com>"); 438 MODULE_AUTHOR("Christophe Roullier <christophe.roullier@st.com>"); 439 MODULE_DESCRIPTION("STMicroelectronics STM32 DWMAC Specific Glue layer"); 440 MODULE_LICENSE("GPL v2"); 441