hal_geth_utils.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /*
  2. * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
  3. *
  4. * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
  5. * the the People's Republic of China and other countries.
  6. * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
  7. *
  8. * DISCLAIMER
  9. * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
  10. * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
  11. * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
  12. * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
  13. * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
  14. * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
  15. * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
  16. *
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
  19. * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
  20. * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
  21. * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
  22. * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  23. * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  28. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  30. * OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. #include <sunxi_hal_geth.h>
  33. void random_ether_addr(uint8_t *addr)
  34. {
  35. uint32_t sid3;
  36. /*
  37. * F133 chipid the start address is located at 0x03006200.
  38. * SID total of 128bits,the offset 0x0c is variable.
  39. */
  40. sid3 = hal_readl(0x03006200 + 0xc);
  41. /*
  42. * DC-44-6D from ieee official licensed to Allwinner.
  43. * on here, for testing purposes only.
  44. */
  45. addr[0] = 0xDC;
  46. addr[1] = 0x44;
  47. addr[2] = 0x6D;
  48. addr[3] = sid3 & 0xFFu;
  49. addr[4] = (sid3 >> 8) & 0xFFu;
  50. addr[5] = (sid3 >> 16) & 0xFFu;
  51. }
  52. void geth_set_link_mode(unsigned long iobase, int duplex, int speed)
  53. {
  54. uint32_t value;
  55. value = hal_readl(iobase + GETH_BASIC_CTL0);
  56. if (!duplex)
  57. value &= ~CTL0_DM;
  58. else
  59. value |= CTL0_DM;
  60. switch (speed) {
  61. case 1000:
  62. value &= ~0x0C;
  63. break;
  64. case 100:
  65. case 10:
  66. default:
  67. value |= 0x08;
  68. if (speed == 100)
  69. value |= 0x04;
  70. else
  71. value &= ~0x04;
  72. break;
  73. }
  74. hal_writel(value, iobase + GETH_BASIC_CTL0);
  75. }
  76. void geth_mac_loopback(unsigned long iobase, int enable)
  77. {
  78. uint32_t value;
  79. value = hal_readl(iobase + GETH_BASIC_CTL0);
  80. if (enable)
  81. value |= 0x02;
  82. else
  83. value &= ~0x02;
  84. hal_writel(value, iobase + GETH_BASIC_CTL0);
  85. }
  86. void geth_start_tx(unsigned long iobase)
  87. {
  88. uint32_t value;
  89. value = hal_readl(iobase + GETH_TX_CTL1);
  90. value |= (1 << 30);
  91. hal_writel(value, iobase + GETH_TX_CTL1);
  92. }
  93. void geth_stop_tx(unsigned long iobase)
  94. {
  95. uint32_t value;
  96. value = hal_readl(iobase + GETH_TX_CTL1);
  97. value &= ~(1 << 30);
  98. hal_writel(value, iobase + GETH_TX_CTL1);
  99. }
  100. void geth_start_rx(unsigned long iobase)
  101. {
  102. uint32_t value;
  103. value = hal_readl(iobase + GETH_RX_CTL1);
  104. value |= (1 << 30);
  105. hal_writel(value, iobase + GETH_RX_CTL1);
  106. }
  107. void geth_stop_rx(unsigned long iobase)
  108. {
  109. uint32_t value;
  110. value = hal_readl(iobase + GETH_RX_CTL1);
  111. value &= ~(1 << 30);
  112. hal_writel(value, iobase + GETH_RX_CTL1);
  113. }
  114. void geth_loopback_enable(unsigned long iobase)
  115. {
  116. uint32_t value;
  117. value = hal_readl(iobase + GETH_BASIC_CTL0);
  118. value |= (1 << 0);
  119. hal_writel(value, iobase + GETH_BASIC_CTL0);
  120. }
  121. void geth_loopback_disable(unsigned long iobase)
  122. {
  123. uint32_t value;
  124. value = hal_readl(iobase + GETH_BASIC_CTL0);
  125. value &= ~(1 << 0);
  126. hal_writel(value, iobase + GETH_BASIC_CTL0);
  127. }
  128. uint32_t geth_mac_reset(unsigned long iobase)
  129. {
  130. uint32_t value;
  131. /* Soft reset all registers and logic */
  132. value = hal_readl(iobase + GETH_BASIC_CTL1);
  133. value |= SOFT_RST;
  134. hal_writel(value, iobase + GETH_BASIC_CTL1);
  135. while(value)
  136. {
  137. rt_thread_delay(10);
  138. value = (hal_readl(iobase + GETH_BASIC_CTL1) & SOFT_RST);
  139. }
  140. return !!value;
  141. }
  142. void geth_mac_init(unsigned long iobase)
  143. {
  144. uint32_t value;
  145. value = hal_readl(iobase + GETH_TX_CTL1);
  146. /* Transmit COE type 2 cannot be done in cut-through mode. */
  147. value |= TX_MD;
  148. hal_writel(value, iobase + GETH_TX_CTL1);
  149. value = hal_readl(iobase + GETH_RX_CTL0);
  150. hal_writel((0x3 << 20), iobase + GETH_MDIO_ADDR); /* MDC_DIV_RATIO */
  151. value = hal_readl(iobase + GETH_RX_CTL1);
  152. value |= RX_MD;
  153. /* Forward frames with error and undersized good frame. */
  154. value |= (RX_ERR_FRM | RX_RUNT_FRM );
  155. hal_writel(value, iobase + GETH_RX_CTL1);
  156. }
  157. void geth_set_filter(unsigned long iobase)
  158. {
  159. uint32_t value;
  160. value = hal_readl(iobase + GETH_RX_FRM_FLT);
  161. value |= 0x1;
  162. hal_writel(value, iobase + GETH_RX_FRM_FLT);
  163. }
  164. void geth_set_mac_addr(unsigned long iobase, unsigned char *addr, int index)
  165. {
  166. uint32_t value;
  167. value = (addr[5] << 8) | addr[4];
  168. hal_writel(value, iobase + GETH_ADDR_HI(index));
  169. value = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
  170. hal_writel(value, iobase + GETH_ADDR_LO(index));
  171. }
  172. void geth_mac_enable(unsigned long iobase)
  173. {
  174. uint32_t value;
  175. value = hal_readl(iobase + GETH_TX_CTL0);
  176. value |= (1 << 31);
  177. hal_writel(value, iobase + GETH_TX_CTL0);
  178. value = hal_readl(iobase + GETH_RX_CTL0);
  179. value |= (1 << 31);
  180. hal_writel(value, iobase + GETH_RX_CTL0);
  181. }
  182. void geth_mac_disable(unsigned long iobase)
  183. {
  184. uint32_t value;
  185. value = hal_readl(iobase + GETH_TX_CTL0);
  186. value &= ~(1 << 31);
  187. hal_writel(value, iobase + GETH_TX_CTL0);
  188. value = hal_readl(iobase + GETH_RX_CTL0);
  189. value &= ~(1 << 31);
  190. hal_writel(value, iobase + GETH_RX_CTL0);
  191. }
  192. void geth_tx_poll(unsigned long iobase)
  193. {
  194. uint32_t value;
  195. value = hal_readl(iobase + GETH_TX_CTL1);
  196. value |= (1 << 31);
  197. hal_writel(value, iobase + GETH_TX_CTL1);
  198. }
  199. void geth_rx_poll(unsigned long iobase)
  200. {
  201. uint32_t value;
  202. value = hal_readl(iobase + GETH_RX_CTL1);
  203. value |= (1 << 31);
  204. hal_writel(value, iobase + GETH_RX_CTL1);
  205. }
  206. void geth_flush_tx(unsigned long iobase)
  207. {
  208. uint32_t value;
  209. value = hal_readl(iobase + GETH_TX_CTL1);
  210. value |= 0x1;
  211. hal_writel(value, iobase + GETH_TX_CTL1);
  212. }
  213. void geth_rx_int_enable(unsigned long iobase)
  214. {
  215. uint32_t value = 0;
  216. value |= RX_INT;
  217. hal_writel(value , iobase + GETH_INT_EN);
  218. }
  219. void geth_tx_int_enable(unsigned long iobase)
  220. {
  221. uint32_t value = 0;
  222. value |= (TX_INT | TX_STOP_INT | TX_UA_INT | TX_TOUT_INT | TX_UNF_INT);
  223. hal_writel(value, iobase + GETH_INT_EN);
  224. }
  225. void geth_rx_int_disable(unsigned long iobase)
  226. {
  227. uint32_t value = 0;
  228. value = hal_readl(iobase + GETH_INT_EN);
  229. value &= ~RX_INT;
  230. hal_writel(value , iobase + GETH_INT_EN);}
  231. void geth_tx_int_disable(unsigned long iobase)
  232. {
  233. uint32_t value = 0;
  234. value = hal_readl(iobase + GETH_INT_EN);
  235. value &= ~TX_INT;
  236. hal_writel(value, iobase + GETH_INT_EN);
  237. }
  238. void geth_all_int_disable(unsigned long iobase)
  239. {
  240. hal_writel(0, iobase + GETH_INT_EN);
  241. }
  242. void geth_clk_enable(uint32_t used_type,uint32_t phy_interface,uint32_t tx_delay,uint32_t rx_delay)
  243. {
  244. uint32_t value;
  245. uint32_t reg_val;
  246. /* Enalbe clk for gmac */
  247. value = hal_readl(CCMU_BASE + CCMU_GETH_CLK_REG);
  248. value |= (1 << CCMU_GETH_RST_BIT);
  249. value |= (1 << CCMU_GETH_GATING_BIT);
  250. hal_writel(value, CCMU_BASE + CCMU_GETH_CLK_REG);
  251. /* Enable clk for ephy */
  252. #ifdef USE_EPHY25M
  253. value = hal_readl(CCMU_BASE + CCMU_EPHY_CLK_REG);
  254. value |= (1 << CCMU_EPHY_PLL_PERI0_GATING_BIT);
  255. value |= (1 << CCMU_EPHY_SCLK_GATING_BIT);
  256. hal_writel(value, CCMU_BASE + CCMU_EPHY_CLK_REG);
  257. #endif
  258. /* Set phy clock */
  259. value = hal_readl(PHY_CLK_REG);
  260. if (used_type == INT_PHY){
  261. reg_val = hal_readl(CCMU_BASE + 0x0070);
  262. reg_val |= (1 << 0);
  263. hal_writel(reg_val, CCMU_BASE + 0x0070);
  264. reg_val = hal_readl(CCMU_BASE + 0x02c8);
  265. reg_val |= (1 << 2);
  266. hal_writel(reg_val, CCMU_BASE + 0x02c8);
  267. value |= (1 << 15);
  268. value &= ~(1 << 16);
  269. value |= (3 << 17);
  270. } else {
  271. value &= ~(1 << 15);
  272. value |= (1 << 16);
  273. }
  274. if (phy_interface == PHY_INTERFACE_MODE_RGMII) {
  275. value |= 0x00000004;
  276. } else {
  277. value &= ~0x00000004;
  278. }
  279. value &= ~0x00002003;
  280. if (phy_interface == PHY_INTERFACE_MODE_RGMII
  281. || phy_interface == PHY_INTERFACE_MODE_GMII) {
  282. value |= 0x00000002;
  283. } else if (phy_interface == PHY_INTERFACE_MODE_RMII) {
  284. value |= 0x00002001;
  285. }
  286. /* Adjust Tx/Rx clock delay */
  287. value &= ~(0x07 << 10);
  288. value |= ((tx_delay & 0x07) << 10);
  289. value &= ~(0x1f << 5);
  290. value |= ((rx_delay & 0x1f) << 5);
  291. hal_writel(value, PHY_CLK_REG);
  292. }
  293. void geth_clk_disable(void)
  294. {
  295. uint32_t value;
  296. /* Disalbe clk for gmac */
  297. value = hal_readl(CCMU_BASE + CCMU_GETH_CLK_REG);
  298. value &= ~(1 << CCMU_GETH_RST_BIT);
  299. value &= ~(1 << CCMU_GETH_GATING_BIT);
  300. hal_writel(value, CCMU_BASE + CCMU_GETH_CLK_REG);
  301. /* Disable clk for ephy */
  302. #ifdef USE_EPHY25M
  303. value = hal_readl(CCMU_BASE + CCMU_EPHY_CLK_REG);
  304. value &= ~(1 << CCMU_EPHY_PLL_PERI0_GATING_BIT);
  305. value &= ~(1 << CCMU_EPHY_SCLK_GATING_BIT);
  306. hal_writel(value, CCMU_BASE + CCMU_EPHY_CLK_REG);
  307. #endif
  308. }
  309. uint32_t geth_mdio_read(unsigned long iobase, int phy_addr, u8 reg)
  310. {
  311. uint32_t value = 0;
  312. value |= (0x06 << 20);
  313. value |= (((phy_addr << 12) & (0x0001F000)) |
  314. ((reg << 4) & (0x000007F0)) |
  315. MII_BUSY);
  316. hal_writel(value, iobase + GETH_MDIO_ADDR);
  317. while (hal_readl(iobase + GETH_MDIO_ADDR) & MII_BUSY)
  318. ;
  319. return (uint32_t)hal_readl(iobase + GETH_MDIO_DATA);
  320. }
  321. uint32_t geth_mdio_write(unsigned long iobase, int phy_addr, u8 reg, u16 data)
  322. {
  323. uint32_t value = 0;
  324. value |= (0x06 << 20);
  325. value |= (((phy_addr << 12) & (0x0001F000)) |
  326. ((reg << 4) & (0x000007F0)) |
  327. MII_WRITE | MII_BUSY);
  328. /* Set the MII address register to write */
  329. hal_writel(data, iobase + GETH_MDIO_DATA);
  330. hal_writel(value, iobase + GETH_MDIO_ADDR);
  331. /* Wait until any existing MII operation is complete */
  332. while (hal_readl(iobase + GETH_MDIO_ADDR) & MII_BUSY)
  333. ;
  334. return 0;
  335. }