mtk_eth_path.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (c) 2018-2019 MediaTek Inc.
  3. /* A library for configuring path from GMAC/GDM to target PHY
  4. *
  5. * Author: Sean Wang <sean.wang@mediatek.com>
  6. *
  7. */
  8. #include <linux/phy.h>
  9. #include <linux/regmap.h>
  10. #include "mtk_eth_soc.h"
  11. struct mtk_eth_muxc {
  12. const char *name;
  13. u64 cap_bit;
  14. int (*set_path)(struct mtk_eth *eth, u64 path);
  15. };
  16. static const char *mtk_eth_path_name(u64 path)
  17. {
  18. switch (path) {
  19. case MTK_ETH_PATH_GMAC1_RGMII:
  20. return "gmac1_rgmii";
  21. case MTK_ETH_PATH_GMAC1_TRGMII:
  22. return "gmac1_trgmii";
  23. case MTK_ETH_PATH_GMAC1_SGMII:
  24. return "gmac1_sgmii";
  25. case MTK_ETH_PATH_GMAC2_RGMII:
  26. return "gmac2_rgmii";
  27. case MTK_ETH_PATH_GMAC2_SGMII:
  28. return "gmac2_sgmii";
  29. case MTK_ETH_PATH_GMAC2_2P5GPHY:
  30. return "gmac2_2p5gphy";
  31. case MTK_ETH_PATH_GMAC2_GEPHY:
  32. return "gmac2_gephy";
  33. case MTK_ETH_PATH_GDM1_ESW:
  34. return "gdm1_esw";
  35. default:
  36. return "unknown path";
  37. }
  38. }
  39. static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path)
  40. {
  41. bool updated = true;
  42. u32 mask, set, reg;
  43. switch (path) {
  44. case MTK_ETH_PATH_GMAC1_SGMII:
  45. mask = ~(u32)MTK_MUX_TO_ESW;
  46. set = 0;
  47. break;
  48. case MTK_ETH_PATH_GDM1_ESW:
  49. mask = ~(u32)MTK_MUX_TO_ESW;
  50. set = MTK_MUX_TO_ESW;
  51. break;
  52. default:
  53. updated = false;
  54. break;
  55. }
  56. if (mtk_is_netsys_v3_or_greater(eth))
  57. reg = MTK_MAC_MISC_V3;
  58. else
  59. reg = MTK_MAC_MISC;
  60. if (updated)
  61. mtk_m32(eth, mask, set, reg);
  62. dev_dbg(eth->dev, "path %s in %s updated = %d\n",
  63. mtk_eth_path_name(path), __func__, updated);
  64. return 0;
  65. }
  66. static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path)
  67. {
  68. unsigned int val = 0;
  69. bool updated = true;
  70. switch (path) {
  71. case MTK_ETH_PATH_GMAC2_GEPHY:
  72. val = ~(u32)GEPHY_MAC_SEL;
  73. break;
  74. default:
  75. updated = false;
  76. break;
  77. }
  78. if (updated)
  79. regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
  80. dev_dbg(eth->dev, "path %s in %s updated = %d\n",
  81. mtk_eth_path_name(path), __func__, updated);
  82. return 0;
  83. }
  84. static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
  85. {
  86. unsigned int val = 0, mask = 0, reg = 0;
  87. bool updated = true;
  88. switch (path) {
  89. case MTK_ETH_PATH_GMAC2_SGMII:
  90. if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) {
  91. reg = USB_PHY_SWITCH_REG;
  92. val = SGMII_QPHY_SEL;
  93. mask = QPHY_SEL_MASK;
  94. } else {
  95. reg = INFRA_MISC2;
  96. val = CO_QPHY_SEL;
  97. mask = val;
  98. }
  99. break;
  100. default:
  101. updated = false;
  102. break;
  103. }
  104. if (updated)
  105. regmap_update_bits(eth->infra, reg, mask, val);
  106. dev_dbg(eth->dev, "path %s in %s updated = %d\n",
  107. mtk_eth_path_name(path), __func__, updated);
  108. return 0;
  109. }
  110. static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path)
  111. {
  112. int ret;
  113. if (path == MTK_ETH_PATH_GMAC2_2P5GPHY) {
  114. ret = regmap_clear_bits(eth->ethsys, ETHSYS_SYSCFG0,
  115. SYSCFG0_SGMII_GMAC2_V2);
  116. if (ret)
  117. return ret;
  118. /* Setup mux to 2p5g PHY */
  119. ret = regmap_clear_bits(eth->infra, TOP_MISC_NETSYS_PCS_MUX,
  120. MUX_G2_USXGMII_SEL);
  121. if (ret)
  122. return ret;
  123. dev_dbg(eth->dev, "path %s in %s updated\n",
  124. mtk_eth_path_name(path), __func__);
  125. }
  126. return 0;
  127. }
  128. static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
  129. {
  130. unsigned int val = 0;
  131. bool updated = true;
  132. switch (path) {
  133. case MTK_ETH_PATH_GMAC1_SGMII:
  134. val = SYSCFG0_SGMII_GMAC1;
  135. break;
  136. case MTK_ETH_PATH_GMAC2_SGMII:
  137. val = SYSCFG0_SGMII_GMAC2;
  138. break;
  139. case MTK_ETH_PATH_GMAC1_RGMII:
  140. case MTK_ETH_PATH_GMAC2_RGMII:
  141. regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
  142. val &= SYSCFG0_SGMII_MASK;
  143. if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) ||
  144. (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2))
  145. val = 0;
  146. else
  147. updated = false;
  148. break;
  149. default:
  150. updated = false;
  151. break;
  152. }
  153. if (updated)
  154. regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
  155. SYSCFG0_SGMII_MASK, val);
  156. dev_dbg(eth->dev, "path %s in %s updated = %d\n",
  157. mtk_eth_path_name(path), __func__, updated);
  158. return 0;
  159. }
  160. static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
  161. {
  162. unsigned int val = 0;
  163. bool updated = true;
  164. regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
  165. switch (path) {
  166. case MTK_ETH_PATH_GMAC1_SGMII:
  167. val |= SYSCFG0_SGMII_GMAC1_V2;
  168. break;
  169. case MTK_ETH_PATH_GMAC2_GEPHY:
  170. val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
  171. break;
  172. case MTK_ETH_PATH_GMAC2_SGMII:
  173. val |= SYSCFG0_SGMII_GMAC2_V2;
  174. break;
  175. default:
  176. updated = false;
  177. }
  178. if (updated)
  179. regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
  180. SYSCFG0_SGMII_MASK, val);
  181. dev_dbg(eth->dev, "path %s in %s updated = %d\n",
  182. mtk_eth_path_name(path), __func__, updated);
  183. return 0;
  184. }
  185. static const struct mtk_eth_muxc mtk_eth_muxc[] = {
  186. {
  187. .name = "mux_gdm1_to_gmac1_esw",
  188. .cap_bit = MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
  189. .set_path = set_mux_gdm1_to_gmac1_esw,
  190. }, {
  191. .name = "mux_gmac2_gmac0_to_gephy",
  192. .cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
  193. .set_path = set_mux_gmac2_gmac0_to_gephy,
  194. }, {
  195. .name = "mux_u3_gmac2_to_qphy",
  196. .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
  197. .set_path = set_mux_u3_gmac2_to_qphy,
  198. }, {
  199. .name = "mux_gmac2_to_2p5gphy",
  200. .cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY,
  201. .set_path = set_mux_gmac2_to_2p5gphy,
  202. }, {
  203. .name = "mux_gmac1_gmac2_to_sgmii_rgmii",
  204. .cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
  205. .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
  206. }, {
  207. .name = "mux_gmac12_to_gephy_sgmii",
  208. .cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
  209. .set_path = set_mux_gmac12_to_gephy_sgmii,
  210. },
  211. };
  212. static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path)
  213. {
  214. int i, err = 0;
  215. if (!MTK_HAS_CAPS(eth->soc->caps, path)) {
  216. dev_err(eth->dev, "path %s isn't support on the SoC\n",
  217. mtk_eth_path_name(path));
  218. return -EINVAL;
  219. }
  220. if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
  221. return 0;
  222. /* Setup MUX in path fabric */
  223. for (i = 0; i < ARRAY_SIZE(mtk_eth_muxc); i++) {
  224. if (MTK_HAS_CAPS(eth->soc->caps, mtk_eth_muxc[i].cap_bit)) {
  225. err = mtk_eth_muxc[i].set_path(eth, path);
  226. if (err)
  227. goto out;
  228. } else {
  229. dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
  230. mtk_eth_muxc[i].name);
  231. }
  232. }
  233. out:
  234. return err;
  235. }
  236. int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
  237. {
  238. u64 path;
  239. path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII :
  240. MTK_ETH_PATH_GMAC2_SGMII;
  241. /* Setup proper MUXes along the path */
  242. return mtk_eth_mux_setup(eth, path);
  243. }
  244. int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id)
  245. {
  246. u64 path = 0;
  247. if (mac_id == MTK_GMAC2_ID)
  248. path = MTK_ETH_PATH_GMAC2_2P5GPHY;
  249. if (!path)
  250. return -EINVAL;
  251. /* Setup proper MUXes along the path */
  252. return mtk_eth_mux_setup(eth, path);
  253. }
  254. int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
  255. {
  256. u64 path = 0;
  257. if (mac_id == 1)
  258. path = MTK_ETH_PATH_GMAC2_GEPHY;
  259. if (!path)
  260. return -EINVAL;
  261. /* Setup proper MUXes along the path */
  262. return mtk_eth_mux_setup(eth, path);
  263. }
  264. int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
  265. {
  266. u64 path;
  267. path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII :
  268. MTK_ETH_PATH_GMAC2_RGMII;
  269. /* Setup proper MUXes along the path */
  270. return mtk_eth_mux_setup(eth, path);
  271. }