dwmac-stm32.c 11 KB

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