xemacpsif_physpeed.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. /*
  2. * Copyright (C) 2010 - 2019 Xilinx, Inc.
  3. * Copyright (C) 2021 WangHuachen.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice,
  10. * this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  20. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  21. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  22. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  25. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  26. * OF SUCH DAMAGE.
  27. *
  28. * This file is part of the lwIP TCP/IP stack.
  29. *
  30. */
  31. /*****************************************************************************
  32. * This file xemacpsif_physpeed.c implements functionalities to:
  33. * - Detect the available PHYs connected to a MAC
  34. * - Negotiate speed
  35. * - Configure speed
  36. * - Configure the SLCR registers for the negotiated speed
  37. *
  38. * In a typical use case, users of the APIs implemented in this file need to
  39. * do the following.
  40. * - Call the API detect_phy. It probes for the available PHYs connected to a MAC.
  41. * The MACs can be Emac0 (XPAR_XEMACPS_0_BASEADDR, 0xE000B000) or Emac1
  42. * (XPAR_XEMACPS_0_BASEADDR, 0xE000C000). It populates an array to notify
  43. * about the detected PHYs. The array phymapemac0 is used for Emac0 and
  44. * phymapemac1 is for Emac1.
  45. * - The users need to parse the corresponding arrays, phymapemac0 or phymapemac1
  46. * to know the available PHYs for a MAC. The users then need to call
  47. * phy_setup_emacps to setup the PHYs for proper speed setting. The API
  48. * phy_setup_emacps should be called with the PHY address for which the speed
  49. * needs to be negotiated or configured. In a specific use case, if 2 PHYs are
  50. * connected to Emac0 with addresses of 7 and 11, then users get these address
  51. * details from phymapemac0 (after calling detect_phy) and then call
  52. * phy_setup_emacps twice, with ab address of 7 and 11.
  53. * - Points to note: The MAC can operate at only one speed. If a MAC is connected
  54. * to multiple PHYs, then all PHYs must negotiate and configured for the same
  55. * speed.
  56. * - This file implements static functions to set proper SLCR clocks. As stated
  57. * above, all PHYs connected to a PHY must operate at same speed and the SLCR
  58. * clock will be setup accordingly.
  59. *
  60. * This file implements the following PHY types.
  61. * - The standard RGMII.
  62. * - It provides support for GMII to RGMII converter Xilinx IP. This Xilinx IP
  63. * sits on the MDIO bus with a predefined PHY address. This IP exposes register
  64. * that needs to be programmed with the negotiated speed.
  65. * For example, in a typical design, the Emac0 or Emac1 exposes GMII interface.
  66. * The user can then use the Xilinx IP that converts GMII to RGMII.
  67. * The external PHY (most typically Marvell 88E1116R) negotiates for speed
  68. * with the remote PHY. The implementation in this file then programs the
  69. * Xilinx IP with this negotiated speed. The Xilinx IP has a predefined IP
  70. * address exposed through xparameters.h
  71. * - The SGMII and 1000 BaseX PHY interfaces.
  72. * If the PHY interface is SGMII or 1000 BaseX a separate "get_IEEE_phy_speed"
  73. * is used which is different from standard RGMII "get_IEEE_phy_speed".
  74. * The 1000 BaseX always operates at 1000 Mbps. The SGMII interface can
  75. * negotiate speed accordingly.
  76. * For SGMII or 1000 BaseX interfaces, the detect_phy should not be called.
  77. * The phy addresses for these interfaces are fixed at the design time.
  78. *
  79. * Point to note:
  80. * A MAC can not be connected to PHYs where there is a mix between
  81. * SGMII or 1000 Basex or GMII/MII/RGMII.
  82. * In a typical multiple PHY designs, it is expected that the PHYs connected
  83. * will be RGMII or GMII.
  84. *
  85. * The users can choose not to negotiate speed from lwip settings GUI.
  86. * If they opt to choose a particular PHY speed, then the PHY will hard code
  87. * the speed to operate only at the corresponding speed. It will not advertise
  88. * any other speeds. It is users responsibility to ensure that the remote PHY
  89. * supports the speed programmed through the lwip gui.
  90. *
  91. * The following combination of MDIO/PHY are supported:
  92. * - Multiple PHYs connected to the MDIO bus of a MAC. If Emac0 MDIO is connected
  93. * to single/multiple PHYs, it is supported. Similarly Emac1 MDIO connected to
  94. * single/multiple PHYs is supported.
  95. * - A design where both the interfaces are present and are connected to their own
  96. * MDIO bus is supported.
  97. *
  98. * The following MDIO/PHY setup is not supported:
  99. * - A design has both the MACs present. MDIO bus is available only for one MAC
  100. * (Emac0 or Emac1). This MDIO bus has multiple PHYs available for both the
  101. * MACs. The negotiated speed for PHYs sitting on the MDIO bus of one MAC will
  102. * not be see for the other MAC and hence the speed/SLCR settings of the other
  103. * MAC cannot be programmed. Hence this kind of design will not work for
  104. * this implementation.
  105. *
  106. ********************************************************************************/
  107. #include "netif/xemacpsif.h"
  108. #include "lwipopts.h"
  109. #include "xparameters_ps.h"
  110. #include "xparameters.h"
  111. #include "xemac_ieee_reg.h"
  112. #if defined (__aarch64__)
  113. #include "bspconfig.h"
  114. #include "xil_smc.h"
  115. #endif
  116. #define CONFIG_LINKSPEED_AUTODETECT 1
  117. #define PHY_DETECT_REG 1
  118. #define PHY_IDENTIFIER_1_REG 2
  119. #define PHY_IDENTIFIER_2_REG 3
  120. #define PHY_DETECT_MASK 0x1808
  121. #define PHY_MARVELL_IDENTIFIER 0x0141
  122. #define PHY_TI_IDENTIFIER 0x2000
  123. #define PHY_REALTEK_IDENTIFIER 0x001c
  124. #define PHY_XILINX_PCS_PMA_ID1 0x0174
  125. #define PHY_XILINX_PCS_PMA_ID2 0x0C00
  126. #define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140
  127. #define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100
  128. #define XEMACPS_GMII2RGMII_SPEED10_FD 0x100
  129. #define XEMACPS_GMII2RGMII_REG_NUM 0x10
  130. #define PHY_REGCR 0x0D
  131. #define PHY_ADDAR 0x0E
  132. #define PHY_RGMIIDCTL 0x86
  133. #define PHY_RGMIICTL 0x32
  134. #define PHY_STS 0x11
  135. #define PHY_TI_CR 0x10
  136. #define PHY_TI_CFG4 0x31
  137. #define MICREL_PHY_IDENTIFIER 0x22
  138. #define MICREL_PHY_KSZ9031_MODEL 0x220
  139. #define PHY_REGCR_ADDR 0x001F
  140. #define PHY_REGCR_DATA 0x401F
  141. #define PHY_TI_CRVAL 0x5048
  142. #define PHY_TI_CFG4RESVDBIT7 0x80
  143. /* Frequency setting */
  144. #define SLCR_LOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x4)
  145. #define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8)
  146. #define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140)
  147. #define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144)
  148. #define SLCR_GEM_SRCSEL_EMIO 0x40
  149. #define SLCR_LOCK_KEY_VALUE 0x767B
  150. #define SLCR_UNLOCK_KEY_VALUE 0xDF0D
  151. #define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214)
  152. #define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF
  153. #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
  154. XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
  155. #define PCM_PMA_CORE_PRESENT
  156. #else
  157. #undef PCM_PMA_CORE_PRESENT
  158. #endif
  159. #ifdef PCM_PMA_CORE_PRESENT
  160. #define IEEE_CTRL_RESET 0x9140
  161. #define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF
  162. #endif
  163. u32_t phymapemac0[32];
  164. u32_t phymapemac1[32];
  165. #if defined (PCM_PMA_CORE_PRESENT) || defined (CONFIG_LINKSPEED_AUTODETECT)
  166. static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr);
  167. #endif
  168. static void SetUpSLCRDivisors(u32_t mac_baseaddr, s32_t speed);
  169. #if defined (CONFIG_LINKSPEED1000) || defined (CONFIG_LINKSPEED100) \
  170. || defined (CONFIG_LINKSPEED10)
  171. static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed);
  172. #endif
  173. #ifdef PCM_PMA_CORE_PRESENT
  174. u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr)
  175. {
  176. u32_t link_speed;
  177. u16_t regval;
  178. u16_t phy_id;
  179. if(phy_addr == 0) {
  180. for (phy_addr = 31; phy_addr > 0; phy_addr--) {
  181. XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
  182. &phy_id);
  183. if (phy_id == PHY_XILINX_PCS_PMA_ID1) {
  184. XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_2_REG,
  185. &phy_id);
  186. if (phy_id == PHY_XILINX_PCS_PMA_ID2) {
  187. /* Found a valid PHY address */
  188. LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
  189. phy_addr));
  190. break;
  191. }
  192. }
  193. }
  194. }
  195. link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr);
  196. if (link_speed == 1000)
  197. SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
  198. else if (link_speed == 100)
  199. SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
  200. else
  201. SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
  202. xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
  203. return link_speed;
  204. }
  205. static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
  206. {
  207. u16_t temp;
  208. u16_t control;
  209. u16_t status;
  210. u16_t partner_capabilities;
  211. xil_printf("Start PHY autonegotiation \r\n");
  212. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  213. control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
  214. control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
  215. control &= IEEE_CTRL_ISOLATE_DISABLE;
  216. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  217. xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
  218. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  219. while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
  220. sleep(1);
  221. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
  222. &status);
  223. }
  224. xil_printf("autonegotiation complete \r\n");
  225. #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1
  226. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1);
  227. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
  228. if ((temp & 0x0020) == 0x0020) {
  229. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
  230. return 1000;
  231. }
  232. else {
  233. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
  234. xil_printf("Link error, temp = %x\r\n", temp);
  235. return 0;
  236. }
  237. #elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
  238. xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
  239. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
  240. while(!(temp & 0x8000)) {
  241. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
  242. }
  243. if((temp & 0x0C00) == 0x0800) {
  244. return 1000;
  245. }
  246. else if((temp & 0x0C00) == 0x0400) {
  247. return 100;
  248. }
  249. else if((temp & 0x0C00) == 0x0000) {
  250. return 10;
  251. } else {
  252. xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Defaulting to Speed = 10 Mbps\r\n");
  253. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &temp);
  254. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, 0x0100);
  255. return 10;
  256. }
  257. #endif
  258. }
  259. #else /*PCM_PMA_CORE_PRESENT not defined, GMII/RGMII case*/
  260. void detect_phy(XEmacPs *xemacpsp)
  261. {
  262. u16_t phy_reg;
  263. u32_t phy_addr;
  264. u32_t emacnum;
  265. if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR)
  266. emacnum = 0;
  267. else
  268. emacnum = 1;
  269. for (phy_addr = 31; phy_addr > 0; phy_addr--) {
  270. XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
  271. &phy_reg);
  272. if ((phy_reg != 0xFFFF) &&
  273. ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
  274. /* Found a valid PHY address */
  275. LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
  276. phy_addr));
  277. if (emacnum == 0)
  278. phymapemac0[phy_addr] = TRUE;
  279. else
  280. phymapemac1[phy_addr] = TRUE;
  281. XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
  282. &phy_reg);
  283. if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
  284. (phy_reg != PHY_TI_IDENTIFIER) &&
  285. (phy_reg != PHY_REALTEK_IDENTIFIER)) {
  286. xil_printf("WARNING: Not a Marvell or TI or Realtek Ethernet PHY. Please verify the initialization sequence\r\n");
  287. }
  288. }
  289. }
  290. }
  291. u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr)
  292. {
  293. u32_t link_speed;
  294. u32_t conv_present = 0;
  295. u32_t convspeeddupsetting = 0;
  296. u32_t convphyaddr = 0;
  297. #ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
  298. convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
  299. conv_present = 1;
  300. #endif
  301. #ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
  302. convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
  303. conv_present = 1;
  304. #endif
  305. #ifdef CONFIG_LINKSPEED_AUTODETECT
  306. link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr);
  307. if (link_speed == 1000) {
  308. SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
  309. convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
  310. } else if (link_speed == 100) {
  311. SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
  312. convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
  313. } else if (link_speed != XST_FAILURE){
  314. SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
  315. convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
  316. } else {
  317. xil_printf("Phy setup error \r\n");
  318. return XST_FAILURE;
  319. }
  320. #elif defined(CONFIG_LINKSPEED1000)
  321. SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
  322. link_speed = 1000;
  323. configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
  324. convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
  325. sleep(1);
  326. #elif defined(CONFIG_LINKSPEED100)
  327. SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
  328. link_speed = 100;
  329. configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
  330. convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
  331. sleep(1);
  332. #elif defined(CONFIG_LINKSPEED10)
  333. SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
  334. link_speed = 10;
  335. configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
  336. convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
  337. sleep(1);
  338. #endif
  339. if (conv_present) {
  340. XEmacPs_PhyWrite(xemacpsp, convphyaddr,
  341. XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
  342. }
  343. xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
  344. return link_speed;
  345. }
  346. #if defined CONFIG_LINKSPEED_AUTODETECT
  347. static u32_t get_phy_speed_ksz9031(XEmacPs *xemacpsp, u32_t phy_addr)
  348. {
  349. static int phy_init_flag = 0;
  350. u16_t temp;
  351. u16_t control;
  352. u16_t status;
  353. u16_t status_speed;
  354. u32_t timeout_counter = 0;
  355. xil_printf("Start PHY autonegotiation \r\n");
  356. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
  357. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
  358. control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
  359. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
  360. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
  361. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
  362. control |= IEEE_ASYMMETRIC_PAUSE_MASK;
  363. control |= IEEE_PAUSE_MASK;
  364. control |= ADVERTISE_100;
  365. control |= ADVERTISE_10;
  366. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
  367. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  368. &control);
  369. control |= ADVERTISE_1000;
  370. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  371. control);
  372. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
  373. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, &control);
  374. control |= (7 << 12); /* max number of gigabit attempts */
  375. control |= (1 << 11); /* enable downshift */
  376. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
  377. control);
  378. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  379. control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
  380. control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
  381. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  382. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  383. control |= IEEE_CTRL_RESET_MASK;
  384. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  385. while (1) {
  386. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  387. if (control & IEEE_CTRL_RESET_MASK)
  388. continue;
  389. else
  390. break;
  391. }
  392. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  393. xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
  394. while (!(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)) {
  395. sleep(1);
  396. XEmacPs_PhyRead(xemacpsp, phy_addr,
  397. IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
  398. timeout_counter++;
  399. if ((phy_init_flag == 0) && (timeout_counter > 1))
  400. {
  401. phy_init_flag = 1;
  402. return XST_FAILURE;
  403. }
  404. if (timeout_counter == 30) {
  405. xil_printf("Auto negotiation error \r\n");
  406. return XST_FAILURE;
  407. }
  408. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  409. }
  410. xil_printf("autonegotiation complete \r\n");
  411. XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1f, &status_speed);
  412. if ((status_speed & 0x40) == 0x40) /* 1000Mbps */
  413. return 1000;
  414. else if ((status_speed & 0x20) == 0x20) /* 100Mbps */
  415. return 100;
  416. else if ((status_speed & 0x10) == 0x10) /* 10Mbps */
  417. return 10;
  418. else
  419. return 0;
  420. return XST_SUCCESS;
  421. }
  422. static u32_t get_TI_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
  423. {
  424. u16_t control;
  425. u16_t status;
  426. u16_t status_speed;
  427. u32_t timeout_counter = 0;
  428. u32_t phyregtemp;
  429. int i;
  430. u32_t RetStatus;
  431. static int phy_init_flag = 0;
  432. xil_printf("Start PHY autonegotiation \r\n");
  433. XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp);
  434. phyregtemp |= 0x4000;
  435. XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, phyregtemp);
  436. RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp);
  437. if (RetStatus != XST_SUCCESS) {
  438. xil_printf("Error during sw reset \n\r");
  439. return XST_FAILURE;
  440. }
  441. XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp);
  442. phyregtemp |= 0x8000;
  443. XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, phyregtemp);
  444. /*
  445. * Delay
  446. */
  447. for(i=0;i<1000000000;i++);
  448. RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp);
  449. if (RetStatus != XST_SUCCESS) {
  450. xil_printf("Error during reset \n\r");
  451. return XST_FAILURE;
  452. }
  453. /* FIFO depth */
  454. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_TI_CR, PHY_TI_CRVAL);
  455. RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_TI_CR, (u16_t *)&phyregtemp);
  456. if (RetStatus != XST_SUCCESS) {
  457. xil_printf("Error writing to 0x10 \n\r");
  458. return XST_FAILURE;
  459. }
  460. /* TX/RX tuning */
  461. /* Write to PHY_RGMIIDCTL */
  462. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
  463. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL);
  464. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
  465. RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xA8);
  466. if (RetStatus != XST_SUCCESS) {
  467. xil_printf("Error in tuning");
  468. return XST_FAILURE;
  469. }
  470. /* Read PHY_RGMIIDCTL */
  471. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
  472. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL);
  473. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
  474. RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
  475. if (RetStatus != XST_SUCCESS) {
  476. xil_printf("Error in tuning");
  477. return XST_FAILURE;
  478. }
  479. /* Write PHY_RGMIICTL */
  480. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
  481. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL);
  482. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
  483. RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xD3);
  484. if (RetStatus != XST_SUCCESS) {
  485. xil_printf("Error in tuning");
  486. return XST_FAILURE;
  487. }
  488. /* Read PHY_RGMIICTL */
  489. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
  490. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL);
  491. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
  492. RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
  493. if (RetStatus != XST_SUCCESS) {
  494. xil_printf("Error in tuning");
  495. return XST_FAILURE;
  496. }
  497. /* SW workaround for unstable link when RX_CTRL is not STRAP MODE 3 or 4 */
  498. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
  499. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4);
  500. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
  501. RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
  502. phyregtemp &= ~(PHY_TI_CFG4RESVDBIT7);
  503. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
  504. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4);
  505. XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
  506. RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, phyregtemp);
  507. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
  508. control |= IEEE_ASYMMETRIC_PAUSE_MASK;
  509. control |= IEEE_PAUSE_MASK;
  510. control |= ADVERTISE_100;
  511. control |= ADVERTISE_10;
  512. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
  513. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  514. &control);
  515. control |= ADVERTISE_1000;
  516. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  517. control);
  518. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  519. control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
  520. control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
  521. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  522. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  523. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  524. xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
  525. while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
  526. sleep(1);
  527. timeout_counter++;
  528. if ((phy_init_flag == 0) && (timeout_counter > 1))
  529. {
  530. phy_init_flag = 1;
  531. return XST_FAILURE;
  532. }
  533. if (timeout_counter == 30) {
  534. xil_printf("Auto negotiation error \r\n");
  535. return XST_FAILURE;
  536. }
  537. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  538. }
  539. xil_printf("autonegotiation complete \r\n");
  540. XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_STS, &status_speed);
  541. if ((status_speed & 0xC000) == 0x8000) {
  542. return 1000;
  543. } else if ((status_speed & 0xC000) == 0x4000) {
  544. return 100;
  545. } else {
  546. return 10;
  547. }
  548. return XST_SUCCESS;
  549. }
  550. static u32_t get_Marvell_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
  551. {
  552. u16_t temp;
  553. u16_t control;
  554. u16_t status;
  555. u16_t status_speed;
  556. u32_t timeout_counter = 0;
  557. u32_t temp_speed;
  558. static int phy_init_flag = 0;
  559. xil_printf("Start PHY autonegotiation \r\n");
  560. XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
  561. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
  562. control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
  563. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
  564. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
  565. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
  566. control |= IEEE_ASYMMETRIC_PAUSE_MASK;
  567. control |= IEEE_PAUSE_MASK;
  568. control |= ADVERTISE_100;
  569. control |= ADVERTISE_10;
  570. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
  571. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  572. &control);
  573. control |= ADVERTISE_1000;
  574. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  575. control);
  576. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
  577. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
  578. &control);
  579. control |= (7 << 12); /* max number of gigabit attempts */
  580. control |= (1 << 11); /* enable downshift */
  581. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
  582. control);
  583. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  584. control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
  585. control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
  586. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  587. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  588. control |= IEEE_CTRL_RESET_MASK;
  589. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  590. while (1) {
  591. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  592. if (control & IEEE_CTRL_RESET_MASK)
  593. continue;
  594. else
  595. break;
  596. }
  597. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  598. xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
  599. while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
  600. sleep(1);
  601. XEmacPs_PhyRead(xemacpsp, phy_addr,
  602. IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
  603. timeout_counter++;
  604. if ((phy_init_flag == 0) && (timeout_counter > 1))
  605. {
  606. phy_init_flag = 1;
  607. return XST_FAILURE;
  608. }
  609. if (timeout_counter == 30) {
  610. xil_printf("Auto negotiation error \r\n");
  611. return XST_FAILURE;
  612. }
  613. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  614. }
  615. xil_printf("autonegotiation complete \r\n");
  616. XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
  617. &status_speed);
  618. if (status_speed & 0x400) {
  619. temp_speed = status_speed & IEEE_SPEED_MASK;
  620. if (temp_speed == IEEE_SPEED_1000)
  621. return 1000;
  622. else if(temp_speed == IEEE_SPEED_100)
  623. return 100;
  624. else
  625. return 10;
  626. }
  627. return XST_SUCCESS;
  628. }
  629. static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
  630. {
  631. u16_t control;
  632. u16_t status;
  633. u16_t status_speed;
  634. u32_t timeout_counter = 0;
  635. u32_t temp_speed;
  636. static int phy_init_flag = 0;
  637. xil_printf("Start PHY autonegotiation \r\n");
  638. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
  639. control |= IEEE_ASYMMETRIC_PAUSE_MASK;
  640. control |= IEEE_PAUSE_MASK;
  641. control |= ADVERTISE_100;
  642. control |= ADVERTISE_10;
  643. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
  644. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  645. &control);
  646. control |= ADVERTISE_1000;
  647. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  648. control);
  649. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  650. control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
  651. control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
  652. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  653. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  654. control |= IEEE_CTRL_RESET_MASK;
  655. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  656. while (1) {
  657. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  658. if (control & IEEE_CTRL_RESET_MASK)
  659. continue;
  660. else
  661. break;
  662. }
  663. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  664. xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
  665. while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
  666. sleep(1);
  667. timeout_counter++;
  668. if ((phy_init_flag == 0) && (timeout_counter > 1))
  669. {
  670. phy_init_flag = 1;
  671. return XST_FAILURE;
  672. }
  673. if (timeout_counter == 30) {
  674. xil_printf("Auto negotiation error \r\n");
  675. return XST_FAILURE;
  676. }
  677. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  678. }
  679. xil_printf("autonegotiation complete \r\n");
  680. XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
  681. &status_speed);
  682. if (status_speed & 0x400) {
  683. temp_speed = status_speed & IEEE_SPEED_MASK;
  684. if (temp_speed == IEEE_SPEED_1000)
  685. return 1000;
  686. else if(temp_speed == IEEE_SPEED_100)
  687. return 100;
  688. else
  689. return 10;
  690. }
  691. return XST_FAILURE;
  692. }
  693. static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
  694. {
  695. u16_t phy_identity;
  696. u32_t RetStatus;
  697. XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
  698. &phy_identity);
  699. if(phy_identity == MICREL_PHY_IDENTIFIER){
  700. RetStatus = get_phy_speed_ksz9031(xemacpsp, phy_addr);
  701. } else if (phy_identity == PHY_TI_IDENTIFIER) {
  702. RetStatus = get_TI_phy_speed(xemacpsp, phy_addr);
  703. } else if (phy_identity == PHY_REALTEK_IDENTIFIER) {
  704. RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr);
  705. } else {
  706. RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
  707. }
  708. return RetStatus;
  709. }
  710. #endif
  711. #if defined (CONFIG_LINKSPEED1000) || defined (CONFIG_LINKSPEED100) \
  712. || defined (CONFIG_LINKSPEED10)
  713. static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed)
  714. {
  715. u16_t control;
  716. u16_t autonereg;
  717. XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
  718. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
  719. control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
  720. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
  721. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
  722. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
  723. autonereg |= IEEE_ASYMMETRIC_PAUSE_MASK;
  724. autonereg |= IEEE_PAUSE_MASK;
  725. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
  726. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  727. control &= ~IEEE_CTRL_LINKSPEED_1000M;
  728. control &= ~IEEE_CTRL_LINKSPEED_100M;
  729. control &= ~IEEE_CTRL_LINKSPEED_10M;
  730. if (speed == 1000) {
  731. control |= IEEE_CTRL_LINKSPEED_1000M;
  732. /* Don't advertise PHY speed of 100 Mbps */
  733. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
  734. autonereg &= (~ADVERTISE_100);
  735. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
  736. /* Don't advertise PHY speed of 10 Mbps */
  737. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
  738. autonereg &= (~ADVERTISE_10);
  739. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
  740. /* Advertise PHY speed of 1000 Mbps */
  741. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
  742. autonereg |= ADVERTISE_1000;
  743. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
  744. }
  745. else if (speed == 100) {
  746. control |= IEEE_CTRL_LINKSPEED_100M;
  747. /* Don't advertise PHY speed of 1000 Mbps */
  748. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
  749. autonereg &= (~ADVERTISE_1000);
  750. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
  751. /* Don't advertise PHY speed of 10 Mbps */
  752. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
  753. autonereg &= (~ADVERTISE_10);
  754. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
  755. /* Advertise PHY speed of 100 Mbps */
  756. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
  757. autonereg |= ADVERTISE_100;
  758. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
  759. }
  760. else if (speed == 10) {
  761. control |= IEEE_CTRL_LINKSPEED_10M;
  762. /* Don't advertise PHY speed of 1000 Mbps */
  763. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
  764. autonereg &= (~ADVERTISE_1000);
  765. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
  766. /* Don't advertise PHY speed of 100 Mbps */
  767. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
  768. autonereg &= (~ADVERTISE_100);
  769. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
  770. /* Advertise PHY speed of 10 Mbps */
  771. XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
  772. autonereg |= ADVERTISE_10;
  773. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
  774. }
  775. XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
  776. control | IEEE_CTRL_RESET_MASK);
  777. {
  778. volatile s32_t wait;
  779. for (wait=0; wait < 100000; wait++);
  780. }
  781. return 0;
  782. }
  783. #endif
  784. #endif /*PCM_PMA_CORE_PRESENT*/
  785. static void SetUpSLCRDivisors(u32_t mac_baseaddr, s32_t speed)
  786. {
  787. volatile u32_t slcrBaseAddress;
  788. u32_t SlcrDiv0 = 0;
  789. u32_t SlcrDiv1 = 0;
  790. u32_t SlcrTxClkCntrl;
  791. u32_t gigeversion;
  792. volatile u32_t CrlApbBaseAddr;
  793. u32_t CrlApbDiv0 = 0;
  794. u32_t CrlApbDiv1 = 0;
  795. u32_t CrlApbGemCtrl;
  796. #if EL1_NONSECURE
  797. u32_t ClkId;
  798. #endif
  799. gigeversion = ((Xil_In32(mac_baseaddr + 0xFC)) >> 16) & 0xFFF;
  800. if (gigeversion == 2) {
  801. *(volatile u32_t *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
  802. if (mac_baseaddr == ZYNQ_EMACPS_0_BASEADDR) {
  803. slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
  804. } else {
  805. slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
  806. }
  807. if((*(volatile u32_t *)(UINTPTR)(slcrBaseAddress)) &
  808. SLCR_GEM_SRCSEL_EMIO) {
  809. return;
  810. }
  811. if (speed == 1000) {
  812. if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
  813. #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
  814. SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
  815. SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
  816. #endif
  817. } else {
  818. #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
  819. SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
  820. SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
  821. #endif
  822. }
  823. } else if (speed == 100) {
  824. if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
  825. #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
  826. SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
  827. SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
  828. #endif
  829. } else {
  830. #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
  831. SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
  832. SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
  833. #endif
  834. }
  835. } else {
  836. if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
  837. #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
  838. SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
  839. SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
  840. #endif
  841. } else {
  842. #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
  843. SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
  844. SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
  845. #endif
  846. }
  847. }
  848. if (SlcrDiv0 != 0 && SlcrDiv1 != 0) {
  849. SlcrTxClkCntrl = *(volatile u32_t *)(UINTPTR)(slcrBaseAddress);
  850. SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
  851. SlcrTxClkCntrl |= (SlcrDiv1 << 20);
  852. SlcrTxClkCntrl |= (SlcrDiv0 << 8);
  853. *(volatile u32_t *)(UINTPTR)(slcrBaseAddress) = SlcrTxClkCntrl;
  854. *(volatile u32_t *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
  855. } else {
  856. xil_printf("Clock Divisors incorrect - Please check\r\n");
  857. }
  858. } else if (gigeversion == GEM_VERSION_ZYNQMP) {
  859. /* Setup divisors in CRL_APB for Zynq Ultrascale+ MPSoC */
  860. if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
  861. CrlApbBaseAddr = CRL_APB_GEM0_REF_CTRL;
  862. } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
  863. CrlApbBaseAddr = CRL_APB_GEM1_REF_CTRL;
  864. } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
  865. CrlApbBaseAddr = CRL_APB_GEM2_REF_CTRL;
  866. } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
  867. CrlApbBaseAddr = CRL_APB_GEM3_REF_CTRL;
  868. }
  869. if (speed == 1000) {
  870. if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
  871. #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
  872. CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
  873. CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
  874. #endif
  875. } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
  876. #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
  877. CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
  878. CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
  879. #endif
  880. } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
  881. #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0
  882. CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0;
  883. CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV1;
  884. #endif
  885. } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
  886. #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0
  887. CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0;
  888. CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV1;
  889. #endif
  890. }
  891. } else if (speed == 100) {
  892. if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
  893. #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
  894. CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
  895. CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
  896. #endif
  897. } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
  898. #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
  899. CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
  900. CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
  901. #endif
  902. } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
  903. #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0
  904. CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0;
  905. CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV1;
  906. #endif
  907. } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
  908. #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0
  909. CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0;
  910. CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV1;
  911. #endif
  912. }
  913. } else {
  914. if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
  915. #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
  916. CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
  917. CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
  918. #endif
  919. } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
  920. #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
  921. CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
  922. CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
  923. #endif
  924. } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
  925. #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0
  926. CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0;
  927. CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV1;
  928. #endif
  929. } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
  930. #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0
  931. CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0;
  932. CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV1;
  933. #endif
  934. }
  935. }
  936. if (CrlApbDiv0 != 0 && CrlApbDiv1 != 0) {
  937. #if EL1_NONSECURE
  938. XSmc_OutVar RegRead;
  939. RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
  940. 0, 0, 0, 0, 0, 0);
  941. CrlApbGemCtrl = RegRead.Arg0 >> 32;
  942. #else
  943. CrlApbGemCtrl = *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr);
  944. #endif
  945. CrlApbGemCtrl &= ~CRL_APB_GEM_DIV0_MASK;
  946. CrlApbGemCtrl |= CrlApbDiv0 << CRL_APB_GEM_DIV0_SHIFT;
  947. CrlApbGemCtrl &= ~CRL_APB_GEM_DIV1_MASK;
  948. CrlApbGemCtrl |= CrlApbDiv1 << CRL_APB_GEM_DIV1_SHIFT;
  949. #if EL1_NONSECURE
  950. Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(CrlApbBaseAddr) | ((u64)(0xFFFFFFFF) << 32),
  951. (u64)CrlApbGemCtrl, 0, 0, 0, 0, 0);
  952. do {
  953. RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
  954. 0, 0, 0, 0, 0, 0);
  955. } while((RegRead.Arg0 >> 32) != CrlApbGemCtrl);
  956. #else
  957. *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr) = CrlApbGemCtrl;
  958. #endif
  959. } else {
  960. xil_printf("Clock Divisors incorrect - Please check\r\n");
  961. }
  962. } else if (gigeversion == GEM_VERSION_VERSAL) {
  963. /* Setup divisors in CRL for Versal */
  964. if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
  965. CrlApbBaseAddr = VERSAL_CRL_GEM0_REF_CTRL;
  966. #if EL1_NONSECURE
  967. ClkId = CLK_GEM0_REF;
  968. #endif
  969. } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
  970. CrlApbBaseAddr = VERSAL_CRL_GEM1_REF_CTRL;
  971. #if EL1_NONSECURE
  972. ClkId = CLK_GEM1_REF;
  973. #endif
  974. }
  975. if (speed == 1000) {
  976. if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
  977. #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
  978. CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
  979. #endif
  980. } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
  981. #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
  982. CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
  983. #endif
  984. }
  985. } else if (speed == 100) {
  986. if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
  987. #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
  988. CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
  989. #endif
  990. } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
  991. #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
  992. CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
  993. #endif
  994. }
  995. } else {
  996. if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
  997. #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
  998. CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
  999. #endif
  1000. } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
  1001. #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
  1002. CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
  1003. #endif
  1004. }
  1005. }
  1006. if (CrlApbDiv0 != 0) {
  1007. #if EL1_NONSECURE
  1008. Xil_Smc(PM_SET_DIVIDER_SMC_FID, (((u64)CrlApbDiv0 << 32) | ClkId), 0, 0, 0, 0, 0, 0);
  1009. #else
  1010. CrlApbGemCtrl = Xil_In32((UINTPTR)CrlApbBaseAddr);
  1011. CrlApbGemCtrl &= ~VERSAL_CRL_GEM_DIV_MASK;
  1012. CrlApbGemCtrl |= CrlApbDiv0 << VERSAL_CRL_APB_GEM_DIV_SHIFT;
  1013. Xil_Out32((UINTPTR)CrlApbBaseAddr, CrlApbGemCtrl);
  1014. #endif
  1015. } else {
  1016. xil_printf("Clock Divisors incorrect - Please check\r\n");
  1017. }
  1018. }
  1019. return;
  1020. }