at91rm9200_ether.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*
  2. * (C) Copyright 2003
  3. * Author : Hamid Ikdoumi (Atmel)
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <at91rm9200_net.h>
  24. #include <net.h>
  25. /* ----- Ethernet Buffer definitions ----- */
  26. typedef struct {
  27. unsigned long addr, size;
  28. } rbf_t;
  29. #define RBF_ADDR 0xfffffffc
  30. #define RBF_OWNER (1<<0)
  31. #define RBF_WRAP (1<<1)
  32. #define RBF_BROADCAST (1<<31)
  33. #define RBF_MULTICAST (1<<30)
  34. #define RBF_UNICAST (1<<29)
  35. #define RBF_EXTERNAL (1<<28)
  36. #define RBF_UNKOWN (1<<27)
  37. #define RBF_SIZE 0x07ff
  38. #define RBF_LOCAL4 (1<<26)
  39. #define RBF_LOCAL3 (1<<25)
  40. #define RBF_LOCAL2 (1<<24)
  41. #define RBF_LOCAL1 (1<<23)
  42. /* Emac Buffers in last 512KBytes of SDRAM*/
  43. /* Be careful, buffer size is limited to 512KBytes !!! */
  44. #define RBF_FRAMEMAX 100
  45. /*#define RBF_FRAMEMEM 0x200000 */
  46. #define RBF_FRAMEMEM 0x21F80000
  47. #define RBF_FRAMELEN 0x600
  48. #define RBF_FRAMEBTD RBF_FRAMEMEM
  49. #define RBF_FRAMEBUF (RBF_FRAMEMEM + RBF_FRAMEMAX*sizeof(rbf_t))
  50. #ifdef CONFIG_DRIVER_ETHER
  51. #if (CONFIG_COMMANDS & CFG_CMD_NET)
  52. /* structure to interface the PHY */
  53. AT91S_PhyOps AT91S_Dm9161Ops;
  54. AT91PS_PhyOps pPhyOps;
  55. AT91PS_EMAC p_mac;
  56. /*************************** Phy layer functions ************************/
  57. /** functions to interface the DAVICOM 10/100Mbps ethernet phy **********/
  58. /*
  59. * Name:
  60. * dm9161_IsPhyConnected
  61. * Description:
  62. * Reads the 2 PHY ID registers
  63. * Arguments:
  64. * p_mac - pointer to AT91S_EMAC struct
  65. * Return value:
  66. * TRUE - if id read successfully
  67. * FALSE- if error
  68. */
  69. static unsigned int dm9161_IsPhyConnected (AT91PS_EMAC p_mac)
  70. {
  71. unsigned short Id1, Id2;
  72. at91rm9200_EmacEnableMDIO (p_mac);
  73. at91rm9200_EmacReadPhy (p_mac, DM9161_PHYID1, &Id1);
  74. at91rm9200_EmacReadPhy (p_mac, DM9161_PHYID2, &Id2);
  75. at91rm9200_EmacDisableMDIO (p_mac);
  76. if ((Id1 == (DM9161_PHYID1_OUI >> 6)) &&
  77. ((Id2 >> 10) == (DM9161_PHYID1_OUI & DM9161_LSB_MASK)))
  78. return TRUE;
  79. return FALSE;
  80. }
  81. /*
  82. * Name:
  83. * dm9161_GetLinkSpeed
  84. * Description:
  85. * Link parallel detection status of MAC is checked and set in the
  86. * MAC configuration registers
  87. * Arguments:
  88. * p_mac - pointer to MAC
  89. * Return value:
  90. * TRUE - if link status set succesfully
  91. * FALSE - if link status not set
  92. */
  93. static UCHAR dm9161_GetLinkSpeed (AT91PS_EMAC p_mac)
  94. {
  95. unsigned short stat1, stat2;
  96. if (!at91rm9200_EmacReadPhy (p_mac, DM9161_BMSR, &stat1))
  97. return FALSE;
  98. if (!(stat1 & DM9161_LINK_STATUS)) /* link status up? */
  99. return FALSE;
  100. if (!at91rm9200_EmacReadPhy (p_mac, DM9161_DSCSR, &stat2))
  101. return FALSE;
  102. if ((stat1 & DM9161_100BASE_TX_FD) && (stat2 & DM9161_100FDX)) {
  103. /*set Emac for 100BaseTX and Full Duplex */
  104. p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
  105. return TRUE;
  106. }
  107. if ((stat1 & DM9161_10BASE_T_FD) && (stat2 & DM9161_10FDX)) {
  108. /*set MII for 10BaseT and Full Duplex */
  109. p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
  110. ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
  111. | AT91C_EMAC_FD;
  112. return TRUE;
  113. }
  114. if ((stat1 & DM9161_100BASE_T4_HD) && (stat2 & DM9161_100HDX)) {
  115. /*set MII for 100BaseTX and Half Duplex */
  116. p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
  117. ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
  118. | AT91C_EMAC_SPD;
  119. return TRUE;
  120. }
  121. if ((stat1 & DM9161_10BASE_T_HD) && (stat2 & DM9161_10HDX)) {
  122. /*set MII for 10BaseT and Half Duplex */
  123. p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
  124. return TRUE;
  125. }
  126. return FALSE;
  127. }
  128. /*
  129. * Name:
  130. * dm9161_InitPhy
  131. * Description:
  132. * MAC starts checking its link by using parallel detection and
  133. * Autonegotiation and the same is set in the MAC configuration registers
  134. * Arguments:
  135. * p_mac - pointer to struct AT91S_EMAC
  136. * Return value:
  137. * TRUE - if link status set succesfully
  138. * FALSE - if link status not set
  139. */
  140. static UCHAR dm9161_InitPhy (AT91PS_EMAC p_mac)
  141. {
  142. UCHAR ret = TRUE;
  143. unsigned short IntValue;
  144. at91rm9200_EmacEnableMDIO (p_mac);
  145. if (!dm9161_GetLinkSpeed (p_mac)) {
  146. /* Try another time */
  147. ret = dm9161_GetLinkSpeed (p_mac);
  148. }
  149. /* Disable PHY Interrupts */
  150. at91rm9200_EmacReadPhy (p_mac, DM9161_MDINTR, &IntValue);
  151. /* clear FDX, SPD, Link, INTR masks */
  152. IntValue &= ~(DM9161_FDX_MASK | DM9161_SPD_MASK |
  153. DM9161_LINK_MASK | DM9161_INTR_MASK);
  154. at91rm9200_EmacWritePhy (p_mac, DM9161_MDINTR, &IntValue);
  155. at91rm9200_EmacDisableMDIO (p_mac);
  156. return (ret);
  157. }
  158. /*
  159. * Name:
  160. * dm9161_AutoNegotiate
  161. * Description:
  162. * MAC Autonegotiates with the partner status of same is set in the
  163. * MAC configuration registers
  164. * Arguments:
  165. * dev - pointer to struct net_device
  166. * Return value:
  167. * TRUE - if link status set successfully
  168. * FALSE - if link status not set
  169. */
  170. static UCHAR dm9161_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
  171. {
  172. unsigned short value;
  173. unsigned short PhyAnar;
  174. unsigned short PhyAnalpar;
  175. /* Set dm9161 control register */
  176. if (!at91rm9200_EmacReadPhy (p_mac, DM9161_BMCR, &value))
  177. return FALSE;
  178. value &= ~DM9161_AUTONEG; /* remove autonegotiation enable */
  179. value |= DM9161_ISOLATE; /* Electrically isolate PHY */
  180. if (!at91rm9200_EmacWritePhy (p_mac, DM9161_BMCR, &value))
  181. return FALSE;
  182. /* Set the Auto_negotiation Advertisement Register */
  183. /* MII advertising for Next page, 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 */
  184. PhyAnar = DM9161_NP | DM9161_TX_FDX | DM9161_TX_HDX |
  185. DM9161_10_FDX | DM9161_10_HDX | DM9161_AN_IEEE_802_3;
  186. if (!at91rm9200_EmacWritePhy (p_mac, DM9161_ANAR, &PhyAnar))
  187. return FALSE;
  188. /* Read the Control Register */
  189. if (!at91rm9200_EmacReadPhy (p_mac, DM9161_BMCR, &value))
  190. return FALSE;
  191. value |= DM9161_SPEED_SELECT | DM9161_AUTONEG | DM9161_DUPLEX_MODE;
  192. if (!at91rm9200_EmacWritePhy (p_mac, DM9161_BMCR, &value))
  193. return FALSE;
  194. /* Restart Auto_negotiation */
  195. value |= DM9161_RESTART_AUTONEG;
  196. if (!at91rm9200_EmacWritePhy (p_mac, DM9161_BMCR, &value))
  197. return FALSE;
  198. /*check AutoNegotiate complete */
  199. udelay (10000);
  200. at91rm9200_EmacReadPhy (p_mac, DM9161_BMSR, &value);
  201. if (!(value & DM9161_AUTONEG_COMP))
  202. return FALSE;
  203. /* Get the AutoNeg Link partner base page */
  204. if (!at91rm9200_EmacReadPhy (p_mac, DM9161_ANLPAR, &PhyAnalpar))
  205. return FALSE;
  206. if ((PhyAnar & DM9161_TX_FDX) && (PhyAnalpar & DM9161_TX_FDX)) {
  207. /*set MII for 100BaseTX and Full Duplex */
  208. p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
  209. return TRUE;
  210. }
  211. if ((PhyAnar & DM9161_10_FDX) && (PhyAnalpar & DM9161_10_FDX)) {
  212. /*set MII for 10BaseT and Full Duplex */
  213. p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
  214. ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
  215. | AT91C_EMAC_FD;
  216. return TRUE;
  217. }
  218. return FALSE;
  219. }
  220. /*********** EMAC Phy layer Management functions *************************/
  221. /*
  222. * Name:
  223. * at91rm9200_EmacEnableMDIO
  224. * Description:
  225. * Enables the MDIO bit in MAC control register
  226. * Arguments:
  227. * p_mac - pointer to struct AT91S_EMAC
  228. * Return value:
  229. * none
  230. */
  231. static void at91rm9200_EmacEnableMDIO (AT91PS_EMAC p_mac)
  232. {
  233. /* Mac CTRL reg set for MDIO enable */
  234. p_mac->EMAC_CTL |= AT91C_EMAC_MPE; /* Management port enable */
  235. }
  236. /*
  237. * Name:
  238. * at91rm9200_EmacDisableMDIO
  239. * Description:
  240. * Disables the MDIO bit in MAC control register
  241. * Arguments:
  242. * p_mac - pointer to struct AT91S_EMAC
  243. * Return value:
  244. * none
  245. */
  246. static void at91rm9200_EmacDisableMDIO (AT91PS_EMAC p_mac)
  247. {
  248. /* Mac CTRL reg set for MDIO disable */
  249. p_mac->EMAC_CTL &= ~AT91C_EMAC_MPE; /* Management port disable */
  250. }
  251. /*
  252. * Name:
  253. * at91rm9200_EmacReadPhy
  254. * Description:
  255. * Reads data from the PHY register
  256. * Arguments:
  257. * dev - pointer to struct net_device
  258. * RegisterAddress - unsigned char
  259. * pInput - pointer to value read from register
  260. * Return value:
  261. * TRUE - if data read successfully
  262. */
  263. static UCHAR at91rm9200_EmacReadPhy (AT91PS_EMAC p_mac,
  264. unsigned char RegisterAddress,
  265. unsigned short *pInput)
  266. {
  267. p_mac->EMAC_MAN = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) |
  268. (AT91C_EMAC_RW_R) |
  269. (RegisterAddress << 18) |
  270. (AT91C_EMAC_CODE_802_3);
  271. udelay (10000);
  272. *pInput = (unsigned short) p_mac->EMAC_MAN;
  273. return TRUE;
  274. }
  275. /*
  276. * Name:
  277. * at91rm9200_EmacWritePhy
  278. * Description:
  279. * Writes data to the PHY register
  280. * Arguments:
  281. * dev - pointer to struct net_device
  282. * RegisterAddress - unsigned char
  283. * pOutput - pointer to value to be written in the register
  284. * Return value:
  285. * TRUE - if data read successfully
  286. */
  287. static UCHAR at91rm9200_EmacWritePhy (AT91PS_EMAC p_mac,
  288. unsigned char RegisterAddress,
  289. unsigned short *pOutput)
  290. {
  291. p_mac->EMAC_MAN = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) |
  292. AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W |
  293. (RegisterAddress << 18) | *pOutput;
  294. udelay (10000);
  295. return TRUE;
  296. }
  297. /*
  298. * Name:
  299. * at91rm92000_GetPhyInterface
  300. * Description:
  301. * Initialise the interface functions to the PHY
  302. * Arguments:
  303. * None
  304. * Return value:
  305. * None
  306. */
  307. void at91rm92000_GetPhyInterface (void)
  308. {
  309. AT91S_Dm9161Ops.Init = dm9161_InitPhy;
  310. AT91S_Dm9161Ops.IsPhyConnected = dm9161_IsPhyConnected;
  311. AT91S_Dm9161Ops.GetLinkSpeed = dm9161_GetLinkSpeed;
  312. AT91S_Dm9161Ops.AutoNegotiate = dm9161_AutoNegotiate;
  313. pPhyOps = (AT91PS_PhyOps) & AT91S_Dm9161Ops;
  314. }
  315. rbf_t *rbfdt;
  316. rbf_t *rbfp;
  317. int eth_init (bd_t * bd)
  318. {
  319. int ret;
  320. int i;
  321. p_mac = AT91C_BASE_EMAC;
  322. *AT91C_PIOA_PDR = AT91C_PA16_EMDIO | AT91C_PA15_EMDC | AT91C_PA14_ERXER | AT91C_PA13_ERX1 | AT91C_PA12_ERX0 | AT91C_PA11_ECRS_ECRSDV | AT91C_PA10_ETX1 | AT91C_PA9_ETX0 | AT91C_PA8_ETXEN | AT91C_PA7_ETXCK_EREFCK; /* PIO Disable Register */
  323. *AT91C_PIOB_PDR = AT91C_PB25_EF100 |
  324. AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV |
  325. AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | AT91C_PB14_ETXER |
  326. AT91C_PB13_ETX3 | AT91C_PB12_ETX2;
  327. *AT91C_PIOB_BSR = AT91C_PB25_EF100 | AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV | AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | AT91C_PB14_ETXER | AT91C_PB13_ETX3 | AT91C_PB12_ETX2; /* Select B Register */
  328. *AT91C_PMC_PCER = 1 << AT91C_ID_EMAC; /* Peripheral Clock Enable Register */
  329. p_mac->EMAC_CFG |= AT91C_EMAC_CSR; /* Clear statistics */
  330. /* Init Ehternet buffers */
  331. rbfdt = (rbf_t *) RBF_FRAMEBTD;
  332. for (i = 0; i < RBF_FRAMEMAX; i++) {
  333. rbfdt[i].addr = RBF_FRAMEBUF + RBF_FRAMELEN * i;
  334. rbfdt[i].size = 0;
  335. }
  336. rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP;
  337. rbfp = &rbfdt[0];
  338. at91rm92000_GetPhyInterface ();
  339. if (!pPhyOps->IsPhyConnected (p_mac))
  340. printf ("PHY not connected!!\n\r");
  341. /* MII management start from here */
  342. if (!(p_mac->EMAC_SR & AT91C_EMAC_LINK)) {
  343. if (!(ret = pPhyOps->Init (p_mac))) {
  344. printf ("MAC: error during MII initialization\n");
  345. return 0;
  346. }
  347. } else {
  348. printf ("No link\n\r");
  349. return 0;
  350. }
  351. p_mac->EMAC_SA2L = (bd->bi_enetaddr[3] << 24) | (bd->bi_enetaddr[2] << 16)
  352. | (bd->bi_enetaddr[1] << 8) | (bd->bi_enetaddr[0]);
  353. p_mac->EMAC_SA2H = (bd->bi_enetaddr[5] << 8) | (bd->bi_enetaddr[4]);
  354. p_mac->EMAC_RBQP = (long) (&rbfdt[0]);
  355. p_mac->EMAC_RSR &= ~(AT91C_EMAC_RSR_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
  356. p_mac->EMAC_CFG = (p_mac->EMAC_CFG | AT91C_EMAC_CAF | AT91C_EMAC_NBC)
  357. & ~AT91C_EMAC_CLK;
  358. #ifdef CONFIG_AT91C_USE_RMII
  359. p_mac->EMAC_CFG |= AT91C_EMAC_RMII;
  360. #endif
  361. p_mac->EMAC_CTL |= AT91C_EMAC_TE | AT91C_EMAC_RE;
  362. return 0;
  363. }
  364. int eth_send (volatile void *packet, int length)
  365. {
  366. while (!(p_mac->EMAC_TSR & AT91C_EMAC_BNQ));
  367. p_mac->EMAC_TAR = (long) packet;
  368. p_mac->EMAC_TCR = length;
  369. while (p_mac->EMAC_TCR & 0x7ff);
  370. p_mac->EMAC_TSR |= AT91C_EMAC_COMP;
  371. return 0;
  372. }
  373. int eth_rx (void)
  374. {
  375. int size;
  376. if (!(rbfp->addr & RBF_OWNER))
  377. return 0;
  378. size = rbfp->size & RBF_SIZE;
  379. NetReceive ((volatile uchar *) (rbfp->addr & RBF_ADDR), size);
  380. rbfp->addr &= ~RBF_OWNER;
  381. if (rbfp->addr & RBF_WRAP)
  382. rbfp = &rbfdt[0];
  383. else
  384. rbfp++;
  385. p_mac->EMAC_RSR |= AT91C_EMAC_REC;
  386. return size;
  387. }
  388. void eth_halt (void)
  389. {
  390. };
  391. #if (CONFIG_COMMANDS & CFG_CMD_MII)
  392. int miiphy_read(unsigned char addr, unsigned char reg, unsigned short * value)
  393. {
  394. at91rm9200_EmacEnableMDIO (p_mac);
  395. at91rm9200_EmacReadPhy (p_mac, reg, value);
  396. at91rm9200_EmacDisableMDIO (p_mac);
  397. return 0;
  398. }
  399. int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
  400. {
  401. at91rm9200_EmacEnableMDIO (p_mac);
  402. at91rm9200_EmacWritePhy (p_mac, reg, &value);
  403. at91rm9200_EmacDisableMDIO (p_mac);
  404. return 0;
  405. }
  406. #endif /* CONFIG_COMMANDS & CFG_CMD_MII */
  407. #endif /* CONFIG_COMMANDS & CFG_CMD_NET */
  408. #endif /* CONFIG_DRIVER_ETHER */