eth_phy_cvitek.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /*
  2. * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <stdio.h>
  17. #include <assert.h>
  18. #include <string.h>
  19. #include <stdbool.h>
  20. #include "cvi_eth_phy.h"
  21. #include "mii.h"
  22. #include "drv_pinmux.h"
  23. // #define CVI_ETH_PHY_LOOPBACK
  24. #define LOOPBACK_XMII2MAC 0x8000
  25. #define LOOPBACK_PCS2MAC 0x2000
  26. #define LOOPBACK_PMA2MAC 0x1000
  27. #define LOOPBACK_RMII2PHY 0x0080
  28. #define CVITEK_EFUSE_BASE (uintptr_t)DRV_IOREMAP((void *)0x03050000, 0x2000)
  29. #define EPHY_EFUSE_VALID_BIT_BASE (CVITEK_EFUSE_BASE + 0x120)
  30. #define EPHY_EFUSE_TXECHORC_FLAG 0x00000100 // bit 8
  31. #define EPHY_EFUSE_TXITUNE_FLAG 0x00000200 // bit 9
  32. #define EPHY_EFUSE_TXRXTERM_FLAG 0x00000800 // bit 11
  33. static inline bool phy_if_mode_is_rgmii(phy_if_mode_t interface)
  34. {
  35. return interface >= PHY_IF_MODE_RGMII && interface <= PHY_IF_MODE_RGMII_TXID;
  36. }
  37. #if defined(CVI_ETH_PHY_LOOPBACK)
  38. static int cv181x_set_phy_loopback(eth_phy_handle_t handle, phy_loopback_mode_t mode)
  39. {
  40. return 0;
  41. }
  42. #endif
  43. /**
  44. \brief Configure the cv181x before make it start up.
  45. \param[in] handle phy handle
  46. \return error code
  47. */
  48. /* CVITEK cv181x */
  49. int32_t cv181x_config(eth_phy_handle_t handle)
  50. {
  51. assert(handle);
  52. eth_phy_dev_t *dev = (eth_phy_dev_t *)handle;
  53. uint32_t val = 0;
  54. // eth_phy_reset(dev);
  55. // set rg_ephy_apb_rw_sel 0x0804@[0]=1/APB by using APB interface
  56. mmio_write_32(ETH_PHY_BASE + 0x804, 0x0001);
  57. // Release 0x0800[0]=0/shutdown
  58. // mmio_write_32(ETH_PHY_BASE + 0x800, 0x0900);
  59. // Release 0x0800[2]=1/dig_rst_n, Let mii_reg can be accessabile
  60. // mmio_write_32(ETH_PHY_BASE + 0x800, 0x0904);
  61. //mdelay(10);
  62. // ANA INIT (PD/EN), switch to MII-page5
  63. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0500);
  64. // Release ANA_PD p5.0x10@[13:8] = 6'b001100
  65. mmio_write_32(ETH_PHY_BASE + 0x040, 0x0c00);
  66. // Release ANA_EN p5.0x10@[7:0] = 8'b01111110
  67. mmio_write_32(ETH_PHY_BASE + 0x040, 0x0c7e);
  68. // Wait PLL_Lock, Lock_Status p5.0x12@[15] = 1
  69. //mdelay(1);
  70. // Release 0x0800[1] = 1/ana_rst_n
  71. mmio_write_32(ETH_PHY_BASE + 0x800, 0x0906);
  72. // ANA INIT
  73. // @Switch to MII-page5
  74. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0500);
  75. // Efuse register
  76. // Set Double Bias Current
  77. //Set rg_eth_txitune1 0x03009064 [15:8]
  78. //Set rg_eth_txitune0 0x03009064 [7:0]
  79. if ((mmio_read_32(EPHY_EFUSE_VALID_BIT_BASE) & EPHY_EFUSE_TXITUNE_FLAG) == EPHY_EFUSE_TXITUNE_FLAG)
  80. {
  81. val = ((mmio_read_32(CVITEK_EFUSE_BASE + 0x1024) >> 24) & 0xFF) | (((mmio_read_32(CVITEK_EFUSE_BASE + 0x1024) >> 16) & 0xFF) << 8);
  82. mmio_clrsetbits_32(ETH_PHY_BASE + 0x064, 0xFFFF, val);
  83. }
  84. else
  85. mmio_write_32(ETH_PHY_BASE + 0x064, 0x5a5a);
  86. // Set Echo_I
  87. // Set rg_eth_txechoiadj 0x03009054 [15:8]
  88. if ((mmio_read_32(EPHY_EFUSE_VALID_BIT_BASE) & EPHY_EFUSE_TXECHORC_FLAG) == EPHY_EFUSE_TXECHORC_FLAG)
  89. {
  90. mmio_clrsetbits_32(ETH_PHY_BASE + 0x054, 0xFF00, ((mmio_read_32(CVITEK_EFUSE_BASE + 0x1024) >> 8) & 0xFF) << 8);
  91. }
  92. else
  93. mmio_write_32(ETH_PHY_BASE + 0x054, 0x0000);
  94. //Set TX_Rterm & Echo_RC_Delay
  95. // Set rg_eth_txrterm_p1 0x03009058 [11:8]
  96. // Set rg_eth_txrterm 0x03009058 [7:4]
  97. // Set rg_eth_txechorcadj 0x03009058 [3:0]
  98. if ((mmio_read_32(EPHY_EFUSE_VALID_BIT_BASE) & EPHY_EFUSE_TXRXTERM_FLAG) == EPHY_EFUSE_TXRXTERM_FLAG)
  99. {
  100. val = (((mmio_read_32(CVITEK_EFUSE_BASE + 0x1020) >> 28) & 0xF) << 4) | (((mmio_read_32(CVITEK_EFUSE_BASE + 0x1020) >> 24) & 0xF) << 8);
  101. mmio_clrsetbits_32(ETH_PHY_BASE + 0x058, 0xFF0, val);
  102. }
  103. else
  104. mmio_write_32(ETH_PHY_BASE + 0x058, 0x0bb0);
  105. // ETH_100BaseT
  106. // Set Rise update
  107. mmio_write_32(ETH_PHY_BASE + 0x05c, 0x0c10);
  108. // Set Falling phase
  109. mmio_write_32(ETH_PHY_BASE + 0x068, 0x0003);
  110. // Set Double TX Bias Current
  111. mmio_write_32(ETH_PHY_BASE + 0x054, 0x0000);
  112. // Switch to MII-page16
  113. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x1000);
  114. // Set MLT3 Positive phase code, Set MLT3 +0
  115. mmio_write_32(ETH_PHY_BASE + 0x068, 0x1000);
  116. mmio_write_32(ETH_PHY_BASE + 0x06c, 0x3020);
  117. mmio_write_32(ETH_PHY_BASE + 0x070, 0x5040);
  118. mmio_write_32(ETH_PHY_BASE + 0x074, 0x7060);
  119. // Set MLT3 +I
  120. mmio_write_32(ETH_PHY_BASE + 0x058, 0x1708);
  121. mmio_write_32(ETH_PHY_BASE + 0x05c, 0x3827);
  122. mmio_write_32(ETH_PHY_BASE + 0x060, 0x5748);
  123. mmio_write_32(ETH_PHY_BASE + 0x064, 0x7867);
  124. // Switch to MII-page17
  125. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x1100);
  126. // Set MLT3 Negative phase code, Set MLT3 -0
  127. mmio_write_32(ETH_PHY_BASE + 0x040, 0x9080);
  128. mmio_write_32(ETH_PHY_BASE + 0x044, 0xb0a0);
  129. mmio_write_32(ETH_PHY_BASE + 0x048, 0xd0c0);
  130. mmio_write_32(ETH_PHY_BASE + 0x04c, 0xf0e0);
  131. // Set MLT3 -I
  132. mmio_write_32(ETH_PHY_BASE + 0x050, 0x9788);
  133. mmio_write_32(ETH_PHY_BASE + 0x054, 0xb8a7);
  134. mmio_write_32(ETH_PHY_BASE + 0x058, 0xd7c8);
  135. mmio_write_32(ETH_PHY_BASE + 0x05c, 0xf8e7);
  136. // @Switch to MII-page5
  137. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0500);
  138. // En TX_Rterm
  139. mmio_write_32(ETH_PHY_BASE + 0x040, (0x0001 | mmio_read_32(ETH_PHY_BASE + 0x040)));
  140. // Link Pulse
  141. // Switch to MII-page10
  142. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0a00);
  143. // Set Link Pulse
  144. mmio_write_32(ETH_PHY_BASE + 0x040, 0x2000);
  145. mmio_write_32(ETH_PHY_BASE + 0x044, 0x3832);
  146. mmio_write_32(ETH_PHY_BASE + 0x048, 0x3132);
  147. mmio_write_32(ETH_PHY_BASE + 0x04c, 0x2d2f);
  148. mmio_write_32(ETH_PHY_BASE + 0x050, 0x2c2d);
  149. mmio_write_32(ETH_PHY_BASE + 0x054, 0x1b2b);
  150. mmio_write_32(ETH_PHY_BASE + 0x058, 0x94a0);
  151. mmio_write_32(ETH_PHY_BASE + 0x05c, 0x8990);
  152. mmio_write_32(ETH_PHY_BASE + 0x060, 0x8788);
  153. mmio_write_32(ETH_PHY_BASE + 0x064, 0x8485);
  154. mmio_write_32(ETH_PHY_BASE + 0x068, 0x8283);
  155. mmio_write_32(ETH_PHY_BASE + 0x06c, 0x8182);
  156. mmio_write_32(ETH_PHY_BASE + 0x070, 0x0081);
  157. // TP_IDLE
  158. // Switch to MII-page11
  159. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0b00);
  160. // Set TP_IDLE
  161. mmio_write_32(ETH_PHY_BASE + 0x040, 0x5252);
  162. mmio_write_32(ETH_PHY_BASE + 0x044, 0x5252);
  163. mmio_write_32(ETH_PHY_BASE + 0x048, 0x4B52);
  164. mmio_write_32(ETH_PHY_BASE + 0x04c, 0x3D47);
  165. mmio_write_32(ETH_PHY_BASE + 0x050, 0xAA99);
  166. mmio_write_32(ETH_PHY_BASE + 0x054, 0x989E);
  167. mmio_write_32(ETH_PHY_BASE + 0x058, 0x9395);
  168. mmio_write_32(ETH_PHY_BASE + 0x05C, 0x9091);
  169. mmio_write_32(ETH_PHY_BASE + 0x060, 0x8E8F);
  170. mmio_write_32(ETH_PHY_BASE + 0x064, 0x8D8E);
  171. mmio_write_32(ETH_PHY_BASE + 0x068, 0x8C8C);
  172. mmio_write_32(ETH_PHY_BASE + 0x06C, 0x8B8B);
  173. mmio_write_32(ETH_PHY_BASE + 0x070, 0x008A);
  174. // ETH 10BaseT Data
  175. // Switch to MII-page13
  176. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0d00);
  177. mmio_write_32(ETH_PHY_BASE + 0x040, 0x1E0A);
  178. mmio_write_32(ETH_PHY_BASE + 0x044, 0x3862);
  179. mmio_write_32(ETH_PHY_BASE + 0x048, 0x1E62);
  180. mmio_write_32(ETH_PHY_BASE + 0x04c, 0x2A08);
  181. mmio_write_32(ETH_PHY_BASE + 0x050, 0x244C);
  182. mmio_write_32(ETH_PHY_BASE + 0x054, 0x1A44);
  183. mmio_write_32(ETH_PHY_BASE + 0x058, 0x061C);
  184. // Switch to MII-page14
  185. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0e00);
  186. mmio_write_32(ETH_PHY_BASE + 0x040, 0x2D30);
  187. mmio_write_32(ETH_PHY_BASE + 0x044, 0x3470);
  188. mmio_write_32(ETH_PHY_BASE + 0x048, 0x0648);
  189. mmio_write_32(ETH_PHY_BASE + 0x04c, 0x261C);
  190. mmio_write_32(ETH_PHY_BASE + 0x050, 0x3160);
  191. mmio_write_32(ETH_PHY_BASE + 0x054, 0x2D5E);
  192. // Switch to MII-page15
  193. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0f00);
  194. mmio_write_32(ETH_PHY_BASE + 0x040, 0x2922);
  195. mmio_write_32(ETH_PHY_BASE + 0x044, 0x366E);
  196. mmio_write_32(ETH_PHY_BASE + 0x048, 0x0752);
  197. mmio_write_32(ETH_PHY_BASE + 0x04c, 0x2556);
  198. mmio_write_32(ETH_PHY_BASE + 0x050, 0x2348);
  199. mmio_write_32(ETH_PHY_BASE + 0x054, 0x0C30);
  200. // Switch to MII-page16
  201. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x1000);
  202. mmio_write_32(ETH_PHY_BASE + 0x040, 0x1E08);
  203. mmio_write_32(ETH_PHY_BASE + 0x044, 0x3868);
  204. mmio_write_32(ETH_PHY_BASE + 0x048, 0x1462);
  205. mmio_write_32(ETH_PHY_BASE + 0x04c, 0x1A0E);
  206. mmio_write_32(ETH_PHY_BASE + 0x050, 0x305E);
  207. mmio_write_32(ETH_PHY_BASE + 0x054, 0x2F62);
  208. // LED PAD MUX
  209. uintptr_t addr = (uintptr_t)DRV_IOREMAP((void *)0x03001000, 0x1000);
  210. mmio_write_32((uintptr_t)(addr + 0xe0), 0x05);
  211. mmio_write_32((uintptr_t)(addr + 0xe4), 0x05);
  212. //(SD1_CLK selphy)
  213. addr = (uintptr_t)DRV_IOREMAP((void *)0x05027000, 0x1000);
  214. mmio_write_32((intptr_t)(addr + 0xb0), 0x11111111);
  215. //(SD1_CMD selphy)
  216. mmio_write_32((intptr_t)(addr + 0xb4), 0x11111111);
  217. // LED
  218. // Switch to MII-page1
  219. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0100);
  220. // select LED_LNK/SPD/DPX out to LED_PAD
  221. mmio_write_32(ETH_PHY_BASE + 0x068, (mmio_read_32(ETH_PHY_BASE + 0x068) & ~0x0f00));
  222. // @Switch to MII-page0
  223. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0000);
  224. // PHY_ID
  225. mmio_write_32(ETH_PHY_BASE + 0x008, 0x0043);
  226. mmio_write_32(ETH_PHY_BASE + 0x00c, 0x5649);
  227. // Switch to MII-page19
  228. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x1300);
  229. mmio_write_32(ETH_PHY_BASE + 0x058, 0x0012);
  230. // set agc max/min swing
  231. mmio_write_32(ETH_PHY_BASE + 0x05C, 0x6848);
  232. // Switch to MII-page18
  233. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x1200);
  234. // p18.0x12, lpf
  235. mmio_write_32(ETH_PHY_BASE + 0x048, 0x0808);
  236. mmio_write_32(ETH_PHY_BASE + 0x04C, 0x0808);
  237. // hpf
  238. //sean
  239. mmio_write_32(ETH_PHY_BASE + 0x050, 0x32f8);
  240. mmio_write_32(ETH_PHY_BASE + 0x054, 0xf8dc);
  241. // Switch to MII-page0
  242. mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0000);
  243. // EPHY start auto-neg procedure
  244. mmio_write_32(ETH_PHY_BASE + 0x800, 0x090e);
  245. // switch to MDIO control by ETH_MAC
  246. mmio_write_32(ETH_PHY_BASE + 0x804, 0x0000);
  247. genphy_config(dev);
  248. #if defined(CVI_ETH_PHY_LOOPBACK)
  249. cv181x_set_phy_loopback(handle, LOOPBACK_PCS2MAC);
  250. #endif
  251. return 0;
  252. }
  253. /**
  254. \brief Parse 88E1xxx's speed and duplex from status register.
  255. \param[in] dev phy device pointer
  256. \return error code
  257. */
  258. static int32_t cv181x_parse_status(eth_phy_dev_t *dev)
  259. {
  260. assert(dev);
  261. assert(dev->priv);
  262. eth_phy_priv_t *priv = dev->priv;
  263. uint8_t phy_addr = dev->phy_addr;
  264. uint16_t mii_reg;
  265. int32_t ret;
  266. ret = eth_phy_read(priv, phy_addr, CVI_MII_BMSR, &mii_reg);
  267. if (ret != 0) {
  268. return ret;
  269. }
  270. if (mii_reg & (CVI_BMSR_100FULL | CVI_BMSR_100HALF))
  271. priv->link_info.speed = CSI_ETH_SPEED_100M;
  272. else
  273. priv->link_info.speed = CSI_ETH_SPEED_10M;
  274. if (mii_reg & (CVI_BMSR_10FULL | CVI_BMSR_100FULL))
  275. priv->link_info.duplex = CSI_ETH_DUPLEX_FULL;
  276. else
  277. priv->link_info.duplex = CSI_ETH_DUPLEX_HALF;
  278. return 0;
  279. }
  280. /**
  281. \brief Start up the 88E1111.
  282. \param[in] handle phy handle
  283. \return error code
  284. */
  285. int32_t cv181x_start(eth_phy_handle_t handle)
  286. {
  287. assert(handle);
  288. eth_phy_dev_t *dev = (eth_phy_dev_t *)handle;
  289. /* Read the Status (2x to make sure link is right) */
  290. genphy_update_link(dev);
  291. return cv181x_parse_status(dev);
  292. }
  293. /**
  294. \brief Halt the cv181x.
  295. \param[in] handle phy handle
  296. \return error code
  297. */
  298. int32_t cv181x_stop(eth_phy_handle_t handle)
  299. {
  300. return 0;
  301. }
  302. /**
  303. \brief Update the cv181x's link state.
  304. \param[in] handle phy handle
  305. \return error code
  306. */
  307. int32_t cv181x_update_link(eth_phy_handle_t handle)
  308. {
  309. assert(handle);
  310. eth_phy_dev_t *dev = (eth_phy_dev_t *)handle;
  311. return cv181x_parse_status(dev);;
  312. }
  313. /* Support for cv181x PHYs */
  314. eth_phy_dev_t cv181x_device = {
  315. .name = "CVITEK,CV181X",
  316. .phy_id = 0x00435649,
  317. .mask = 0xffffffff,
  318. .features = CVI_PHY_BASIC_FEATURES,
  319. .config = &cv181x_config,
  320. .start = &cv181x_start,
  321. .stop = &cv181x_stop,
  322. //.loopback = &cv181x_loopback,
  323. //.update_link = &cv181x_update_link,
  324. };