PageRenderTime 29ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/net/netarm_eth.c

https://github.com/CharlieWood/uboot-imx
C | 358 lines | 219 code | 59 blank | 80 comment | 34 complexity | ed1953fff5ae4534e01660d380dac726 MD5 | raw file
  1. /*
  2. * Copyright (C) 2004 IMMS gGmbH <www.imms.de>
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of
  7. * the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  17. * MA 02111-1307 USA
  18. *
  19. * author(s): Thomas Elste, <info@elste.org>
  20. * (some parts derived from uCLinux Netarm Ethernet Driver)
  21. */
  22. #include <common.h>
  23. #ifdef CONFIG_DRIVER_NETARMETH
  24. #include <command.h>
  25. #include <net.h>
  26. #include "netarm_eth.h"
  27. #include <asm/arch/netarm_registers.h>
  28. #if defined(CONFIG_CMD_NET)
  29. static int na_mii_poll_busy (void);
  30. static void na_get_mac_addr (void)
  31. {
  32. unsigned short p[3];
  33. char *m_addr;
  34. char ethaddr[20];
  35. m_addr = (char *) p;
  36. p[0] = (unsigned short) GET_EADDR (NETARM_ETH_SAL_STATION_ADDR_1);
  37. p[1] = (unsigned short) GET_EADDR (NETARM_ETH_SAL_STATION_ADDR_2);
  38. p[2] = (unsigned short) GET_EADDR (NETARM_ETH_SAL_STATION_ADDR_3);
  39. sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
  40. m_addr[0], m_addr[1],
  41. m_addr[2], m_addr[3], m_addr[4], m_addr[5]);
  42. printf ("HW-MAC Address: %s\n", ethaddr);
  43. /* set env, todo: check if already an adress is set */
  44. setenv ("ethaddr", ethaddr);
  45. }
  46. static void na_mii_write (int reg, int value)
  47. {
  48. int mii_addr;
  49. /* Select register */
  50. mii_addr = CFG_ETH_PHY_ADDR + reg;
  51. SET_EADDR (NETARM_ETH_MII_ADDR, mii_addr);
  52. /* Write value */
  53. SET_EADDR (NETARM_ETH_MII_WRITE, value);
  54. na_mii_poll_busy ();
  55. }
  56. static unsigned int na_mii_read (int reg)
  57. {
  58. int mii_addr, val;
  59. /* Select register */
  60. mii_addr = CFG_ETH_PHY_ADDR + reg;
  61. SET_EADDR (NETARM_ETH_MII_ADDR, mii_addr);
  62. /* do one management cycle */
  63. SET_EADDR (NETARM_ETH_MII_CMD,
  64. GET_EADDR (NETARM_ETH_MII_CMD) | NETARM_ETH_MIIC_RSTAT);
  65. na_mii_poll_busy ();
  66. /* Return read value */
  67. val = GET_EADDR (NETARM_ETH_MII_READ);
  68. return val;
  69. }
  70. static int na_mii_poll_busy (void)
  71. {
  72. /* arm simple, non interrupt dependent timer */
  73. reset_timer_masked ();
  74. while (get_timer_masked () < NA_MII_POLL_BUSY_DELAY) {
  75. if (!(GET_EADDR (NETARM_ETH_MII_IND) & NETARM_ETH_MIII_BUSY)) {
  76. return 1;
  77. }
  78. }
  79. printf ("na_mii_busy timeout\n");
  80. return (0);
  81. }
  82. static int na_mii_identify_phy (void)
  83. {
  84. int id_reg_a = 0;
  85. /* get phy id register */
  86. id_reg_a = na_mii_read (MII_PHY_ID);
  87. if (id_reg_a == 0x0043) {
  88. /* This must be an Enable or a Lucent LU3X31 PHY chip */
  89. return 1;
  90. } else if (id_reg_a == 0x0013) {
  91. /* it is an Intel LXT971A */
  92. return 1;
  93. }
  94. return (0);
  95. }
  96. static int na_mii_negotiate (void)
  97. {
  98. int i = 0;
  99. /* Enable auto-negotiation */
  100. na_mii_write (MII_PHY_AUTONEGADV, 0x01e1);
  101. /* FIXME: 0x01E1 is 100Mb half and full duplex, 0x0061 is 10Mb only */
  102. /* Restart auto-negotiation */
  103. na_mii_write (MII_PHY_CONTROL, 0x1200);
  104. /* status register is 0xffff after setting the autoneg restart bit */
  105. while (na_mii_read (MII_PHY_STATUS) == 0xffff) {
  106. i++;
  107. }
  108. /* na_mii_read uses the timer already, so we can't use it again for
  109. timeout checking.
  110. Instead we just try some times.
  111. */
  112. for (i = 0; i < 40000; i++) {
  113. if ((na_mii_read (MII_PHY_STATUS) & 0x0024) == 0x0024) {
  114. return 0;
  115. }
  116. }
  117. /*
  118. printf("*Warning* autonegotiation timeout, status: 0x%x\n",na_mii_read(MII_PHY_STATUS));
  119. */
  120. return (1);
  121. }
  122. static unsigned int na_mii_check_speed (void)
  123. {
  124. unsigned int status;
  125. /* Read Status register */
  126. status = na_mii_read (MII_PHY_STATUS);
  127. /* Check link status. If 0, default to 100 Mbps. */
  128. if ((status & 0x0004) == 0) {
  129. printf ("*Warning* no link detected, set default speed to 100Mbs\n");
  130. return 1;
  131. } else {
  132. if ((na_mii_read (17) & 0x4000) != 0) {
  133. printf ("100Mbs link detected\n");
  134. return 1;
  135. } else {
  136. printf ("10Mbs link detected\n");
  137. return 0;
  138. }
  139. }
  140. return 0;
  141. }
  142. static int reset_eth (void)
  143. {
  144. int pt;
  145. na_get_mac_addr ();
  146. pt = na_mii_identify_phy ();
  147. /* reset the phy */
  148. na_mii_write (MII_PHY_CONTROL, 0x8000);
  149. reset_timer_masked ();
  150. while (get_timer_masked () < NA_MII_NEGOTIATE_DELAY) {
  151. if ((na_mii_read (MII_PHY_STATUS) & 0x8000) == 0) {
  152. break;
  153. }
  154. }
  155. if (get_timer_masked () >= NA_MII_NEGOTIATE_DELAY)
  156. printf ("phy reset timeout\n");
  157. /* set the PCS reg */
  158. SET_EADDR (NETARM_ETH_PCS_CFG, NETARM_ETH_PCSC_CLKS_25M |
  159. NETARM_ETH_PCSC_ENJAB | NETARM_ETH_PCSC_NOCFR);
  160. na_mii_negotiate ();
  161. na_mii_check_speed ();
  162. /* Delay 10 millisecond. (Maybe this should be 1 second.) */
  163. udelay (10000);
  164. /* Turn receive on.
  165. Enable statistics register autozero on read.
  166. Do not insert MAC address on transmit.
  167. Do not enable special test modes. */
  168. SET_EADDR (NETARM_ETH_STL_CFG,
  169. (NETARM_ETH_STLC_AUTOZ | NETARM_ETH_STLC_RXEN));
  170. /* Set the inter-packet gap delay to 0.96us for MII.
  171. The NET+ARM H/W Reference Guide indicates that the Back-to-back IPG
  172. Gap Timer Register should be set to 0x15 and the Non Back-to-back IPG
  173. Gap Timer Register should be set to 0x00000C12 for the MII PHY. */
  174. SET_EADDR (NETARM_ETH_B2B_IPG_GAP_TMR, 0x15);
  175. SET_EADDR (NETARM_ETH_NB2B_IPG_GAP_TMR, 0x00000C12);
  176. /* Add CRC to end of packets.
  177. Pad packets to minimum length of 64 bytes.
  178. Allow unlimited length transmit packets.
  179. Receive all broadcast packets.
  180. NOTE: Multicast addressing is NOT enabled here currently. */
  181. SET_EADDR (NETARM_ETH_MAC_CFG,
  182. (NETARM_ETH_MACC_CRCEN |
  183. NETARM_ETH_MACC_PADEN | NETARM_ETH_MACC_HUGEN));
  184. SET_EADDR (NETARM_ETH_SAL_FILTER, NETARM_ETH_SALF_BROAD);
  185. /* enable fifos */
  186. SET_EADDR (NETARM_ETH_GEN_CTRL,
  187. (NETARM_ETH_GCR_ERX | NETARM_ETH_GCR_ETX));
  188. return (0);
  189. }
  190. extern int eth_init (bd_t * bd)
  191. {
  192. reset_eth ();
  193. return 0;
  194. }
  195. extern void eth_halt (void)
  196. {
  197. SET_EADDR (NETARM_ETH_GEN_CTRL, 0);
  198. }
  199. /* Get a data block via Ethernet */
  200. extern int eth_rx (void)
  201. {
  202. int i;
  203. unsigned short rxlen;
  204. unsigned int *addr;
  205. unsigned int rxstatus, lastrxlen;
  206. char *pa;
  207. /* RXBR is 1, data block was received */
  208. if ((GET_EADDR (NETARM_ETH_GEN_STAT) & NETARM_ETH_GST_RXBR) == 0)
  209. return 0;
  210. /* get status register and the length of received block */
  211. rxstatus = GET_EADDR (NETARM_ETH_RX_STAT);
  212. rxlen = (rxstatus & NETARM_ETH_RXSTAT_SIZE) >> 16;
  213. if (rxlen == 0)
  214. return 0;
  215. /* clear RXBR to make fifo available */
  216. SET_EADDR (NETARM_ETH_GEN_STAT,
  217. GET_EADDR (NETARM_ETH_GEN_STAT) & ~NETARM_ETH_GST_RXBR);
  218. /* clear TXBC to make fifo available */
  219. /* According to NETARM50 data manual you just have to clear
  220. RXBR but that has no effect. Only after clearing TXBC the
  221. Fifo becomes readable. */
  222. SET_EADDR (NETARM_ETH_GEN_STAT,
  223. GET_EADDR (NETARM_ETH_GEN_STAT) & ~NETARM_ETH_GST_TXBC);
  224. addr = (unsigned int *) NetRxPackets[0];
  225. pa = (char *) NetRxPackets[0];
  226. /* read the fifo */
  227. for (i = 0; i < rxlen / 4; i++) {
  228. *addr = GET_EADDR (NETARM_ETH_FIFO_DAT1);
  229. addr++;
  230. }
  231. if (GET_EADDR (NETARM_ETH_GEN_STAT) & NETARM_ETH_GST_RXREGR) {
  232. /* RXFDB indicates wether the last word is 1,2,3 or 4 bytes long */
  233. lastrxlen =
  234. (GET_EADDR (NETARM_ETH_GEN_STAT) &
  235. NETARM_ETH_GST_RXFDB) >> 28;
  236. *addr = GET_EADDR (NETARM_ETH_FIFO_DAT1);
  237. switch (lastrxlen) {
  238. case 1:
  239. *addr &= 0xff000000;
  240. break;
  241. case 2:
  242. *addr &= 0xffff0000;
  243. break;
  244. case 3:
  245. *addr &= 0xffffff00;
  246. break;
  247. }
  248. }
  249. /* Pass the packet up to the protocol layers. */
  250. NetReceive (NetRxPackets[0], rxlen);
  251. return rxlen;
  252. }
  253. /* Send a data block via Ethernet. */
  254. extern int eth_send (volatile void *packet, int length)
  255. {
  256. int i, length32;
  257. char *pa;
  258. unsigned int *pa32, lastp = 0, rest;
  259. pa = (char *) packet;
  260. pa32 = (unsigned int *) packet;
  261. length32 = length / 4;
  262. rest = length % 4;
  263. /* make sure there's no garbage in the last word */
  264. switch (rest) {
  265. case 0:
  266. lastp = pa32[length32];
  267. length32--;
  268. break;
  269. case 1:
  270. lastp = pa32[length32] & 0x000000ff;
  271. break;
  272. case 2:
  273. lastp = pa32[length32] & 0x0000ffff;
  274. break;
  275. case 3:
  276. lastp = pa32[length32] & 0x00ffffff;
  277. break;
  278. }
  279. /* write to the fifo */
  280. for (i = 0; i < length32; i++)
  281. SET_EADDR (NETARM_ETH_FIFO_DAT1, pa32[i]);
  282. /* the last word is written to an extra register, this
  283. starts the transmission */
  284. SET_EADDR (NETARM_ETH_FIFO_DAT2, lastp);
  285. /* NETARM_ETH_TXSTAT_TXOK should be checked, to know if the transmission
  286. went fine. But we can't use the timer for a timeout loop because
  287. of it is used already in upper layers. So we just try some times. */
  288. i = 0;
  289. while (i < 50000) {
  290. if ((GET_EADDR (NETARM_ETH_TX_STAT) & NETARM_ETH_TXSTAT_TXOK)
  291. == NETARM_ETH_TXSTAT_TXOK)
  292. return 0;
  293. i++;
  294. }
  295. printf ("eth_send timeout\n");
  296. return 1;
  297. }
  298. #endif /* CONFIG_CMD_NET */
  299. #endif /* CONFIG_DRIVER_NETARMETH */