fxmac_phy.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fxmac_phy.c
  15. * Date: 2022-04-06 14:46:52
  16. * LastEditTime: 2022-04-06 14:46:58
  17. * Description:  This file is for
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. */
  23. #include "fxmac.h"
  24. #include "eth_ieee_reg.h"
  25. #include "fdebug.h"
  26. #if defined(CONFIG_FXMAC_PHY_YT)
  27. #include "phy_yt.h"
  28. #endif
  29. #define FXMAC_DEBUG_TAG "FXMAC_PHY"
  30. #define FXMAC_ERROR(format, ...) FT_DEBUG_PRINT_E(FXMAC_DEBUG_TAG, format, ##__VA_ARGS__)
  31. #define FXMAC_INFO(format, ...) FT_DEBUG_PRINT_I(FXMAC_DEBUG_TAG, format, ##__VA_ARGS__)
  32. #define FXMAC_DEBUG(format, ...) FT_DEBUG_PRINT_D(FXMAC_DEBUG_TAG, format, ##__VA_ARGS__)
  33. #define FXMAC_WARN(format, ...) FT_DEBUG_PRINT_W(FXMAC_DEBUG_TAG, format, ##__VA_ARGS__)
  34. static FXmac *instance_b;
  35. static u32 phy_addr_b;
  36. static FError FXmacDetect(FXmac *instance_p, u32 *phy_addr_p)
  37. {
  38. u32 phy_addr = 0, i = 0, index;
  39. u16 phy_reg = 0, phy_id1_reg, phy_id2_reg;
  40. FError ret;
  41. instance_b = instance_p;
  42. for (phy_addr = 0; phy_addr < FT_XMAC_PHY_MAX_NUM; phy_addr++)
  43. {
  44. ret = FXmacPhyRead(instance_p, phy_addr, PHY_STATUS_REG_OFFSET, &phy_reg);
  45. if (ret != FT_SUCCESS)
  46. {
  47. FXMAC_ERROR("%s, PHY operation is busy", __func__);
  48. return ret;
  49. }
  50. FXMAC_INFO("PHY_STATUS_REG_OFFSET is %x \r\n", phy_reg);
  51. if (phy_reg != 0xffff)
  52. {
  53. ret = FXmacPhyRead(instance_p, phy_addr, PHY_IDENTIFIER_1_REG, &phy_id1_reg);
  54. ret |= FXmacPhyRead(instance_p, phy_addr, PHY_IDENTIFIER_2_REG, &phy_id2_reg);
  55. FXMAC_INFO("phy_id1_reg is 0x%x \r\n", phy_id1_reg);
  56. FXMAC_INFO("phy_id2_reg is 0x%x \r\n", phy_id2_reg);
  57. if ((ret == FT_SUCCESS) && (phy_id2_reg != 0) && (phy_id1_reg != 0xffff) && (phy_id1_reg != 0xffff))
  58. {
  59. *phy_addr_p = phy_addr;
  60. phy_addr_b = phy_addr;
  61. FXMAC_INFO("phy_addr is 0x%x \r\n", phy_addr);
  62. return FT_SUCCESS;
  63. }
  64. }
  65. }
  66. return FT_SUCCESS;
  67. }
  68. static FError FXmacGetIeeePhySpeed(FXmac *instance_p, u32 phy_addr)
  69. {
  70. u16 temp, temp2;
  71. u16 control;
  72. u16 status;
  73. u16 partner_capabilities;
  74. u32 negotitation_timeout_cnt = 0;
  75. FError ret;
  76. volatile s32 wait;
  77. FXMAC_INFO("Start PHY autonegotiation ");
  78. ret = FXmacPhyRead(instance_p, phy_addr, PHY_CONTROL_REG_OFFSET, &control);
  79. if (ret != FT_SUCCESS)
  80. {
  81. FXMAC_ERROR("%s line is %d,read PHY_CONTROL_REG_OFFSET is error", __func__, __LINE__);
  82. return ret;
  83. }
  84. control |= PHY_CONTROL_RESET_MASK;
  85. ret = FXmacPhyWrite(instance_p, phy_addr, PHY_CONTROL_REG_OFFSET, control);
  86. if (ret != FT_SUCCESS)
  87. {
  88. FXMAC_ERROR("%s line is %d,write PHY_CONTROL_REG_OFFSET is error", __func__, __LINE__);
  89. return ret;
  90. }
  91. for (wait = 0; wait < 100000; wait++)
  92. ;
  93. FXMAC_INFO(" PHY reset end ");
  94. ret = FXmacPhyRead(instance_p, phy_addr, PHY_CONTROL_REG_OFFSET, &control);
  95. if (ret != FT_SUCCESS)
  96. {
  97. FXMAC_ERROR("%s line is %d,read PHY_CONTROL_REG_OFFSET is error", __func__, __LINE__);
  98. return ret;
  99. }
  100. control |= PHY_CONTROL_AUTONEGOTIATE_ENABLE;
  101. control |= PHY_CONTROL_AUTONEGOTIATE_RESTART;
  102. ret = FXmacPhyWrite(instance_p, phy_addr, PHY_CONTROL_REG_OFFSET, control);
  103. if (ret != FT_SUCCESS)
  104. {
  105. FXMAC_ERROR("%s line is %d,write PHY_CONTROL_REG_OFFSET is error", __func__, __LINE__);
  106. return ret;
  107. }
  108. FXMAC_INFO("Waiting for PHY to complete autonegotiation.");
  109. ret = FXmacPhyRead(instance_p, phy_addr, PHY_STATUS_REG_OFFSET, &status);
  110. if (ret != FT_SUCCESS)
  111. {
  112. FXMAC_ERROR("%s line is %d,read PHY_CONTROL_REG_OFFSET is error", __func__, __LINE__);
  113. return ret;
  114. }
  115. while (!(status & PHY_STATUS_AUTONEGOTIATE_COMPLETE))
  116. {
  117. for (wait = 0; wait < 1000000; wait++)
  118. ;
  119. ret = FXmacPhyRead(instance_p, phy_addr, PHY_STATUS_REG_OFFSET, &status);
  120. if (ret != FT_SUCCESS)
  121. {
  122. FXMAC_ERROR("%s line is %d,read PHY_STATUS_REG_OFFSET is error", __func__, __LINE__);
  123. return ret;
  124. }
  125. if (negotitation_timeout_cnt++ >= 0xfff)
  126. {
  127. FXMAC_ERROR("autonegotiation is error ");
  128. return FXMAC_PHY_AUTO_AUTONEGOTIATION_FAILED;
  129. }
  130. }
  131. FXMAC_INFO("autonegotiation complete ");
  132. ret = FXmacPhyRead(instance_p, phy_addr, PHY_SPECIFIC_STATUS_REG, &temp);
  133. if (ret != FT_SUCCESS)
  134. {
  135. FXMAC_ERROR("%s line is %d,read PHY_SPECIFIC_STATUS_REG is error", __func__, __LINE__);
  136. return ret;
  137. }
  138. FXMAC_INFO("temp is %x \r\n", temp);
  139. ret = FXmacPhyRead(instance_p, phy_addr, PHY_STATUS_REG_OFFSET, &temp2);
  140. if (ret != FT_SUCCESS)
  141. {
  142. FXMAC_ERROR("%s line is %d,read PHY_STATUS_REG_OFFSET is error", __func__, __LINE__);
  143. return ret;
  144. }
  145. FXMAC_INFO("temp2 is %x \r\n", temp2);
  146. if (temp & (1 << 13))
  147. {
  148. FXMAC_INFO("duplex is full \r\n");
  149. instance_p->config.duplex = 1;
  150. }
  151. else
  152. {
  153. FXMAC_INFO("duplex is half \r\n");
  154. instance_p->config.duplex = 0;
  155. }
  156. if ((temp & 0xC000) == PHY_SPECIFIC_STATUS_SPEED_1000M)
  157. {
  158. FXMAC_INFO("speed is 1000\r\n");
  159. instance_p->config.speed = 1000;
  160. }
  161. else if ((temp & 0xC000) == PHY_SPECIFIC_STATUS_SPEED_100M)
  162. {
  163. FXMAC_INFO("speed is 100\r\n");
  164. instance_p->config.speed = 100;
  165. }
  166. else
  167. {
  168. FXMAC_INFO("speed is 10\r\n");
  169. instance_p->config.speed = 10;
  170. }
  171. return FT_SUCCESS;
  172. }
  173. void FxmaxLinkupCheck(void)
  174. {
  175. u16 temp;
  176. FXmacPhyRead(instance_b, phy_addr_b, PHY_SPECIFIC_STATUS_REG, &temp);
  177. FXMAC_INFO("0x17 value is %x \r\n", temp);
  178. FXMAC_INFO("linkup status is %x \r\n", temp & (1 << 10));
  179. }
  180. static FError FXmacConfigureIeeePhySpeed(FXmac *instance_p, u32 phy_addr, u32 speed, u32 duplex_mode)
  181. {
  182. u16 control;
  183. u16 autonereg;
  184. volatile s32 wait;
  185. FError ret;
  186. u16 specific_reg = 0;
  187. FXMAC_INFO("manual setting ,phy_addr is %d,speed %d, duplex_mode is %d \r\n", phy_addr, speed, duplex_mode);
  188. ret = FXmacPhyRead(instance_p, phy_addr, PHY_AUTONEGO_ADVERTISE_REG, &autonereg);
  189. if (ret != FT_SUCCESS)
  190. {
  191. FXMAC_ERROR("%s line is %d,read PHY_AUTONEGO_ADVERTISE_REG is error", __func__, __LINE__);
  192. return ret;
  193. }
  194. autonereg |= PHY_AUTOADVERTISE_ASYMMETRIC_PAUSE_MASK;
  195. autonereg |= PHY_AUTOADVERTISE_PAUSE_MASK;
  196. ret = FXmacPhyWrite(instance_p, phy_addr, PHY_AUTONEGO_ADVERTISE_REG, autonereg);
  197. if (ret != FT_SUCCESS)
  198. {
  199. FXMAC_ERROR("%s line is %d,write PHY_AUTONEGO_ADVERTISE_REG is error", __func__, __LINE__);
  200. return ret;
  201. }
  202. ret = FXmacPhyRead(instance_p, phy_addr, PHY_CONTROL_REG_OFFSET, &control);
  203. if (ret != FT_SUCCESS)
  204. {
  205. FXMAC_ERROR("%s line is %d,read PHY_AUTONEGO_ADVERTISE_REG is error", __func__, __LINE__);
  206. return ret;
  207. }
  208. FXMAC_INFO("PHY_CONTROL_REG_OFFSET is %x \r\n", control);
  209. control &= ~PHY_CONTROL_LINKSPEED_1000M;
  210. control &= ~PHY_CONTROL_LINKSPEED_100M;
  211. control &= ~PHY_CONTROL_LINKSPEED_10M;
  212. if (speed == 1000)
  213. {
  214. control |= PHY_CONTROL_LINKSPEED_1000M;
  215. }
  216. else if (speed == 100)
  217. {
  218. control |= PHY_CONTROL_LINKSPEED_100M;
  219. }
  220. else if (speed == 10)
  221. {
  222. control |= PHY_CONTROL_LINKSPEED_10M;
  223. }
  224. if (duplex_mode == 1)
  225. {
  226. control |= PHY_CONTROL_FULL_DUPLEX_MASK;
  227. }
  228. else
  229. {
  230. control &= ~PHY_CONTROL_FULL_DUPLEX_MASK;
  231. }
  232. /* disable auto-negotiation */
  233. control &= ~(PHY_CONTROL_AUTONEGOTIATE_ENABLE);
  234. control &= ~(PHY_CONTROL_AUTONEGOTIATE_RESTART);
  235. ret = FXmacPhyWrite(instance_p, phy_addr, PHY_CONTROL_REG_OFFSET, control); /* Technology Ability Field */
  236. if (ret != FT_SUCCESS)
  237. {
  238. FXMAC_ERROR("%s line is %d,write PHY_AUTONEGO_ADVERTISE_REG is error", __func__, __LINE__);
  239. return ret;
  240. }
  241. for (wait = 0; wait < 100000; wait++)
  242. ;
  243. FXMAC_INFO("Manual selection completed \r\n");
  244. ret = FXmacPhyRead(instance_p, phy_addr, PHY_SPECIFIC_STATUS_REG, &specific_reg);
  245. if (ret != FT_SUCCESS)
  246. {
  247. FXMAC_ERROR("%s line is %d,read PHY_SPECIFIC_STATUS_REG is error", __func__, __LINE__);
  248. return ret;
  249. }
  250. FXMAC_INFO("specific_reg is %x \r\n", specific_reg);
  251. if (specific_reg & (1 << 13))
  252. {
  253. FXMAC_INFO("duplex is full \r\n");
  254. instance_p->config.duplex = 1;
  255. }
  256. else
  257. {
  258. FXMAC_INFO("duplex is half \r\n");
  259. instance_p->config.duplex = 0;
  260. }
  261. if ((specific_reg & 0xC000) == PHY_SPECIFIC_STATUS_SPEED_1000M)
  262. {
  263. FXMAC_INFO("speed is 1000\r\n");
  264. instance_p->config.speed = 1000;
  265. }
  266. else if ((specific_reg & 0xC000) == PHY_SPECIFIC_STATUS_SPEED_100M)
  267. {
  268. FXMAC_INFO("speed is 100\r\n");
  269. instance_p->config.speed = 100;
  270. }
  271. else
  272. {
  273. FXMAC_INFO("speed is 10\r\n");
  274. instance_p->config.speed = 10;
  275. }
  276. return FT_SUCCESS;
  277. }
  278. /**
  279. * @name: FXmacPhyInit
  280. * @msg: setup the PHYs for proper speed setting.
  281. * @param {FXmac} *instance_p is a pointer to the instance to be worked on.
  282. * @param {u32} speed is phy operating speed
  283. * @param {u32} phy_addr is the address of the PHY to be read (supports multiple PHYs)
  284. * @param {u32} duplex_mode is The duplex mode can be selected via either the Auto-Negotiation process or manual duplex selection.
  285. * @param {u32} autonegotiation_en is an auto-negotiated flag . 1 is enable auto ,0 is manual
  286. * @return {FError}
  287. */
  288. FError FXmacPhyInit(FXmac *instance_p, u32 speed, u32 duplex_mode, u32 autonegotiation_en)
  289. {
  290. FError ret;
  291. u32 index = 0, phy_mask;
  292. u16 phy_identity;
  293. u32 phy_addr;
  294. if (FXmacDetect(instance_p, &phy_addr) != FT_SUCCESS)
  295. {
  296. FXMAC_ERROR("phy is not found");
  297. return FXMAC_PHY_IS_NOT_FOUND;
  298. }
  299. FXMAC_INFO("settings phy_addr is %d\n", phy_addr);
  300. instance_p->phy_address = phy_addr;
  301. if (autonegotiation_en)
  302. {
  303. ret = FXmacGetIeeePhySpeed(instance_p, phy_addr);
  304. if (ret != FT_SUCCESS)
  305. {
  306. return ret;
  307. }
  308. }
  309. else
  310. {
  311. FXMAC_INFO("Set the communication speed manually");
  312. ret = FXmacConfigureIeeePhySpeed(instance_p, phy_addr, speed, duplex_mode);
  313. if (ret != FT_SUCCESS)
  314. {
  315. FXMAC_ERROR("Failed to manually set the PHY");
  316. return ret;
  317. }
  318. }
  319. instance_p->link_status = FXMAC_LINKUP;
  320. return FT_SUCCESS;
  321. }