mtk_eth_path.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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. int cap_bit;
  14. int (*set_path)(struct mtk_eth *eth, int path);
  15. };
  16. static const char *mtk_eth_path_name(int 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_GEPHY:
  30. return "gmac2_gephy";
  31. case MTK_ETH_PATH_GDM1_ESW:
  32. return "gdm1_esw";
  33. default:
  34. return "unknown path";
  35. }
  36. }
  37. static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path)
  38. {
  39. bool updated = true;
  40. u32 val, mask, set;
  41. switch (path) {
  42. case MTK_ETH_PATH_GMAC1_SGMII:
  43. mask = ~(u32)MTK_MUX_TO_ESW;
  44. set = 0;
  45. break;
  46. case MTK_ETH_PATH_GDM1_ESW:
  47. mask = ~(u32)MTK_MUX_TO_ESW;
  48. set = MTK_MUX_TO_ESW;
  49. break;
  50. default:
  51. updated = false;
  52. break;
  53. };
  54. if (updated) {
  55. val = mtk_r32(eth, MTK_MAC_MISC);
  56. val = (val & mask) | set;
  57. mtk_w32(eth, val, MTK_MAC_MISC);
  58. }
  59. dev_dbg(eth->dev, "path %s in %s updated = %d\n",
  60. mtk_eth_path_name(path), __func__, updated);
  61. return 0;
  62. }
  63. static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path)
  64. {
  65. unsigned int val = 0;
  66. bool updated = true;
  67. switch (path) {
  68. case MTK_ETH_PATH_GMAC2_GEPHY:
  69. val = ~(u32)GEPHY_MAC_SEL;
  70. break;
  71. default:
  72. updated = false;
  73. break;
  74. }
  75. if (updated)
  76. regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
  77. dev_dbg(eth->dev, "path %s in %s updated = %d\n",
  78. mtk_eth_path_name(path), __func__, updated);
  79. return 0;
  80. }
  81. static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
  82. {
  83. unsigned int val = 0;
  84. bool updated = true;
  85. switch (path) {
  86. case MTK_ETH_PATH_GMAC2_SGMII:
  87. val = CO_QPHY_SEL;
  88. break;
  89. default:
  90. updated = false;
  91. break;
  92. }
  93. if (updated)
  94. regmap_update_bits(eth->infra, INFRA_MISC2, CO_QPHY_SEL, val);
  95. dev_dbg(eth->dev, "path %s in %s updated = %d\n",
  96. mtk_eth_path_name(path), __func__, updated);
  97. return 0;
  98. }
  99. static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path)
  100. {
  101. unsigned int val = 0;
  102. bool updated = true;
  103. switch (path) {
  104. case MTK_ETH_PATH_GMAC1_SGMII:
  105. val = SYSCFG0_SGMII_GMAC1;
  106. break;
  107. case MTK_ETH_PATH_GMAC2_SGMII:
  108. val = SYSCFG0_SGMII_GMAC2;
  109. break;
  110. case MTK_ETH_PATH_GMAC1_RGMII:
  111. case MTK_ETH_PATH_GMAC2_RGMII:
  112. regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
  113. val &= SYSCFG0_SGMII_MASK;
  114. if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) ||
  115. (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2))
  116. val = 0;
  117. else
  118. updated = false;
  119. break;
  120. default:
  121. updated = false;
  122. break;
  123. };
  124. if (updated)
  125. regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
  126. SYSCFG0_SGMII_MASK, val);
  127. dev_dbg(eth->dev, "path %s in %s updated = %d\n",
  128. mtk_eth_path_name(path), __func__, updated);
  129. return 0;
  130. }
  131. static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path)
  132. {
  133. unsigned int val = 0;
  134. bool updated = true;
  135. regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
  136. switch (path) {
  137. case MTK_ETH_PATH_GMAC1_SGMII:
  138. val |= SYSCFG0_SGMII_GMAC1_V2;
  139. break;
  140. case MTK_ETH_PATH_GMAC2_GEPHY:
  141. val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
  142. break;
  143. case MTK_ETH_PATH_GMAC2_SGMII:
  144. val |= SYSCFG0_SGMII_GMAC2_V2;
  145. break;
  146. default:
  147. updated = false;
  148. };
  149. if (updated)
  150. regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
  151. SYSCFG0_SGMII_MASK, val);
  152. dev_dbg(eth->dev, "path %s in %s updated = %d\n",
  153. mtk_eth_path_name(path), __func__, updated);
  154. return 0;
  155. }
  156. static const struct mtk_eth_muxc mtk_eth_muxc[] = {
  157. {
  158. .name = "mux_gdm1_to_gmac1_esw",
  159. .cap_bit = MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
  160. .set_path = set_mux_gdm1_to_gmac1_esw,
  161. }, {
  162. .name = "mux_gmac2_gmac0_to_gephy",
  163. .cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
  164. .set_path = set_mux_gmac2_gmac0_to_gephy,
  165. }, {
  166. .name = "mux_u3_gmac2_to_qphy",
  167. .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
  168. .set_path = set_mux_u3_gmac2_to_qphy,
  169. }, {
  170. .name = "mux_gmac1_gmac2_to_sgmii_rgmii",
  171. .cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
  172. .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
  173. }, {
  174. .name = "mux_gmac12_to_gephy_sgmii",
  175. .cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
  176. .set_path = set_mux_gmac12_to_gephy_sgmii,
  177. },
  178. };
  179. static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
  180. {
  181. int i, err = 0;
  182. if (!MTK_HAS_CAPS(eth->soc->caps, path)) {
  183. dev_err(eth->dev, "path %s isn't support on the SoC\n",
  184. mtk_eth_path_name(path));
  185. return -EINVAL;
  186. }
  187. if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
  188. return 0;
  189. /* Setup MUX in path fabric */
  190. for (i = 0; i < ARRAY_SIZE(mtk_eth_muxc); i++) {
  191. if (MTK_HAS_CAPS(eth->soc->caps, mtk_eth_muxc[i].cap_bit)) {
  192. err = mtk_eth_muxc[i].set_path(eth, path);
  193. if (err)
  194. goto out;
  195. } else {
  196. dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
  197. mtk_eth_muxc[i].name);
  198. }
  199. }
  200. out:
  201. return err;
  202. }
  203. int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
  204. {
  205. int err, path;
  206. path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII :
  207. MTK_ETH_PATH_GMAC2_SGMII;
  208. /* Setup proper MUXes along the path */
  209. err = mtk_eth_mux_setup(eth, path);
  210. if (err)
  211. return err;
  212. return 0;
  213. }
  214. int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
  215. {
  216. int err, path = 0;
  217. if (mac_id == 1)
  218. path = MTK_ETH_PATH_GMAC2_GEPHY;
  219. if (!path)
  220. return -EINVAL;
  221. /* Setup proper MUXes along the path */
  222. err = mtk_eth_mux_setup(eth, path);
  223. if (err)
  224. return err;
  225. return 0;
  226. }
  227. int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
  228. {
  229. int err, path;
  230. path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII :
  231. MTK_ETH_PATH_GMAC2_RGMII;
  232. /* Setup proper MUXes along the path */
  233. err = mtk_eth_mux_setup(eth, path);
  234. if (err)
  235. return err;
  236. return 0;
  237. }