ag71xx.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. /*
  2. * Atheros AR71xx built-in ethernet mac driver
  3. *
  4. * Copyright (C) 2010 Michael Kurz <michi.kurz@googlemail.com>
  5. * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  6. * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  7. *
  8. * Based on Atheros' AG7100 driver
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License version 2 as published
  12. * by the Free Software Foundation.
  13. */
  14. #include <common.h>
  15. #include <malloc.h>
  16. #include <net.h>
  17. #include <miiphy.h>
  18. #include <asm/ar71xx.h>
  19. #include "ag71xx.h"
  20. #ifdef AG71XX_DEBUG
  21. #define DBG(fmt,args...) printf(fmt ,##args)
  22. #else
  23. #define DBG(fmt,args...)
  24. #endif
  25. static struct ag71xx agtable[] = {
  26. {
  27. .mac_base = KSEG1ADDR(AR71XX_GE0_BASE),
  28. .mii_ctrl = KSEG1ADDR(AR71XX_MII_BASE + MII_REG_MII0_CTRL),
  29. .mii_if = CONFIG_AG71XX_MII0_IIF,
  30. } , {
  31. .mac_base = KSEG1ADDR(AR71XX_GE1_BASE),
  32. .mii_ctrl = KSEG1ADDR(AR71XX_MII_BASE + MII_REG_MII1_CTRL),
  33. .mii_if = CONFIG_AG71XX_MII1_IIF,
  34. }
  35. };
  36. static int ag71xx_ring_alloc(struct ag71xx_ring *ring, unsigned int size)
  37. {
  38. int err;
  39. int i;
  40. int rsize;
  41. ring->desc_size = sizeof(struct ag71xx_desc);
  42. if (ring->desc_size % (CONFIG_SYS_CACHELINE_SIZE)) {
  43. rsize = roundup(ring->desc_size, CONFIG_SYS_CACHELINE_SIZE);
  44. DBG("ag71xx: ring %p, desc size %u rounded to %u\n",
  45. ring, ring->desc_size,
  46. rsize);
  47. ring->desc_size = rsize;
  48. }
  49. ring->descs_cpu = (u8 *) malloc((size * ring->desc_size)
  50. + CONFIG_SYS_CACHELINE_SIZE - 1);
  51. if (!ring->descs_cpu) {
  52. err = -1;
  53. goto err;
  54. }
  55. ring->descs_cpu = (u8 *) UNCACHED_SDRAM((((u32) ring->descs_cpu +
  56. CONFIG_SYS_CACHELINE_SIZE - 1) & ~(CONFIG_SYS_CACHELINE_SIZE - 1)));
  57. ring->descs_dma = (u8 *) virt_to_phys(ring->descs_cpu);
  58. ring->size = size;
  59. ring->buf = malloc(size * sizeof(*ring->buf));
  60. if (!ring->buf) {
  61. err = -1;
  62. goto err;
  63. }
  64. memset(ring->buf, 0, size * sizeof(*ring->buf));
  65. for (i = 0; i < size; i++) {
  66. ring->buf[i].desc =
  67. (struct ag71xx_desc *)&ring->descs_cpu[i * ring->desc_size];
  68. DBG("ag71xx: ring %p, desc %d at %p\n",
  69. ring, i, ring->buf[i].desc);
  70. }
  71. flush_cache( (u32) ring->buf, size * sizeof(*ring->buf));
  72. return 0;
  73. err:
  74. return err;
  75. }
  76. static void ag71xx_ring_tx_init(struct ag71xx *ag)
  77. {
  78. struct ag71xx_ring *ring = &ag->tx_ring;
  79. int i;
  80. for (i = 0; i < AG71XX_TX_RING_SIZE; i++) {
  81. ring->buf[i].desc->next = (u32) virt_to_phys((ring->descs_dma +
  82. ring->desc_size * ((i + 1) % AG71XX_TX_RING_SIZE)));
  83. ring->buf[i].desc->ctrl = DESC_EMPTY;
  84. ring->buf[i].skb = NULL;
  85. }
  86. ring->curr = 0;
  87. }
  88. static void ag71xx_ring_rx_clean(struct ag71xx *ag)
  89. {
  90. struct ag71xx_ring *ring = &ag->rx_ring;
  91. int i;
  92. if (!ring->buf)
  93. return;
  94. for (i = 0; i < AG71XX_RX_RING_SIZE; i++) {
  95. ring->buf[i].desc->data = (u32) virt_to_phys(NetRxPackets[i]);
  96. flush_cache((u32) NetRxPackets[i], PKTSIZE_ALIGN);
  97. ring->buf[i].desc->ctrl = DESC_EMPTY;
  98. }
  99. ring->curr = 0;
  100. }
  101. static int ag71xx_ring_rx_init(struct ag71xx *ag)
  102. {
  103. struct ag71xx_ring *ring = &ag->rx_ring;
  104. unsigned int i;
  105. for (i = 0; i < AG71XX_RX_RING_SIZE; i++) {
  106. ring->buf[i].desc->next = (u32) virt_to_phys((ring->descs_dma +
  107. ring->desc_size * ((i + 1) % AG71XX_RX_RING_SIZE)));
  108. DBG("ag71xx: RX desc at %p, next is %08x\n",
  109. ring->buf[i].desc,
  110. ring->buf[i].desc->next);
  111. }
  112. for (i = 0; i < AG71XX_RX_RING_SIZE; i++) {
  113. ring->buf[i].desc->data = (u32) virt_to_phys(NetRxPackets[i]);
  114. ring->buf[i].desc->ctrl = DESC_EMPTY;
  115. }
  116. ring->curr = 0;
  117. return 0;
  118. }
  119. static int ag71xx_rings_init(struct ag71xx *ag)
  120. {
  121. int ret;
  122. ret = ag71xx_ring_alloc(&ag->tx_ring, AG71XX_TX_RING_SIZE);
  123. if (ret)
  124. return ret;
  125. ag71xx_ring_tx_init(ag);
  126. ret = ag71xx_ring_alloc(&ag->rx_ring, AG71XX_RX_RING_SIZE);
  127. if (ret)
  128. return ret;
  129. ret = ag71xx_ring_rx_init(ag);
  130. return ret;
  131. }
  132. static void ar71xx_set_pll(u32 cfg_reg, u32 pll_reg, u32 pll_val, u32 shift)
  133. {
  134. uint32_t base = KSEG1ADDR(AR71XX_PLL_BASE);
  135. u32 t;
  136. t = readl(base + cfg_reg);
  137. t &= ~(3 << shift);
  138. t |= (2 << shift);
  139. writel(t, base + cfg_reg);
  140. udelay(100);
  141. writel(pll_val, base + pll_reg);
  142. t |= (3 << shift);
  143. writel(t, base + cfg_reg);
  144. udelay(100);
  145. t &= ~(3 << shift);
  146. writel(t, base + cfg_reg);
  147. udelay(100);
  148. debug("ar71xx: pll_reg %#x: %#x\n", (unsigned int)(base + pll_reg),
  149. readl(base + pll_reg));
  150. }
  151. static void ar91xx_set_pll_ge0(int speed)
  152. {
  153. //u32 val = ar71xx_get_eth_pll(0, speed);
  154. u32 pll_val;
  155. switch (speed) {
  156. case SPEED_10:
  157. pll_val = 0x00441099;
  158. break;
  159. case SPEED_100:
  160. pll_val = 0x13000a44;
  161. break;
  162. case SPEED_1000:
  163. pll_val = 0x1a000000;
  164. break;
  165. default:
  166. BUG();
  167. }
  168. ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH0_INT_CLOCK,
  169. pll_val, AR91XX_ETH0_PLL_SHIFT);
  170. }
  171. static void ar91xx_set_pll_ge1(int speed)
  172. {
  173. //u32 val = ar71xx_get_eth_pll(1, speed);
  174. u32 pll_val;
  175. switch (speed) {
  176. case SPEED_10:
  177. pll_val = 0x00441099;
  178. break;
  179. case SPEED_100:
  180. pll_val = 0x13000a44;
  181. break;
  182. case SPEED_1000:
  183. pll_val = 0x1a000000;
  184. break;
  185. default:
  186. BUG();
  187. }
  188. ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH1_INT_CLOCK,
  189. pll_val, AR91XX_ETH1_PLL_SHIFT);
  190. }
  191. static void ag71xx_hw_set_macaddr(struct ag71xx *ag, unsigned char *mac)
  192. {
  193. u32 t;
  194. t = (((u32) mac[5]) << 24) | (((u32) mac[4]) << 16)
  195. | (((u32) mac[3]) << 8) | ((u32) mac[2]);
  196. ag71xx_wr(ag, AG71XX_REG_MAC_ADDR1, t);
  197. t = (((u32) mac[1]) << 24) | (((u32) mac[0]) << 16);
  198. ag71xx_wr(ag, AG71XX_REG_MAC_ADDR2, t);
  199. }
  200. static void ag71xx_dma_reset(struct ag71xx *ag)
  201. {
  202. u32 val;
  203. int i;
  204. DBG("%s: txdesc reg: 0x%08x rxdesc reg: 0x%08x\n",
  205. ag->dev->name,
  206. ag71xx_rr(ag, AG71XX_REG_TX_DESC),
  207. ag71xx_rr(ag, AG71XX_REG_RX_DESC));
  208. /* stop RX and TX */
  209. ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0);
  210. ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0);
  211. /* clear descriptor addresses */
  212. ag71xx_wr(ag, AG71XX_REG_TX_DESC, 0);
  213. ag71xx_wr(ag, AG71XX_REG_RX_DESC, 0);
  214. /* clear pending RX/TX interrupts */
  215. for (i = 0; i < 256; i++) {
  216. ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_PR);
  217. ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS);
  218. }
  219. /* clear pending errors */
  220. ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_BE | RX_STATUS_OF);
  221. ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_BE | TX_STATUS_UR);
  222. val = ag71xx_rr(ag, AG71XX_REG_RX_STATUS);
  223. if (val)
  224. printf("%s: unable to clear DMA Rx status: %08x\n",
  225. ag->dev->name, val);
  226. val = ag71xx_rr(ag, AG71XX_REG_TX_STATUS);
  227. /* mask out reserved bits */
  228. val &= ~0xff000000;
  229. if (val)
  230. printf("%s: unable to clear DMA Tx status: %08x\n",
  231. ag->dev->name, val);
  232. }
  233. static void ag71xx_halt(struct eth_device *dev)
  234. {
  235. struct ag71xx *ag = (struct ag71xx *) dev->priv;
  236. /* stop RX engine */
  237. ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0);
  238. ag71xx_dma_reset(ag);
  239. }
  240. #define MAX_WAIT 1000
  241. static int ag71xx_send(struct eth_device *dev, volatile void *packet,
  242. int length)
  243. {
  244. struct ag71xx *ag = (struct ag71xx *) dev->priv;
  245. struct ag71xx_ring *ring = &ag->tx_ring;
  246. struct ag71xx_desc *desc;
  247. int i;
  248. i = ring->curr % AG71XX_TX_RING_SIZE;
  249. desc = ring->buf[i].desc;
  250. if (!ag71xx_desc_empty(desc)) {
  251. printf("%s: tx buffer full\n", ag->dev->name);
  252. return 1;
  253. }
  254. flush_cache((u32) packet, length);
  255. desc->data = (u32) virt_to_phys(packet);
  256. desc->ctrl = (length & DESC_PKTLEN_M);
  257. DBG("%s: sending %#08x length %#08x\n",
  258. ag->dev->name, desc->data, desc->ctrl);
  259. ring->curr++;
  260. if (ring->curr >= AG71XX_TX_RING_SIZE){
  261. ring->curr = 0;
  262. }
  263. /* enable TX engine */
  264. ag71xx_wr(ag, AG71XX_REG_TX_CTRL, TX_CTRL_TXE);
  265. for (i = 0; i < MAX_WAIT; i++)
  266. {
  267. if (ag71xx_desc_empty(desc))
  268. break;
  269. udelay(10);
  270. }
  271. if (i == MAX_WAIT) {
  272. printf("%s: tx timed out!\n", ag->dev->name);
  273. return -1;
  274. }
  275. /* disable TX engine */
  276. ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0);
  277. desc->data = 0;
  278. desc->ctrl = DESC_EMPTY;
  279. return 0;
  280. }
  281. static int ag71xx_recv(struct eth_device *dev)
  282. {
  283. struct ag71xx *ag = (struct ag71xx *) dev->priv;
  284. struct ag71xx_ring *ring = &ag->rx_ring;
  285. for (;;) {
  286. unsigned int i = ring->curr % AG71XX_RX_RING_SIZE;
  287. struct ag71xx_desc *desc = ring->buf[i].desc;
  288. int pktlen;
  289. if (ag71xx_desc_empty(desc))
  290. break;
  291. DBG("%s: rx packets, curr=%u\n", dev->name, ring->curr);
  292. pktlen = ag71xx_desc_pktlen(desc);
  293. pktlen -= ETH_FCS_LEN;
  294. NetReceive(NetRxPackets[i] , pktlen);
  295. flush_cache( (u32) NetRxPackets[i], PKTSIZE_ALIGN);
  296. ring->buf[i].desc->ctrl = DESC_EMPTY;
  297. ring->curr++;
  298. if (ring->curr >= AG71XX_RX_RING_SIZE){
  299. ring->curr = 0;
  300. }
  301. }
  302. if ((ag71xx_rr(ag, AG71XX_REG_RX_CTRL) & RX_CTRL_RXE) == 0) {
  303. /* start RX engine */
  304. ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE);
  305. }
  306. return 0;
  307. }
  308. #ifdef AG71XX_DEBUG
  309. static char *ag71xx_speed_str(struct ag71xx *ag)
  310. {
  311. switch (ag->speed) {
  312. case SPEED_1000:
  313. return "1000";
  314. case SPEED_100:
  315. return "100";
  316. case SPEED_10:
  317. return "10";
  318. }
  319. return "?";
  320. }
  321. #endif
  322. void ag71xx_link_adjust(struct ag71xx *ag)
  323. {
  324. u32 cfg2;
  325. u32 ifctl;
  326. u32 fifo5;
  327. u32 mii_speed;
  328. if (!ag->link) {
  329. DBG("%s: link down\n", ag->dev->name);
  330. return;
  331. }
  332. cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2);
  333. cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX);
  334. cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0;
  335. ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL);
  336. ifctl &= ~(MAC_IFCTL_SPEED);
  337. fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5);
  338. fifo5 &= ~FIFO_CFG5_BM;
  339. switch (ag->speed) {
  340. case SPEED_1000:
  341. mii_speed = MII_CTRL_SPEED_1000;
  342. cfg2 |= MAC_CFG2_IF_1000;
  343. fifo5 |= FIFO_CFG5_BM;
  344. break;
  345. case SPEED_100:
  346. mii_speed = MII_CTRL_SPEED_100;
  347. cfg2 |= MAC_CFG2_IF_10_100;
  348. ifctl |= MAC_IFCTL_SPEED;
  349. break;
  350. case SPEED_10:
  351. mii_speed = MII_CTRL_SPEED_10;
  352. cfg2 |= MAC_CFG2_IF_10_100;
  353. break;
  354. default:
  355. BUG();
  356. return;
  357. }
  358. ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x00780fff);
  359. if (ag->macNum == 0)
  360. ar91xx_set_pll_ge0(ag->speed);
  361. else
  362. ar91xx_set_pll_ge1(ag->speed);
  363. ag71xx_mii_ctrl_set_speed(ag, mii_speed);
  364. ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2);
  365. ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5);
  366. ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl);
  367. DBG("%s: link up (%sMbps/%s duplex)\n",
  368. ag->dev->name,
  369. ag71xx_speed_str(ag),
  370. (1 == ag->duplex) ? "Full" : "Half");
  371. DBG("%s: fifo_cfg0=%#x, fifo_cfg1=%#x, fifo_cfg2=%#x\n",
  372. ag->dev->name,
  373. ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0),
  374. ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1),
  375. ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2));
  376. DBG("%s: fifo_cfg3=%#x, fifo_cfg4=%#x, fifo_cfg5=%#x\n",
  377. ag->dev->name,
  378. ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3),
  379. ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4),
  380. ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5));
  381. DBG("%s: mac_cfg2=%#x, mac_ifctl=%#x, mii_ctrl=%#x\n",
  382. ag->dev->name,
  383. ag71xx_rr(ag, AG71XX_REG_MAC_CFG2),
  384. ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL),
  385. ag71xx_mii_ctrl_rr(ag));
  386. }
  387. #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
  388. static int ag71xx_getMiiSpeed(struct ag71xx *ag)
  389. {
  390. uint16_t phyreg, cap;
  391. if (miiphy_read(ag->phyname, ag->phyid,
  392. PHY_BMSR, &phyreg)) {
  393. puts("PHY_BMSR read failed, assuming no link\n");
  394. return -1;
  395. }
  396. if ((phyreg & PHY_BMSR_LS) == 0) {
  397. return -1;
  398. }
  399. if (miiphy_read(ag->phyname, ag->phyid,
  400. PHY_1000BTSR, &phyreg))
  401. return -1;
  402. if (phyreg & PHY_1000BTSR_1000FD) {
  403. ag->speed = SPEED_1000;
  404. ag->duplex = 1;
  405. } else if (phyreg & PHY_1000BTSR_1000HD) {
  406. ag->speed = SPEED_1000;
  407. ag->duplex = 0;
  408. } else {
  409. if (miiphy_read(ag->phyname, ag->phyid,
  410. PHY_ANAR, &cap))
  411. return -1;
  412. if (miiphy_read(ag->phyname, ag->phyid,
  413. PHY_ANLPAR, &phyreg))
  414. return -1;
  415. cap &= phyreg;
  416. if (cap & PHY_ANLPAR_TXFD) {
  417. ag->speed = SPEED_100;
  418. ag->duplex = 1;
  419. } else if (cap & PHY_ANLPAR_TX) {
  420. ag->speed = SPEED_100;
  421. ag->duplex = 0;
  422. } else if (cap & PHY_ANLPAR_10FD) {
  423. ag->speed = SPEED_10;
  424. ag->duplex = 1;
  425. } else {
  426. ag->speed = SPEED_10;
  427. ag->duplex = 0;
  428. }
  429. }
  430. ag->link = 1;
  431. return 0;
  432. }
  433. #endif
  434. static int ag71xx_hw_start(struct eth_device *dev, bd_t * bd)
  435. {
  436. struct ag71xx *ag = (struct ag71xx *) dev->priv;
  437. ag71xx_dma_reset(ag);
  438. ag71xx_ring_rx_clean(ag);
  439. ag71xx_ring_tx_init(ag);
  440. ag71xx_wr(ag, AG71XX_REG_TX_DESC,
  441. (u32) virt_to_phys(ag->tx_ring.descs_dma));
  442. ag71xx_wr(ag, AG71XX_REG_RX_DESC,
  443. (u32) virt_to_phys(ag->rx_ring.descs_dma));
  444. ag71xx_hw_set_macaddr(ag, ag->dev->enetaddr);
  445. if (ag->phyfixed) {
  446. ag->link = 1;
  447. ag->duplex = 1;
  448. ag->speed = SPEED_1000;
  449. } else {
  450. #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
  451. if (ag71xx_getMiiSpeed(ag))
  452. return -1;
  453. #else
  454. /* only fixed, without mii */
  455. return -1;
  456. #endif
  457. }
  458. ag71xx_link_adjust(ag);
  459. DBG("%s: txdesc reg: %#08x rxdesc reg: %#08x\n",
  460. ag->dev->name,
  461. ag71xx_rr(ag, AG71XX_REG_TX_DESC),
  462. ag71xx_rr(ag, AG71XX_REG_RX_DESC));
  463. /* start RX engine */
  464. ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE);
  465. return 0;
  466. }
  467. #define FIFO_CFG0_INIT (FIFO_CFG0_ALL << FIFO_CFG0_ENABLE_SHIFT)
  468. #define FIFO_CFG4_INIT (FIFO_CFG4_DE | FIFO_CFG4_DV | FIFO_CFG4_FC | \
  469. FIFO_CFG4_CE | FIFO_CFG4_CR | FIFO_CFG4_LM | \
  470. FIFO_CFG4_LO | FIFO_CFG4_OK | FIFO_CFG4_MC | \
  471. FIFO_CFG4_BC | FIFO_CFG4_DR | FIFO_CFG4_LE | \
  472. FIFO_CFG4_CF | FIFO_CFG4_PF | FIFO_CFG4_UO | \
  473. FIFO_CFG4_VT)
  474. #define FIFO_CFG5_INIT (FIFO_CFG5_DE | FIFO_CFG5_DV | FIFO_CFG5_FC | \
  475. FIFO_CFG5_CE | FIFO_CFG5_LO | FIFO_CFG5_OK | \
  476. FIFO_CFG5_MC | FIFO_CFG5_BC | FIFO_CFG5_DR | \
  477. FIFO_CFG5_CF | FIFO_CFG5_PF | FIFO_CFG5_VT | \
  478. FIFO_CFG5_LE | FIFO_CFG5_FT | FIFO_CFG5_16 | \
  479. FIFO_CFG5_17 | FIFO_CFG5_SF)
  480. static int ag71xx_hw_init(struct ag71xx *ag)
  481. {
  482. int ret = 0;
  483. uint32_t reg;
  484. uint32_t mask, mii_type;
  485. if (ag->macNum == 0) {
  486. mask = (RESET_MODULE_GE0_MAC | RESET_MODULE_GE0_PHY);
  487. mii_type = 0x13;
  488. } else {
  489. mask = (RESET_MODULE_GE1_MAC | RESET_MODULE_GE1_PHY);
  490. mii_type = 0x11;
  491. }
  492. // mac soft reset
  493. ag71xx_sb(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_SR);
  494. udelay(20);
  495. // device stop
  496. reg = ar71xx_reset_rr(AR91XX_RESET_REG_RESET_MODULE);
  497. ar71xx_reset_wr(AR91XX_RESET_REG_RESET_MODULE, reg | mask);
  498. udelay(100 * 1000);
  499. // device start
  500. reg = ar71xx_reset_rr(AR91XX_RESET_REG_RESET_MODULE);
  501. ar71xx_reset_wr(AR91XX_RESET_REG_RESET_MODULE, reg & ~mask);
  502. udelay(100 * 1000);
  503. /* setup MAC configuration registers */
  504. ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, (MAC_CFG1_RXE | MAC_CFG1_TXE));
  505. ag71xx_sb(ag, AG71XX_REG_MAC_CFG2,
  506. MAC_CFG2_PAD_CRC_EN | MAC_CFG2_LEN_CHECK);
  507. /* setup FIFO configuration register 0 */
  508. ag71xx_wr(ag, AG71XX_REG_FIFO_CFG0, FIFO_CFG0_INIT);
  509. /* setup MII interface type */
  510. ag71xx_mii_ctrl_set_if(ag, ag->mii_if);
  511. /* setup mdio clock divisor */
  512. ag71xx_wr(ag, AG71XX_REG_MII_CFG, MII_CFG_CLK_DIV_20);
  513. /* setup FIFO configuration registers */
  514. ag71xx_sb(ag, AG71XX_REG_FIFO_CFG4, FIFO_CFG4_INIT);
  515. ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0fff0000);
  516. ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x00001fff);
  517. ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, FIFO_CFG5_INIT);
  518. ag71xx_dma_reset(ag);
  519. ret = ag71xx_rings_init(ag);
  520. if (ret)
  521. return -1;
  522. ag71xx_wr(ag, AG71XX_REG_TX_DESC,
  523. (u32) virt_to_phys(ag->tx_ring.descs_dma));
  524. ag71xx_wr(ag, AG71XX_REG_RX_DESC,
  525. (u32) virt_to_phys(ag->rx_ring.descs_dma));
  526. ag71xx_hw_set_macaddr(ag, ag->dev->enetaddr);
  527. return 0;
  528. }
  529. #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
  530. #define AG71XX_MDIO_RETRY 1000
  531. #define AG71XX_MDIO_DELAY 5
  532. static inline struct ag71xx *ag71xx_name2mac(char *devname)
  533. {
  534. if (strcmp(devname, agtable[0].dev->name) == 0)
  535. return &agtable[0];
  536. else if (strcmp(devname, agtable[1].dev->name) == 0)
  537. return &agtable[1];
  538. else
  539. return NULL;
  540. }
  541. static inline void ag71xx_mdio_wr(struct ag71xx *ag, unsigned reg,
  542. u32 value)
  543. {
  544. uint32_t r;
  545. r = ag->mac_base + reg;
  546. writel(value, r);
  547. /* flush write */
  548. (void) readl(r);
  549. }
  550. static inline u32 ag71xx_mdio_rr(struct ag71xx *ag, unsigned reg)
  551. {
  552. return readl(ag->mac_base + reg);
  553. }
  554. static int ag71xx_mdio_read(char *devname, unsigned char addr,
  555. unsigned char reg, unsigned short *val)
  556. {
  557. struct ag71xx *ag = ag71xx_name2mac(devname);
  558. uint16_t regData;
  559. int i;
  560. ag71xx_mdio_wr(ag, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
  561. ag71xx_mdio_wr(ag, AG71XX_REG_MII_ADDR,
  562. ((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff));
  563. ag71xx_mdio_wr(ag, AG71XX_REG_MII_CMD, MII_CMD_READ);
  564. i = AG71XX_MDIO_RETRY;
  565. while (ag71xx_mdio_rr(ag, AG71XX_REG_MII_IND) & MII_IND_BUSY) {
  566. if (i-- == 0) {
  567. printf("%s: mii_read timed out\n",
  568. ag->dev->name);
  569. return -1;
  570. }
  571. udelay(AG71XX_MDIO_DELAY);
  572. }
  573. regData = (uint16_t) ag71xx_mdio_rr(ag, AG71XX_REG_MII_STATUS) & 0xffff;
  574. ag71xx_mdio_wr(ag, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
  575. DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr, reg, regData);
  576. if (val)
  577. *val = regData;
  578. return 0;
  579. }
  580. static int ag71xx_mdio_write(char *devname, unsigned char addr,
  581. unsigned char reg, unsigned short val)
  582. {
  583. struct ag71xx *ag = ag71xx_name2mac(devname);
  584. int i;
  585. if (ag == NULL)
  586. return 1;
  587. DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr, reg, val);
  588. ag71xx_mdio_wr(ag, AG71XX_REG_MII_ADDR,
  589. ((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff));
  590. ag71xx_mdio_wr(ag, AG71XX_REG_MII_CTRL, val);
  591. i = AG71XX_MDIO_RETRY;
  592. while (ag71xx_mdio_rr(ag, AG71XX_REG_MII_IND) & MII_IND_BUSY) {
  593. if (i-- == 0) {
  594. printf("%s: mii_write timed out\n",
  595. ag->dev->name);
  596. break;
  597. }
  598. udelay(AG71XX_MDIO_DELAY);
  599. }
  600. return 0;
  601. }
  602. #endif
  603. int ag71xx_register(bd_t * bis, char *phyname[], uint16_t phyid[], uint16_t phyfixed[])
  604. {
  605. int i, num = 0;
  606. u8 used_ports[MAX_AG71XX_DEVS] = CONFIG_AG71XX_PORTS;
  607. for (i = 0; i < MAX_AG71XX_DEVS; i++) {
  608. /*skip if port is configured not to use */
  609. if (used_ports[i] == 0)
  610. continue;
  611. agtable[i].dev = malloc(sizeof(struct eth_device));
  612. if (agtable[i].dev == NULL) {
  613. puts("malloc failed\n");
  614. return 0;
  615. }
  616. memset(agtable[i].dev, 0, sizeof(struct eth_device));
  617. sprintf(agtable[i].dev->name, "eth%d", i);
  618. agtable[i].dev->iobase = 0;
  619. agtable[i].dev->init = ag71xx_hw_start;
  620. agtable[i].dev->halt = ag71xx_halt;
  621. agtable[i].dev->send = ag71xx_send;
  622. agtable[i].dev->recv = ag71xx_recv;
  623. agtable[i].dev->priv = (void *) (&agtable[i]);
  624. agtable[i].macNum = i;
  625. eth_register(agtable[i].dev);
  626. #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
  627. if ((phyname == NULL) || (phyid == NULL) || (phyfixed == NULL))
  628. return -1;
  629. agtable[i].phyname = strdup(phyname[i]);
  630. agtable[i].phyid = phyid[i];
  631. agtable[i].phyfixed = phyfixed[i];
  632. miiphy_register(agtable[i].dev->name, ag71xx_mdio_read,
  633. ag71xx_mdio_write);
  634. #endif
  635. if (ag71xx_hw_init(&agtable[i]))
  636. continue;
  637. num++;
  638. }
  639. return num;
  640. }